Oda SDK: Python reference
The Oda Python SDK drives DataMind Oda from your own Python program: it starts an Oda runtime as a subprocess and speaks newline-delimited JSON-RPC with it over standard input and output. This page is the reference for the run result, the runtime's lifecycle, the errors you can meet and the wire surface. If you are new to the family, start with the Oda SDK overview; install and a first run are in Oda SDK: Python.
The runtime's lifecycle
- Starting is lazy: the runtime launches the first time a run needs it, and later runs reuse it. One client keeps one runtime until you close it, and a context manager closes it for you when the block ends.
- Every launch needs a non-empty home folder; the SDK never falls back to a default one.
- A run sends your prompt and returns when the session goes
idle. The result describes the interval from the prompt's receipt to that moment.
- At the wire level, a prompt is queued right away and returns the message id of the queued message; that id is a receipt, not the reply.
- Each run works in its own session unless you pass a session id. Reuse a session id, with the same home, only to continue the same conversation and its session-owned resources.
- Closing stops the runtime in stages: a shutdown request with a bounded wait, then the runtime's input closes, then a termination signal if the process is still up, and a forced end as a last resort. Closing before the runtime ever started does nothing, and closing again is safe.
What a run returns
A run returns a RunResult:
| Part | What it holds |
|---|
session_id | The session the run worked in. |
final_response | The text of the last assistant message in the run, with its text blocks joined; an empty string when the run has no assistant message. |
finish_reason | How the last turn ended: a kind such as completed, max-tokens or error, or None when the run has no turn end. |
events | The events of your own session, in the order they arrived. |
notifications | The notifications of your session and of every helper agent below it, in the order they arrived on the wire. |
- The notifications follow the helper-agent tree: the client records the parent-to-child edge from each helper start notification and pairs the matching finish notification with it, so the activity of the whole tree arrives. For what helper agents are, see Subagents.
- Events stay with your session: the final response is built from the session's own text, and a helper agent's output cannot replace it.
When the runtime cannot start
Each failure below stops the launch, and the message names what is wrong.
- Missing runtime package. When the runtime package that matches the SDK is not installed, the launch fails with a message that says the bundled runtime cannot be located and names the package to install.
- No home. A launch without a non-empty home folder is refused; the home can come from the client's configuration or from the environment.
- An incomplete runtime payload. Before the process starts, the runtime package checks its own files and names the first missing part: the runtime executable, the search sidecar, the terminal helper used on macOS, or the Office sidecar and its engine.
- An unsupported system. A system with no runtime build is refused, and the message lists the supported ones: Linux x64 and arm64, macOS x64 and arm64, and Windows x64.
- An unknown runtime mode. A runtime mode the package does not recognise is refused before the process starts.
Errors while it runs
- Not running. Using the client while no runtime is running fails with a transport error whose text says the runtime is not running.
- A failed write. A write to the runtime's input that fails raises a transport error that says the write failed; the runtime's diagnostics come with it.
- A closed stream. A runtime that exits or closes its output fails calls that are waiting with a transport error; the message says the runtime's output closed, or that the runtime closed, and the runtime's diagnostics come with it.
- A timeout. A call that passes its time limit fails with a timeout error that names the method and says it waited for the runtime. The error carries the runtime's exit code, when the process has exited, and the tail of its error output, the newest 400 lines. A start-up timeout also names the profile the launch selected.
- Nothing is retried for you: a failed call raises in your program.
Protocol notes
- Create the client with a configuration object or with keyword options; passing both is refused.
- The launch command carries the runtime, the selected profile and every patch file you pass, in order; each patch path becomes absolute before the runtime starts.
- The start-up handshake carries
cwd, provider, model, and, when you set them, reasoningEffort and maxTokens. The full message set is in SDK wire protocol.
- A line on the runtime's output that is not JSON is ignored, so a stray line from the runtime does not break the client.
- A notification that matches no subscription stays queued in the client instead of being dropped.
- A turn end whose reason is not a string kind fails the run with a protocol error:
turn/end event requires a string data.reason.kind.
Questions, answered
What does a run return?
Five parts: the session id, the final response, the finish reason, your session's events and the notifications for your session and its helper agents. The table above lists each one.
When does a run finish?
When the session goes idle, the moment the whole session has settled. The run covers the interval from your prompt's receipt to that point.
How long does the runtime stay up?
One client keeps one runtime across all of its runs: it starts lazily on the first run and lives until you close the client or leave its context manager. Closing stops it in stages, and closing again is safe.
Which sessions do the notifications cover?
Your session and every helper agent below it, in the order they arrived on the wire. The client follows the tree from the helper start notifications. Events, by contrast, stay limited to your own session.
What happens if the runtime package is not installed?
The launch fails and the error says the bundled runtime cannot be located and names the runtime package to install.
What does the start-up handshake carry?
The working folder (cwd), the provider, the model, and, when you set them, the reasoning effort (reasoningEffort) and the token cap (maxTokens).
What happens to calls that are waiting when the runtime exits?
They fail with a transport error that says the runtime's output closed or that the runtime is closed, and the error carries the runtime's exit code and the tail of its error output. Nothing is retried for you.
Why did a turn end fail with a protocol error?
The runtime sent a turn end whose reason is not a string kind, which the protocol does not allow. The run fails with turn/end event requires a string data.reason.kind. Run the task again; if it repeats, keep the error text for a problem report.
What happens to a notification that nothing is reading?
It stays queued in the client instead of being dropped, so a later reader can pick it up.
Can I pass a configuration object and keyword options together?
No. The client takes one form or the other; passing both is refused.