The Oda SDK client is the TypeScript package that starts an Oda runtime and drives its turns from your own program, so a script or an internal tool of yours can call DataMind Oda. The family starts with Oda SDK overview; the raw JSON-RPC messages are in SDK wire protocol.
maxTokens. The runtime checks that exact route before it accepts a prompt: a provider, model or effort it cannot serve fails the handshake instead of falling back to a default.The opposite role, a process that serves SDK clients instead of driving one, is described in Run an Oda runtime server.
Timeouts are in milliseconds.
| Option | Default | What it does |
|---|---|---|
initializeTimeoutMs | 10000 | How long the client waits for the start-up handshake. |
requestTimeoutMs | none | With no value, requests wait indefinitely, because a turn can legitimately run long. |
shutdownTimeoutMs | 1000 | How long the shutdown request may take before the client moves on. |
disposeEofGraceMs | 6000 | How long the runtime may take to finish after its input closes. |
disposeGraceMs | 3000 | How long it may take to exit after the client sends a stop signal. |
env: when you pass it, it replaces the environment completely for the runtime. The client reads it at the moment the runtime starts.Because env replaces the environment rather than adding to it, list every variable the runtime needs when you use it.
maxTokens: optional. It caps each request the root agent makes, and sub-agents that run in the same process inherit the cap.reasoningEffort: optional. An omitted effort keeps the model's own default.provider and model: the route the client asks for. When you leave them out, the client sends its built-in default route.run() with your prompt. The first call also starts the runtime.run() returns when the agent next goes idle, and the result separates your session from the wider tree:
sessionId: the session the run worked in.finalResponse: the last committed assistant text of the session.events: the events of your session.notifications: activity from the wider session tree, sub-agents included.finalResponse is not assigned to the prompt you sent: it is the session's last committed assistant text, and it is empty when there is none.JsonRpcResponseError for an error the other side reported (it keeps the wire code, message and data), RequestTimeoutError for a request that passed its timeout, SdkProtocolError for an answer that did not fit the protocol, and TransportClosedError for using the client after it closed or after the runtime is gone.<method> timed out after <ms>ms waiting for <description>; stderr tail: and carries the newest 400 lines of the runtime's error output, so you can see why it stalled.initialize returned no server identity:, session/ prompt returned no message id:, and turn/ end carried no reason envelope:. The detail follows the colon.close(), or let await using call it for you when the block ends.close() stops the runtime in stages: it sends a shutdown request first, then closes the runtime's input, then sends a stop signal on systems other than Windows, and finally forces the process to end. It finishes when the process has exited, and it is safe to call again.close() fails with runtime process did not exit within <ms>ms after SIGKILL was accepted|refused or SIGKILL failed.close() the client starts no new runtime, and using it again fails as closed.close(), anything not delivered yet is dropped.The start-up handshake gets 10 seconds; requests wait indefinitely unless you set requestTimeoutMs; the shutdown request gets 1 second; and the teardown stages get 6 seconds after the input closes and 3 seconds after the stop signal.
Yes, set requestTimeoutMs. Leaving it out is the default, because a turn can legitimately run long. A timeout ends the wait on your side; the runtime is not stopped.
The client resolves the folder before the start-up handshake. An absolute path keeps that resolution final, so the folder cannot be resolved twice.
run() start a new runtime each time?No. The runtime starts on the first call and is kept for later calls. Each run works in a session of its own.
finalResponse the reply to my prompt?Not exactly. It is the last committed assistant text of the session, and it is not assigned to a specific prompt. If the session has not produced an assistant message yet, it is empty.
The client cleans up that attempt and prepares a fresh one, so your next call may succeed. If the cleanup fails too, the client reports both failures as one combined error.
So you can see why the runtime stalled or died. The tail holds the newest 400 lines of the runtime's error output, and the exit code shows how the process ended.
A reader that is open when the runtime dies can still drain what was already delivered, then it fails. After close(), notifications that were not delivered yet are dropped.
Yes. Pass env and the runtime starts with exactly that environment: it replaces the parent environment completely, so include every variable the runtime needs. The client reads it when the runtime starts.
Use close(). It asks the runtime to shut down and escalates in bounded steps until the process has exited, and calling it again is safe. Only a process that will not exit after the force step makes it fail, with a message that names the wait.