The Oda agent runtime

Behind every chat, DataMind Oda runs a live worker called an agent. The agent drives the chat's loop: it reads the session that records the conversation, builds each model request, runs tool calls and writes results back as they settle. This page describes the runtime itself: how agents are created, resumed and disposed, the states they move through, the operations that drive a conversation, and the options and limits that shape a run. The record an agent works on is described on Sessions and the transcript.

What an agent is

Creating, resuming and disposing agents

  1. Create or resume. Creating an agent returns a handle; resuming returns a handle that continues a stored session, repairing unfinished work first (see Recovering sessions after a crash).
  2. Drive. The handle carries the operations described below, and work appends to the session as it settles.
  3. Dispose. Disposing stops the loop, unregisters the agent, removes the session and unwinds the scope. Only the holder of the handle can dispose the agent.

Agents declared in configuration

Agents can also be declared in the profile the runtime loads, and declared agents start by themselves when it loads. Each declares:

FieldWhat it sets
id (required)The agent's label, and the base of its session id.
provider and modelThe model route; both are needed before a request can be built.
reasoningEffortOptional; a whole number of at least 1.
maxTokensOptional token cap; a positive safe integer.
cwdThe folder the agent works in; an absolute path.
sessionIdPins the session id.
resumeSessionIdResumes a stored session by id; cannot be combined with sessionId.

Driving a conversation

A handle drives the conversation through a small set of operations. They differ in where what they carry goes and whether the agent wakes for it.

How these appear in the app is on Prompts, queue and steering; what a stop leaves behind is on Stopping Oda and queued messages.

Status and faults

Options and live changes

Known limits

How agents are kept apart

Questions, answered

What is the difference between a chat and an agent?

A chat is what you see: its history, its name and its place in the sidebar. Under it sit a session, the stored record, and an agent, the live worker that acts on it. This page is about the worker; the record is described on Sessions and the transcript.

What happens when I dispose an agent?

The agent's loop stops, the agent unregisters, the session is removed and the scope unwinds, taking everything registered under the agent with it. Only the holder of the handle can dispose it, and a turn that was running is closed as aborted with disposed as its cause.

Can two agents share the same id or session?

No. A second agent cannot join under an id that is in use (agent "<id>" is already registered), and two declared agents cannot resolve to the same exact session identity (agents "<first>" and "<second>" use duplicate exact session identity "<id>").

Why did an agent fail with no provider or model?

It reached a model request with no route: no provider and model were set for it, and none were supplied while the request was built. The refusal says what to set: agent "<id>" has no provider/model: set AgentOptions.provider and AgentOptions.model or supply both via the agent/request waterfall.

What session id does a declared agent get?

Without sessionId or resumeSessionId, every startup mints a fresh id of the form <id>-session-<uuid>. sessionId pins one identity for the agent instead, and resumeSessionId resumes a stored session by id; the two cannot be combined (sessionId and resumeSessionId are mutually exclusive).

What statuses can an agent be in?

Two: idle and running. Maintenance presents as idle, and a change is reported only when it happens: the same status is never reported twice in a row.

Can settings change while an agent runs?

Yes. A running loop accepts a live update, such as the parallel tool-call cap, and keeps the same loop and the agents already composed. A value it cannot take is refused, and the previous value stays in force. The declared agent list is the exception: it is read at startup.

What is the difference between steering and injecting?

A steer joins the turn that is running and is taken at its next step, so the turn continues. An inject stages context without opening a turn: the agent stays idle, and the context goes with a later request.

What happens if a listener throws?

The failure is logged and contained: it cannot stop the loop or starve the other listeners. A registration that fails is rolled back, so nothing half-applied stays behind.

Does an agent stop on its own after some number of turns?

No. There is no built-in turn budget: the loop keeps going until the work ends, is stopped, or fails.

Do agents share what they register with each other?

No. Tools and prompt sections registered through one agent belong to that agent and are removed with it. Scopes pass definitions down, with the nearest one winning, and events up; a chain cannot loop, and a scope is not a security boundary.