An Oda runtime can serve an out-of-process client over a newline-delimited JSON-RPC connection instead of an interactive chat. This page describes the messages on that connection, so you can read a trace, debug an integration or build a client of your own.
If you are new to the family, start with the Oda SDK overview.
Your program owns the connection. The runtime reads requests on its standard input and writes messages back on its standard output.
\n.id and a method. Request ids look like req_ followed by a UUID.id and no method. It carries the id of the request it answers.method and no id.Standard output carries protocol frames only. Keep anything else off that stream.
initializeSets up the connection and resolves the model route.
cwd), the provider and model route, an optional reasoningEffort and an optional maxTokens.reasoningEffort must be a non-empty string: initialize reasoningEffort must be a non-empty string. When you leave it out, the model's default effort applies.maxTokens must be a positive safe integer: initialize maxTokens must be a positive safe integer. Zero, negative values, fractions and oversized values are refused.no adapter registered for provider "<p>"; a route that cannot be resolved does not fall back to a default.session/ prompt is refused until one initialize has completed.session/ promptQueues one user message and returns a receipt right away.
sessionId that is new to the runtime starts that session.{ "messageId": ". . . " }. The message id does not identify a later assistant message, a turn ending, or the result of that prompt.image/ png, image/ jpeg, image/ webp and image/ gif, in a block like this:{ "type": "image", "mimeType": "image/png", "data": "..." }shutdownFlushes what the runtime has written, winds its work down and exits. The reply carries an empty result.
Notifications travel from the runtime to your client.
session. event streams a session's events as they are appended.session. status reports the whole agent as running or idle.subagent. started announces a sub-agent session and links it to its parent.subagent. finished reports a sub-agent run that executed in the same process, with a status of ok or error. When the sub-agent produced no reply, its last assistant message is left out instead of sent empty.initialize with the working folder and the model route you want. The result confirms the route; a route that cannot be resolved fails here.session/ prompt and keep the messageId from the receipt.session. event streams the session's events, session. status reports work as running, and sub-agent runs announce themselves with subagent. started.session. status to report idle: the turn has settled. The last committed assistant message of the session is the run's final text, and it is not assigned to one prompt.shutdown to end the connection.The client tells the run's own session events apart from its wider tree by following the lineage in subagent.. A turn end carries a reason envelope; when a turn is aborted, the reason names the kind (user, parent, disposed, legacy or hook), and a hook abort carries its reason string.
-32601: no registered handler. The answer reads method not found: <m>.-32603: a handler failure. The answer carries the handler's error message.JSON-RPC transport closed and JSON-RPC input closed: the connection is closed, and pending requests fail.JSON-RPC request aborted: <reason>: the request was aborted. Its pending state is dropped; nothing is retained for a response that may never come.JSON-RPC error: the fallback text for a failure that carries no other message.For the client side of the SDK, see the TypeScript client guide. To serve clients from a runtime, see Run an Oda runtime server.
No. There is no cancel method and no per-session close. A turn runs until the agent reports idle, and shutdown ends the connection itself.
Not at the connection level. session/ returns only the enqueue receipt, and its messageId does not identify a later assistant message, a turn ending or the prompt's result. Read the stream until the agent is idle.
initialize before prompting?Yes. session/ is refused until one initialize has completed, and the handshake is where the model route is resolved. A route problem fails the handshake instead of the prompt.
No. The handshake result reports the server's identity, but there is no version negotiation; a client must be built for the same version as the runtime it drives.
Its pending state is dropped, so nothing is retained for a response that may never come. The rejection names the reason: JSON-RPC request aborted: <reason>.
Inline images with image/, image/, image/ or image/. Each inline image becomes a durable reference in the session before the prompt is enqueued.
It is ignored. A line that does not parse as a JSON-RPC message gets no answer; check that each message is a single line of valid JSON.
By id. Every request carries an id (req_ followed by a UUID) and the response returns the same id. Notifications carry no id.
They fail. A closed input reports JSON-RPC input closed, and a closed transport reports JSON-RPC transport closed; nothing is retried for you.
initialize fail with a missing adapter?The provider you named has no registered adapter, so the route could not be resolved. Check the provider and model you send; a route that cannot be resolved fails the handshake and cannot fall back to a default.