Client / AsyncClient and Run / AsyncRun.
The async methods are awaited; both share the same handlers and error types.
Client
on_question / on_confirm makes runs interactive; omitting
both runs the agent unattended. Use one client per thread (one per event loop for
AsyncClient).
Callable[[Question], str]
Answer an
ask_user. Passing it declares the elicitation capability. Omit to
run unattended (the agent is never offered questions). Answer within ~2
minutes (Question.expires_in carries the exact window) — after that the
question auto-dismisses, the agent proceeds on its own judgment, and the SDK
stops waiting on your handler. Return a
non-empty string: an empty answer reads as “no answer” and the agent
proceeds immediately — re-prompt your human instead (the app disables its
submit button on empty text for the same reason).Callable[[Confirmation], bool]
Approve or deny a
confirm_action. Omit to auto-resolve (approve safe, decline
dangerous). Undecided for ~2 minutes counts as a decline.float
default:"600.0"
Seconds a single run may take. Expiry cancels the run server-side (nothing
keeps working behind your back) and raises
CosmonTimeoutError. There is no
server-side cap — set it as high as your longest solve.str
Override where the app’s descriptor is read from (defaults to the per-OS path;
or the
COSMON_SDK_DESCRIPTOR environment variable).str
Connect explicitly instead of discovering the app (mainly for tests).
Methods
Run
Start a one-shot agent run; returns a
Run.Session
Open a multi-turn
Session (see below). agent picks the entry agent for the
first turn; ephemeral=True deletes the conversation when the session closes;
id resumes an earlier session’s conversation (a previous session’s .id).DiscoverInfo
Login state, account, available agents, default agent, active model, and
runtime readiness.
list[ChatInfo]
The conversations your scripts left on the server (SDK-owned only — never the
app user’s own chats), newest first. Each
ChatInfo has id (resume with
session(id=...)), title (from the first prompt), and updated_at.None
Disconnect. Done automatically by the context manager.
run() options
str
Target platform agent, e.g.
"solidworks", "abaqus", "fluent". Omit for the default.list[str]
File paths to attach to the prompt (read on the machine running the app).
Relative paths are resolved against your current working directory.
bool
default:"False"
Delete the conversation (transcript + agent history) when the run finishes,
instead of persisting it server-side.
Run
The handle for one run — single-use: iterate it or drain it once.str
Drive the run to completion and return its transcript — the agent’s answer
with each tool step inline as a
▶ <summary> line. live=True also prints
the run while it works (tokens to stdout, steps and [agent] labels to
stderr); the returned string stays the authoritative version. On AsyncRun,
await run.text(). Raises CosmonRunError if the run failed.Iterator[RunEvent]
Stream the run: yields
ToolCall / TextChunk events as they happen (async for
on AsyncRun). Raises CosmonRunError if the run fails mid-stream.Session
A multi-turn conversation over one stable id — open it withclient.session(...).
Every run on it reuses the id, so the runtime resumes the same thread (it
remembers earlier turns). Use it as a context manager so it’s ended on exit.
Run
Run the next turn. The entry
agent is sent only on the first turn; later turns
follow the agent in control (so a handoff carries into the next turn). Returns a
Run — same handle as client.run.str
The session id shared across the conversation’s turns.
None
End the session. The conversation persists server-side and can be picked
up again with
client.session(id=chat.id) — an ephemeral session is deleted
here instead. Idempotent; also called on with-block exit. On AsyncSession,
await chat.close().None
Delete the conversation entirely (transcript + agent history), then end the
session. The explicit destructive act —
close() never deletes. Idempotent.
On AsyncSession, await chat.delete().client.run(...) (no session) leaves its history server-side unless
run with ephemeral=True; SDK runs don’t appear in the app’s chat list.
AsyncClient.session(...) returns an AsyncSession — async with it and
await chat.run(...).text().
Events (RunEvent)
What iterating a run yields. A small discriminated union — isinstance-match it.
pydantic model
The agent invoked a tool.
name: str, summary: str (human-readable),
finished: bool (emitted False on start, True on finish), agent: str —
which agent ran it (a run can span a handoff chain; "" from older apps).
images: tuple[str, ...] — image data: URIs the tool produced for the user
(e.g. a CAD screenshot), carried on the finished=True event; () when the
tool produced none, and from apps that predate the field. See
the Images from tools example.pydantic model
text: str — a piece of the agent’s answer, as it streams; agent: str —
who said it. Concatenate the chunks to rebuild the answer text.Interaction handlers
Passed to the client; called as the agent needs input (the respond side — kept out of the event stream because the agent blocks on the returned value).pydantic model
prompt: str — the question. options: list[str] — the offered choices, or
[] for a free-form answer (custom answers outside the options are fine).
expires_in: float — seconds before the prompt auto-dismisses and the agent
proceeds without you (~120; render it if a human is answering). on_question
returns the chosen/typed string.pydantic model
summary: str — what the agent wants to do. expires_in: float — seconds
before an undecided gate counts as declined (~120). on_confirm returns
True to approve, False to deny.on_confirm, the run is
question-free (the agent is never offered ask_user) while every confirmation
gate reaches your handler; with only on_question, questions reach you while
confirmations auto-resolve (approve safe, decline dangerous).
ChatInfo
Returned bychats(): id: str, title: str, updated_at: str (ISO
timestamp of the last activity). Resume one with client.session(id=info.id);
remove one with that session’s delete().
DiscoverInfo
Returned bydiscover(): logged_in: bool, account: str | None,
agents: list[str], default_agent: str, model: str, runtime_ready: bool,
tool_server_ready: bool (reported True by older apps that predate the field).
Async
AsyncClient mirrors Client for pipelines, FastAPI, notebooks, etc. It’s the
native form (the sync Client wraps it on a background event loop).
Errors
All inherit fromCosmonError — catch that to handle any SDK failure in one
place. There are two channels: errors opening the client (connection, auth,
protocol) and failures during a run (run failure, timeout, a dropped
connection). Each concrete error below.
CosmonError
The base class every other SDK error subclasses. Catch it as a catch-all; catch the specific subclasses below when you want to branch on the cause.CosmonConnectionError
The app can’t be reached. Raised opening the client when the app isn’t running or Developer access is off — and during a run if the connection drops mid-flight (the app quit, or Developer access was turned off). Fix: make sure Nexus is running, signed in, with Developer access on.CosmonAuthError
The server rejected the bearer token — raised opening the client. Happens when Developer access is off, or the per-launch token rotated (the app restarted). Fix: toggle Developer access off and back on to reissue the token.CosmonProtocolError
The app speaks a gateway protocol version the SDK can’t drive — raised opening the client. Fix: update the SDK and the app to compatible versions.CosmonTimeoutError
A run exceeded the client’stimeout — raised during the run. The run is
cancelled server-side (nothing keeps working behind your back). Fix: raise
timeout on the client for long solves, or shorten the task.
CosmonRunError
The run itself failed — raised during the run — including provider errors like being out of credits. Itscode attribute lets you branch without
parsing the message:
Command line
The SDK also installs thecosmon command — doctor, run, and chats. It
has its own page: Command line.