My agentic slop goes here. Not intended for anyone else!
1(** SDK Control Protocol for Claude.
2
3 This module defines the typed SDK control protocol for bidirectional
4 communication between the SDK and the Claude CLI. It handles:
5
6 - Permission requests (tool usage authorization)
7 - Hook callbacks (intercepting and modifying tool execution)
8 - Dynamic control (changing settings mid-conversation)
9 - Server introspection (querying capabilities)
10
11 {2 Protocol Overview}
12
13 The SDK control protocol is a JSON-based request/response protocol that
14 runs alongside the main message stream. It enables:
15
16 1. {b Callbacks}: Claude asks the SDK for permission or hook execution
17 2. {b Control}: SDK changes Claude's behavior dynamically
18 3. {b Introspection}: SDK queries server metadata
19
20 {2 Request/Response Flow}
21
22 {v
23 SDK Claude CLI
24 | |
25 |-- Initialize (with hooks) --> |
26 |<-- Permission Request --------| (for tool usage)
27 |-- Allow/Deny Response ------> |
28 | |
29 |<-- Hook Callback -------------| (pre/post tool)
30 |-- Hook Result -------------> |
31 | |
32 |-- Set Model ---------------> | (dynamic control)
33 |<-- Success Response ----------|
34 | |
35 |-- Get Server Info ----------> |
36 |<-- Server Info Response ------|
37 v}
38
39 {2 Usage}
40
41 Most users won't interact with this module directly. The {!Client} module
42 handles the protocol automatically. However, this module is exposed for:
43
44 - Understanding the control protocol
45 - Implementing custom control logic
46 - Debugging control message flow
47 - Advanced SDK extensions
48
49 {2 Dynamic Control Examples}
50
51 See {!Client.set_permission_mode}, {!Client.set_model}, and
52 {!Client.get_server_info} for high-level APIs that use this protocol. *)
53
54open Ezjsonm
55
56(** The log source for SDK control operations *)
57val src : Logs.Src.t
58
59(** {1 Request Types} *)
60
61module Request : sig
62 (** SDK control request types. *)
63
64 type interrupt = {
65 subtype : [`Interrupt];
66 }
67 (** Interrupt request to stop execution. *)
68
69 type permission = {
70 subtype : [`Can_use_tool];
71 tool_name : string;
72 input : value;
73 permission_suggestions : Permissions.Update.t list option;
74 blocked_path : string option;
75 }
76 (** Permission request for tool usage. *)
77
78 type initialize = {
79 subtype : [`Initialize];
80 hooks : (string * value) list option; (* Hook event to configuration *)
81 }
82 (** Initialize request with optional hook configuration. *)
83
84 type set_permission_mode = {
85 subtype : [`Set_permission_mode];
86 mode : Permissions.Mode.t;
87 }
88 (** Request to change permission mode. *)
89
90 type hook_callback = {
91 subtype : [`Hook_callback];
92 callback_id : string;
93 input : value;
94 tool_use_id : string option;
95 }
96 (** Hook callback request. *)
97
98 type mcp_message = {
99 subtype : [`Mcp_message];
100 server_name : string;
101 message : value;
102 }
103 (** MCP server message request. *)
104
105 type set_model = {
106 subtype : [`Set_model];
107 model : string;
108 }
109 (** Request to change the AI model. *)
110
111 type get_server_info = {
112 subtype : [`Get_server_info];
113 }
114 (** Request to get server information. *)
115
116 type t =
117 | Interrupt of interrupt
118 | Permission of permission
119 | Initialize of initialize
120 | Set_permission_mode of set_permission_mode
121 | Hook_callback of hook_callback
122 | Mcp_message of mcp_message
123 | Set_model of set_model
124 | Get_server_info of get_server_info
125 (** The type of SDK control requests. *)
126
127 val interrupt : unit -> t
128 (** [interrupt ()] creates an interrupt request. *)
129
130 val permission :
131 tool_name:string ->
132 input:value ->
133 ?permission_suggestions:Permissions.Update.t list ->
134 ?blocked_path:string ->
135 unit -> t
136 (** [permission ~tool_name ~input ?permission_suggestions ?blocked_path ()]
137 creates a permission request. *)
138
139 val initialize : ?hooks:(string * value) list -> unit -> t
140 (** [initialize ?hooks ()] creates an initialize request. *)
141
142 val set_permission_mode : mode:Permissions.Mode.t -> t
143 (** [set_permission_mode ~mode] creates a permission mode change request. *)
144
145 val hook_callback :
146 callback_id:string ->
147 input:value ->
148 ?tool_use_id:string ->
149 unit -> t
150 (** [hook_callback ~callback_id ~input ?tool_use_id ()] creates a hook callback request. *)
151
152 val mcp_message : server_name:string -> message:value -> t
153 (** [mcp_message ~server_name ~message] creates an MCP message request. *)
154
155 val set_model : model:string -> t
156 (** [set_model ~model] creates a model change request. *)
157
158 val get_server_info : unit -> t
159 (** [get_server_info ()] creates a server info request. *)
160
161 val to_json : t -> value
162 (** [to_json t] converts a request to JSON. *)
163
164 val of_json : value -> t
165 (** [of_json json] parses a request from JSON.
166 @raise Invalid_argument if the JSON is not a valid request. *)
167
168 val pp : Format.formatter -> t -> unit
169 (** [pp fmt t] pretty-prints the request. *)
170end
171
172(** {1 Response Types} *)
173
174module Response : sig
175 (** SDK control response types. *)
176
177 type success = {
178 subtype : [`Success];
179 request_id : string;
180 response : value option;
181 }
182 (** Successful response. *)
183
184 type error = {
185 subtype : [`Error];
186 request_id : string;
187 error : string;
188 }
189 (** Error response. *)
190
191 type t =
192 | Success of success
193 | Error of error
194 (** The type of SDK control responses. *)
195
196 val success : request_id:string -> ?response:value -> unit -> t
197 (** [success ~request_id ?response ()] creates a success response. *)
198
199 val error : request_id:string -> error:string -> t
200 (** [error ~request_id ~error] creates an error response. *)
201
202 val to_json : t -> value
203 (** [to_json t] converts a response to JSON. *)
204
205 val of_json : value -> t
206 (** [of_json json] parses a response from JSON.
207 @raise Invalid_argument if the JSON is not a valid response. *)
208
209 val pp : Format.formatter -> t -> unit
210 (** [pp fmt t] pretty-prints the response. *)
211end
212
213(** {1 Control Messages} *)
214
215type control_request = {
216 type_ : [`Control_request];
217 request_id : string;
218 request : Request.t;
219}
220(** Control request message. *)
221
222type control_response = {
223 type_ : [`Control_response];
224 response : Response.t;
225}
226(** Control response message. *)
227
228type t =
229 | Request of control_request
230 | Response of control_response
231(** The type of SDK control messages. *)
232
233val create_request : request_id:string -> request:Request.t -> t
234(** [create_request ~request_id ~request] creates a control request message. *)
235
236val create_response : response:Response.t -> t
237(** [create_response ~response] creates a control response message. *)
238
239val to_json : t -> value
240(** [to_json t] converts a control message to JSON. *)
241
242val of_json : value -> t
243(** [of_json json] parses a control message from JSON.
244 @raise Invalid_argument if the JSON is not a valid control message. *)
245
246val pp : Format.formatter -> t -> unit
247(** [pp fmt t] pretty-prints the control message. *)
248
249(** {1 Logging} *)
250
251val log_request : Request.t -> unit
252(** [log_request req] logs an SDK control request. *)
253
254val log_response : Response.t -> unit
255(** [log_response resp] logs an SDK control response. *)
256
257(** {1 Server Information}
258
259 Server information provides metadata about the Claude CLI server,
260 including version, capabilities, available commands, and output styles.
261
262 {2 Use Cases}
263
264 - Feature detection: Check if specific capabilities are available
265 - Version compatibility: Ensure minimum version requirements
266 - Debugging: Log server information for troubleshooting
267 - Dynamic adaptation: Adjust SDK behavior based on capabilities
268
269 {2 Example}
270
271 {[
272 let info = Client.get_server_info client in
273 Printf.printf "Claude CLI version: %s\n"
274 (Server_info.version info);
275
276 if List.mem "structured-output" (Server_info.capabilities info) then
277 Printf.printf "Structured output is supported\n"
278 else
279 Printf.printf "Structured output not available\n";
280 ]} *)
281
282module Server_info : sig
283 (** Server information and capabilities. *)
284
285 type t = {
286 version : string;
287 (** Server version string (e.g., "2.0.0") *)
288
289 capabilities : string list;
290 (** Available server capabilities (e.g., "hooks", "structured-output") *)
291
292 commands : string list;
293 (** Available CLI commands *)
294
295 output_styles : string list;
296 (** Supported output formats (e.g., "json", "stream-json") *)
297 }
298 (** Server metadata and capabilities.
299
300 This information is useful for feature detection and debugging. *)
301
302 val create :
303 version:string ->
304 capabilities:string list ->
305 commands:string list ->
306 output_styles:string list ->
307 t
308 (** [create ~version ~capabilities ~commands ~output_styles] creates server info. *)
309
310 val version : t -> string
311 (** [version t] returns the server version. *)
312
313 val capabilities : t -> string list
314 (** [capabilities t] returns the server capabilities. *)
315
316 val commands : t -> string list
317 (** [commands t] returns available commands. *)
318
319 val output_styles : t -> string list
320 (** [output_styles t] returns available output styles. *)
321
322 val of_json : value -> t
323 (** [of_json json] parses server info from JSON.
324 @raise Invalid_argument if the JSON is not valid server info. *)
325
326 val to_json : t -> value
327 (** [to_json t] converts server info to JSON. *)
328
329 val pp : Format.formatter -> t -> unit
330 (** [pp fmt t] pretty-prints the server info. *)
331end