Coding agents and setup

Run coding agents (Claude Code, Codex, Gemini CLI, OpenCode, ...) inside any sandbox, and set them up on this machine.

sandbox.agents() (or guest.agents()) runs a harness over the Agent Client Protocol: normalized events, follow-ups, interrupts and results. Runs outlive the handle that started them.

Agents in a sandbox#

Methods of Sandbox.

Sandbox.agents#

Coding agents inside this sandbox (needs cua-spacesd): run a harness over ACP, stream normalized events, follow up, interrupt, collect results; runs outlive this handle.

async def agents(self) -> Agents

Returns Agents · Async · Raises CuaError

Agents through a spacesd client#

Methods of SpacesdClient.

SpacesdClient.agents#

Coding agents in this guest.

async def agents(self) -> Agents

Returns Agents · Async · Raises CuaError

Agents#

Agent runs in one sandbox.

Returned by Sandbox.agents, SpacesdClient.agents.

MethodDescription
ensureInstalls harnesses or apps (["claude-code", "blender"]: harness ids or installable ids) now; returns the progress lines.
getA handle for an existing run (started by any client).
listEvery run in the sandbox, newest first.
runStarts harness on prompt and returns at once; the run lives in the sandbox (fire and forget) until it is stopped.

Agents.ensure#

Installs harnesses or apps (["claude-code", "blender"]: harness ids or installable ids) now; returns the progress lines.

async def ensure(self, ids: List[str]) -> List[str]
ParameterTypeDefault
idsVec<String>required

Returns Vec<String> · Async · Raises CuaError

Agents.get#

A handle for an existing run (started by any client).

async def get(self, run_id: str) -> AgentRun
ParameterTypeDefault
run_idStringrequired

Returns AgentRun · Async · Raises CuaError

Agents.list#

Every run in the sandbox, newest first.

async def list(self) -> List[AgentRunInfo]

Returns Vec<AgentRunInfo> · Async · Raises CuaError

Agents.run#

Starts harness on prompt and returns at once; the run lives in the sandbox (fire and forget) until it is stopped.

async def run(self, harness: str, prompt: str, options: Optional[AgentRunOptions]) -> AgentRun
ParameterTypeDefault
harnessStringrequired
promptStringrequired
optionsOption<AgentRunOptions>required

Returns AgentRun · Async · Raises CuaError

AgentRun#

One run.

Returned by Agents.get, Agents.run.

MethodDescription
artifactsFiles the run created or changed in its working directory.
eventsEvents after cursor (0: from the start), at most max.
interruptCancels the turn in flight; the session stays open.
removeStops the run and deletes its directory (secrets included).
resultThe last turn's outcome.
sendA follow-up in the same session (queued while a turn runs).
status
stopStops the run and verifies its process is gone.
waitWaits until no turn is running (at most timeout_ms), then returns the result.
AccessorReturnsDescription
harness()String
run_id()String

AgentRun.artifacts#

Files the run created or changed in its working directory.

async def artifacts(self) -> List[AgentArtifact]

Returns Vec<AgentArtifact> · Async · Raises CuaError

AgentRun.events#

Events after cursor (0: from the start), at most max.

async def events(self, cursor: int, max: Optional[int]) -> AgentEventPage
ParameterTypeDefault
cursoru64required
maxOption<u32>required

Returns AgentEventPage · Async · Raises CuaError

AgentRun.interrupt#

Cancels the turn in flight; the session stays open.

async def interrupt(self) -> AgentRunInfo

Returns AgentRunInfo · Async · Raises CuaError

AgentRun.remove#

Stops the run and deletes its directory (secrets included).

async def remove(self) -> None

Async · Raises CuaError

AgentRun.result#

The last turn's outcome.

async def result(self) -> AgentRunResult

Returns AgentRunResult · Async · Raises CuaError

AgentRun.send#

A follow-up in the same session (queued while a turn runs).

async def send(self, text: str, files: Optional[List[AgentFile]]) -> AgentRunInfo
ParameterTypeDefault
textStringrequired
filesOption<Vec<AgentFile>>required

Returns AgentRunInfo · Async · Raises CuaError

AgentRun.status#

async def status(self) -> AgentRunInfo

Returns AgentRunInfo · Async · Raises CuaError

AgentRun.stop#

Stops the run and verifies its process is gone.

async def stop(self) -> AgentRunInfo

Returns AgentRunInfo · Async · Raises CuaError

AgentRun.wait#

Waits until no turn is running (at most timeout_ms), then returns the result.

async def wait(self, timeout_ms: Optional[int]) -> AgentRunResult
ParameterTypeDefault
timeout_msOption<u64>required

Returns AgentRunResult · Async · Raises CuaError

AgentRunOptions record#

Options for Agents.run. Every field is optional.

FieldTypeDefaultDescription
cwdOption<String>NoneWorking directory in the sandbox (default: the run's own).
repoOption<String>NoneGit URL cloned into the working directory first.
branchOption<String>None
envHashMap<String, String>[:]Env for the agent only (API keys): written 0600 in the run, redacted from its event log, never in argv.
env_from_host / envFromHostVec<String>[]Provider key variables copied from THIS process's environment (["ANTHROPIC_API_KEY"]); only known provider key names.
modelOption<String>NoneModel id.
base_url / baseUrlOption<String>NoneA custom model endpoint (proxy, gateway, compatible server).
wireOption<String>NoneIts wire format: anthropic, openai-responses, openai-chat, gemini (default: the harness's own).
mcp_servers / mcpServersVec<AgentRunMcpServer>[]
sandbox_mcp / sandboxMcpOption<bool>NoneGive the agent the sandbox's own MCP (cua-driver). Default true.
skillsOption<bool>NoneCopy the cua skills into the harness. Default true.
installOption<bool>NoneInstall what the harness needs. Default true.
filesVec<AgentFile>[]
exit_when_idle / exitWhenIdleboolfalseStop (resumably) once the queue is empty: fire-and-forget.
labelOption<String>None

AgentRunMcpServer record#

An MCP server a run's agent gets: url (streamable HTTP, as reachable from inside the sandbox) or command (stdio, run in the sandbox).

FieldTypeDefaultDescription
nameStringName the agent sees.
urlOption<String>None
headersHashMap<String, String>[:]Header values (secrets allowed: they travel like env keys).
commandOption<String>None
argsVec<String>[]
envHashMap<String, String>[:]

AgentFile record#

A file for the first prompt or a follow-up.

FieldTypeDefaultDescription
nameStringFile name in the run's attachments/.
bytesVec<u8>

AgentEvent record#

One normalized event.

FieldTypeDefaultDescription
sequ64
ts_ms / tsMsu64
turnu32
kindStringmessage, thought, tool_call, tool_update, plan, usage, permission, turn_started, turn_ended, install, error, exited, ... (see harnesses()).
textOption<String>
tool_id / toolIdOption<String>
tool_title / toolTitleOption<String>
tool_kind / toolKindOption<String>
tool_status / toolStatusOption<String>
stop_reason / stopReasonOption<String>
categoryStringHow a conversation view shows it: message (the agent's words), user (the prompt as the agent got it), activity (a muted one-line row: install, thinking, tools, plan, turn end, notice, error, exit) or hidden. See AgentTranscript.
summaryOption<String>One short line for an activity event.
lineOption<String>One human-readable line, when the kind has one.
jsonStringThe event as written (ACP payload included), JSON.

AgentEventPage record#

A page of events.

Returned by AgentRun.events.

FieldTypeDefaultDescription
eventsVec<AgentEvent>
cursoru64Pass back to continue.
caught_up / caughtUpboolNothing more is written yet.

AgentRunInfo record#

A run's state.

Returned by AgentRun.interrupt, AgentRun.send, AgentRun.status, AgentRun.stop, Agents.list.

FieldTypeDefaultDescription
run_id / runIdString
harnessOption<String>
statusStringrunning, idle, failed, crashed, unknown.
phaseStringinstalling, starting, working, waiting, exited, ...
reasonString
turnu32
aliveOption<bool>
accepts_message / acceptsMessageboolA follow-up sent now starts the next turn (not mid-turn).
promptOption<String>
labelOption<String>
created_at / createdAtOption<f64>Unix seconds.
jsonString

AgentRunResult record#

What the last turn produced.

Returned by AgentRun.result, AgentRun.wait.

FieldTypeDefaultDescription
run_id / runIdString
statusString
turnu32
textStringThe agent's messages in the last turn.
stop_reason / stopReasonOption<String>
usage_json / usageJsonOption<String>
errorOption<String>
tool_calls / toolCallsu32

AgentArtifact record#

A file the run created or changed.

Returned by AgentRun.artifacts.

FieldTypeDefaultDescription
pathString
sizeu64
modified_ms / modifiedMsu64

agent_harnesses#

The harnesses, their readiness, installs, key variables and limits, as JSON.

def agent_harnesses() -> str

Returns String

AgentTranscript#

A run's events folded into conversation items, the same rule in every language: the agent's message chunks join into message items, the prompt is a user item (never repeated as agent text), and consecutive activity of one turn folds into one activity group. Absorbing an event twice changes nothing, so a poll can re-read a page.

MethodDescription
newAn empty transcript.
absorbAdds events from AgentRun.events.
absorb_jsonAdds the events of an agent_events result (Space.agent_events, the MCP tool), or a JSON array of events.
noteAdds a line the app itself produced (a start note, "queued") as an activity step of turn.
AccessorReturnsDescription
cursor()u64The highest agent_events cursor absorbed: pass it back to read on.
items()Vec<AgentTranscriptItem>The items so far.
preview()Option<String>The agent's last message on one line (a roster preview), None before it has said anything. Activity is never a preview.
revision()u64Changes whenever the items do.

AgentTranscript.new#

An empty transcript.

AgentTranscript()

Returns AgentTranscript

AgentTranscript.absorb#

Adds events from AgentRun.events.

def absorb(self, events: List[AgentEvent]) -> None
ParameterTypeDefault
eventsVec<AgentEvent>required

AgentTranscript.absorb_json#

Adds the events of an agent_events result (Space.agent_events, the MCP tool), or a JSON array of events. Returns the page's cursor (also kept, see AgentTranscript.cursor) when it has one.

def absorb_json(self, json: str) -> Optional[int]
ParameterTypeDefault
jsonStringrequired

Returns Option<u64> · Raises CuaError

AgentTranscript.note#

Adds a line the app itself produced (a start note, "queued") as an activity step of turn.

def note(self, turn: int, text: str) -> None
ParameterTypeDefault
turnu32required
textStringrequired

AgentTranscriptItem record#

One item of an AgentTranscript.

Returned by AgentTranscript.items.

FieldTypeDefaultDescription
kindStringmessage (a bubble or prose), user (the prompt as the agent got it; skip it when the app shows what the user typed) or activity (a muted, collapsible group of one-line steps).
turnu32Turn number (0 before the first prompt).
textStringThe message or prompt; for activity, the group summary (5 steps).
stepsVec<String>activity only: one line per step.

agent_event_category#

The category of an event kind: message, user, activity or hidden (the rule AgentEvent.category and AgentTranscript use).

def agent_event_category(kind: str) -> str
ParameterTypeDefault
kindStringrequired

Returns String