Agents in a Space
Add a coding or computer-use agent to a Space, message it, and check back on it later, from the CLI, from your own agent over MCP, or from code.
An agent in a Space works on a computer of its own instead of on This Mac. You add it once, give it work, and come back later to read what it did. The Space is the boundary: the agent approves its own tool calls inside it, and nothing it does reaches your computer unless you allow it.
There are three ways to run one:
| You want | Use |
|---|---|
| An agent with a name that remembers across runs and can work on a schedule | cua agent add NAME |
| One task, then stop | cua agent add NAME --once |
| A task that must survive a crash of the process or the machine driving it | cua agent add NAME --durable |
A named agent keeps its memory in the Cua Volume (see Memory and identity) and can run on a schedule. A durable agent is re-driven after a crash (see Keep an agent running through crashes).
Add an agent#
cua agent add ada --harness claude-code --in local:dev
cua agent send ada "Clone github.com/org/app and get the test suite passing"--in names the Space the agent works in. --harness is any id from
cua agent harnesses. Pass a prompt after the name to give the first task
in the same command.
Named agents are kept by the Cua daemon on This Mac (or on the computer whose daemon you use), and their Space can be any Space you can reach: a local one, one on a computer you added, or one in your own cloud.
Message it#
cua agent send ada "..." (MCP agent_send) gives the agent a turn. If its
last run is idle, the message is a follow-up in the same session; if it has
none, a new run starts with its memory restored. A message sent while a turn is
running is refused, never interrupts it, and the reply says why.
Check back#
| To see | CLI | MCP |
|---|---|---|
| Your agents, their Space and state | cua agent ls | persistent_agent_list |
| What a run did, event by event | cua agent logs local:dev RUN_ID -f | agent_events, agent_status |
| Turns that ended, questions and failures | cua agent notifications --unread | notifications_list |
When a turn ends the daemon posts a notification with the agent's answer, and the Cua app shows it as a system notification. Open the Space in Cua Spaces to watch the agent's desktop while it works, or take over.
cua agent ls
cua agent ls local:dev
cua agent notifications --unreadcua agent ls with no Space lists your named agents; with a Space it lists the
runs in it, including one-off tasks.
From another device or person#
A Space's thread and its agents live on the computer that provides the Space. When that computer is shared with you, directly or through a team, you read and post in the thread of each Space it provides from your own device, and @mention its agents there, with the same tools as on that computer. When only a Space is shared with you, you reach that Space's thread the same way, and nothing else of the computer that provides it. Your role is the one the Space was shared with, and stopping the share ends it. Cua sends each call to that computer's daemon through the relay, signed in as you: what you post shows your name, and the owner's roles and each agent's rights decide what you can do. Shared with you to view, you can read the thread and see the agents, but you cannot post, give tasks, stop an agent or answer its questions.
thread_post {space: "relay:space-7f2c41d0", text: "@ada run the e2e suite and post the failures here"}
thread_read {space: "relay:space-7f2c41d0", after: 41, follow_ms: 20000}follow_ms waits up to 25 seconds for new entries, so a client can follow the
thread. The thread can be reached while that computer is online. If it runs an
older Cua, the answer says to update Cua on it.
Coding agents#
Every agent runs a harness inside the Space over the Agent Client Protocol. The
Spaces daemon installs the harness on first use (pinned and checksum-verified)
and gives it the Space's tools. Nine harnesses are supported: Claude Code
(claude-code), OpenAI Codex (openai-codex), Gemini CLI (gemini-cli),
Google Antigravity (google-antigravity), OpenCode (opencode), Goose
(goose), Pi (pi), Hermes (hermes) and OpenClaw (openclaw).
cua agent harnessescua agent harnesses (MCP agent_capabilities) reports each one's readiness,
the key variables it reads and what is known not to work. A harness whose key
is saved reports auth: ok.
A harness needs a provider key. Save it once in Cua Spaces, Settings,
Agents (or cua agent keys set), and each run gets the keys its harness
reads, written 0600 inside the run and redacted from its log; see
Agent keys. Credential files on
your computer, such as ~/.claude/.credentials.json or Codex's ChatGPT
sign-in, are never copied into a Space. A harness can use a sign-in that is
already inside the Space, for example one you moved there with
Teleport an app, which asks you first.
Computer use#
Every run gets the Space's own Cua Driver tools as an MCP server: screenshots,
clicks, typing, launching apps and the accessibility tree of the Space's
desktop. So any harness above is also a computer-use agent: ask it to use an
app in the Space and it drives the desktop the way it would edit a file. Turn
this off with --no-sandbox-mcp on cua agent run (MCP sandbox_mcp: false).
Give it more MCP servers with --mcp NAME=URL (MCP mcp_servers), and open a
terminal on the Space's desktop that follows the run with show: true on
agent_start.
Run a one-off task#
A one-off task has no name and no memory: it runs in the Space, answers, and stops.
cua agent add fix-tests --harness claude-code --in local:dev --once "Fix the failing test in /work"
cua agent run local:dev claude-code "Fix the failing test in /work" --follow--once is cua agent run with the name as the run's label and
--exit-when-idle. Over MCP, call agent_start {space, agent, prompt}, then
agent_message for each follow-up, agent_events to read it and agent_stop
to end it. A run is a detached process in the Space; everything about it is a
file under ~/.cua/agents/<run_id>/ there, so it survives your client going
away and the server restarting, and a fresh client can list and continue it.
It does not survive the Space being deleted.
cua agent ls local:dev
cua agent send local:dev run-1a2b3c4d "now add a regression test" -f
cua agent interrupt local:dev run-1a2b3c4d
cua agent stop local:dev run-1a2b3c4dagent_start with home set runs the task as a named agent instead (created on
first use), with its memory restored.
From code#
A run is a thread in the TypeScript SDK:
import { embedded } from "@trycua/cua"
import { startThread } from "@trycua/cua/spaces"
const bot = await startThread(embedded().spaces(), {
agent: "claude-code",
prompt: "Open the repo in the Space and run the tests",
placement: { type: "dedicated", on: "local", deleteOnClose: true },
})
await bot.send("Now fix the failing test")
console.log(await bot.status())
await bot.close() // stops the run and deletes the Spaceplacement shared ({ type: "shared", space, acknowledgeNoIsolation: true })
reuses a Space you name. adoptThread(spaces, spaceId, runId) reattaches.
The lower-level calls are one run per thread and one message per turn. A message sent mid-turn is refused (or queued) unless forced, so show the reason. The TypeScript and Rust tabs are from the examples in other languages, and the Swift tab is from the CuaBots sample.
const report = await space.agentStart(bot.agent, prompt, false, options)
const t = new BotThread(bot, report.runId, space)const r = await this.space.agentMessage(this.runId, message, false)
if (!r.ok) {
this.fold.note(this.turns.length, `Refused: ${r.reason}`)
return { accepted: false, reason: r.reason }
}In a sandbox from the Cua SDK, sandbox.agents() installs a harness, streams
its events and collects the result: see
Run a coding agent in a sandbox.
Run agent frameworks in a sandbox covers
OpenAI Agents, Codex, Cursor and OpenClaw. To build an agent whose own loop is
durable, see Build a durable agent in code.
Reference#
Every tool and its parameters: Agents and Persistent agents in the Spaces reference. Every command: the CLI reference.