Persistent agents and your cloud
Named agents whose memory outlives their Space: homes in the Cua Volume, routines, notifications, pause and resume, access to your computers, and Spaces in your own AWS, Google Cloud or Modal account.
A persistent agent keeps its harness memory in its home in the Cua Volume (agents/<name>/). The daemon restores the home before each run, saves it after each turn, fires routines with or without an app open, and posts notifications. See Memory and identity.
Persistent agents#
Methods of Spaces.
Spaces.persistent_agent_create#
Creates a persistent agent: harness working in space, its home at
agents/<name>/ in the Cua Volume.
async def persistent_agent_create(self, name: str, harness: str, space: str, options: Optional[PersistentAgentOptions]) -> PersistentAgentInfo| Parameter | Type | Default |
|---|---|---|
name | String | required |
harness | String | required |
space | String | required |
options | Option<PersistentAgentOptions> | required |
Returns PersistentAgentInfo · Async · Raises CuaError
Spaces.persistent_agents#
Every persistent agent.
async def persistent_agents(self) -> List[PersistentAgentInfo]Returns Vec<PersistentAgentInfo> · Async · Raises CuaError
Spaces.persistent_agent_remove#
Forgets a persistent agent (its home stays in the drive).
async def persistent_agent_remove(self, name: str) -> PersistentAgentInfo| Parameter | Type | Default |
|---|---|---|
name | String | required |
Returns PersistentAgentInfo · Async · Raises CuaError
Spaces.persistent_agent_send#
Gives a persistent agent a turn: a follow-up to its idle run, or a new run with its home restored.
async def persistent_agent_send(self, name: str, text: str) -> AgentDelivery| Parameter | Type | Default |
|---|---|---|
name | String | required |
text | String | required |
Returns AgentDelivery · Async · Raises CuaError
Spaces.persistent_agent_save#
Saves a persistent agent's home into the drive now.
async def persistent_agent_save(self, name: str) -> HomeTransfer| Parameter | Type | Default |
|---|---|---|
name | String | required |
Returns HomeTransfer · Async · Raises CuaError
Spaces.agent_pause#
Pauses a persistent agent: run, routines and (local) Space.
async def agent_pause(self, name: str) -> AgentPauseReport| Parameter | Type | Default |
|---|---|---|
name | String | required |
Returns AgentPauseReport · Async · Raises CuaError
Spaces.agent_resume#
Resumes a paused persistent agent; with prompt, starts a run.
async def agent_resume(self, name: str, prompt: Optional[str]) -> AgentResumeReport| Parameter | Type | Default |
|---|---|---|
name | String | required |
prompt | Option<String> | required |
Returns AgentResumeReport · Async · Raises CuaError
Routines#
Methods of Spaces.
Spaces.routine_add#
Adds a routine. Give exactly one of every_minutes, daily_at
(HH:MM) or weekly_on (mon 09:00).
async def routine_add(self, agent: str, title: str, prompt: str, every_minutes: Optional[int], daily_at: Optional[str], weekly_on: Optional[str]) -> RoutineInfo| Parameter | Type | Default |
|---|---|---|
agent | String | required |
title | String | required |
prompt | String | required |
every_minutes | Option<i64> | required |
daily_at | Option<String> | required |
weekly_on | Option<String> | required |
Returns RoutineInfo · Async · Raises CuaError
Spaces.routines#
Routines (of one agent, or all).
async def routines(self, agent: Optional[str]) -> List[RoutineInfo]| Parameter | Type | Default |
|---|---|---|
agent | Option<String> | required |
Returns Vec<RoutineInfo> · Async · Raises CuaError
Spaces.routine_remove#
Deletes a routine.
async def routine_remove(self, id: str) -> None| Parameter | Type | Default |
|---|---|---|
id | String | required |
Async · Raises CuaError
Spaces.routine_set_enabled#
Turns a routine on or off.
async def routine_set_enabled(self, id: str, enabled: bool) -> RoutineInfo| Parameter | Type | Default |
|---|---|---|
id | String | required |
enabled | bool | required |
Returns RoutineInfo · Async · Raises CuaError
Notifications#
Methods of Spaces.
Spaces.notify_user#
Posts a notification to the Cua app. Returns its id.
async def notify_user(self, title: str, body: Optional[str], agent: Optional[str]) -> str| Parameter | Type | Default |
|---|---|---|
title | String | required |
body | Option<String> | required |
agent | Option<String> | required |
Returns String · Async · Raises CuaError
Spaces.notifications#
The notifications feed, newest first.
async def notifications(self, unread_only: bool, since_ms: Optional[int]) -> List[NotificationInfo]| Parameter | Type | Default |
|---|---|---|
unread_only | bool | required |
since_ms | Option<u64> | required |
Returns Vec<NotificationInfo> · Async · Raises CuaError
Spaces.notifications_ack#
Marks notifications read (every one when ids is empty).
async def notifications_ack(self, ids: List[str]) -> int| Parameter | Type | Default |
|---|---|---|
ids | Vec<String> | required |
Returns u64 · Async · Raises CuaError
Access to your computers#
Methods of Spaces.
Spaces.computer_access_grant#
Lets one persistent agent use one of the user's computers (asks for presence).
async def computer_access_grant(self, agent: str, machine: str, expires_in_secs: Optional[int]) -> ComputerGrant| Parameter | Type | Default |
|---|---|---|
agent | String | required |
machine | String | required |
expires_in_secs | Option<u64> | required |
Returns ComputerGrant · Async · Raises CuaError
Spaces.computer_access_revoke#
Takes a persistent agent's computer access back (every machine when
machine is empty). Returns how many grants.
async def computer_access_revoke(self, agent: str, machine: Optional[str]) -> int| Parameter | Type | Default |
|---|---|---|
agent | String | required |
machine | Option<String> | required |
Returns u64 · Async · Raises CuaError
Spaces.computer_access#
Per-agent computer grants (of one agent, or all).
async def computer_access(self, agent: Optional[str]) -> List[ComputerGrant]| Parameter | Type | Default |
|---|---|---|
agent | Option<String> | required |
Returns Vec<ComputerGrant> · Async · Raises CuaError
ThreadView record#
What a person was looking at in a Space as they posted to its thread:
the Space's desktop, or one of its windows. Every thread entry and task
that has one carries it as view (thread_read, thread_inbox, the
entry thread_post returns); thread_view_of reads it. The fields
are cua.env.v1.ThreadView's.
Returned by thread_view_of.
| Field | Type | Default | Description |
|---|---|---|---|
kind | String | desktop or window. | |
app | Option<String> | The window's app ("Firefox"). | |
title | Option<String> | The window's title ("Pull requests"). | |
window_id / windowId | Option<String> | The window's id in the Space (what the window tools take). |
thread_view_of#
The view of one thread entry or task, given as JSON (an element of
thread_read's entries or tasks, or thread_inbox's tasks):
none when it has none.
def thread_view_of(entry_json: str) -> Optional[ThreadView]| Parameter | Type | Default |
|---|---|---|
entry_json | String | required |
Returns Option<ThreadView> · Raises CuaError
PersistentAgentInfo record#
A persistent agent: a named harness whose memory (its home in the Cua Drive) outlives its runs and its Space.
Returned by Spaces.persistent_agent_create, Spaces.persistent_agent_remove, Spaces.persistent_agents.
| Field | Type | Default | Description |
|---|---|---|---|
name | String | ||
harness | String | Harness id. | |
space | String | The Space it works in. | |
model | Option<String> | ||
base_url / baseUrl | Option<String> | ||
env_from_host / envFromHost | Vec<String> | ||
paused | bool | ||
space_state / spaceState | String | running, suspended (a paused local Space) or released (a paused cloud Space). | |
run_id / runId | Option<String> | The current run. | |
saved_ms / savedMs | u64 | Unix ms of the last home save. | |
created_ms / createdMs | u64 | ||
last_error / lastError | Option<String> |
PersistentAgentOptions record#
How to create a persistent agent.
| Field | Type | Default | Description |
|---|---|---|---|
model | Option<String> | None | |
base_url / baseUrl | Option<String> | None | |
env_from_host / envFromHost | Vec<String> | [] | Provider key variables forwarded from the host's environment at each start. |
env | HashMap<String, String> | [:] | More environment for every run (not secrets). |
AgentDelivery record#
What Spaces.persistent_agent_send did.
Returned by Spaces.persistent_agent_send.
| Field | Type | Default | Description |
|---|---|---|---|
run_id / runId | String | ||
started | bool | A new run started (with the home restored) rather than a follow-up. | |
restored | Option<HomeTransfer> |
HomeTransfer record#
What moved between the drive and a Space.
Returned by Spaces.persistent_agent_save.
| Field | Type | Default | Description |
|---|---|---|---|
files | u64 | ||
bytes | u64 | ||
unchanged | u64 | ||
removed | u64 | ||
blocked | Vec<String> | path (kind) of each file the secret scanner kept out. | |
millis | u64 |
AgentPauseReport record#
What Spaces.agent_pause did.
Returned by Spaces.agent_pause.
| Field | Type | Default | Description |
|---|---|---|---|
stopped_run / stoppedRun | Option<String> | ||
saved | Option<HomeTransfer> | ||
space_state / spaceState | String | ||
millis | u64 |
AgentResumeReport record#
What Spaces.agent_resume did.
Returned by Spaces.agent_resume.
| Field | Type | Default | Description |
|---|---|---|---|
space | String | ||
recreated | bool | ||
restored | Option<HomeTransfer> | ||
run_id / runId | Option<String> | ||
ready_ms / readyMs | u64 | From the call to the home being back in a ready Space. |
RoutineInfo record#
A routine: a recurring turn of a persistent agent, fired by the daemon.
Returned by Spaces.routine_add, Spaces.routine_set_enabled, Spaces.routines.
| Field | Type | Default | Description |
|---|---|---|---|
id | String | ||
agent | String | ||
title | String | ||
prompt | String | ||
label | String | Every day at 8:00 AM. | |
enabled | bool | ||
next_fire / nextFire | Option<String> | RFC 3339. | |
last_fired_at / lastFiredAt | Option<String> | ||
last_outcome / lastOutcome | Option<String> | ||
last_run_id / lastRunId | Option<String> |
NotificationInfo record#
One entry of the notifications feed.
Returned by Spaces.notifications.
| Field | Type | Default | Description |
|---|---|---|---|
id | String | ||
at_ms / atMs | u64 | ||
agent | Option<String> | ||
kind | String | turn_ended, message, approval or error. | |
title | String | ||
body | String | ||
run_id / runId | Option<String> | ||
space | Option<String> | ||
read | bool |
ComputerGrant record#
A persistent agent's grant on one of the user's computers.
Returned by Spaces.computer_access, Spaces.computer_access_grant.
| Field | Type | Default | Description |
|---|---|---|---|
id | String | ||
agent | String | ||
machine | String | ||
created_ms / createdMs | u64 | ||
expires_ms / expiresMs | Option<u64> | ||
revoked | bool |
Your cloud#
Create a sandbox or Space with on="aws", "gcp", "hetzner" or "modal" once the cloud is connected. AWS, Google Cloud and Modal use their own CLI sign-in and Cua stores only the profile, region, project or environment names; Hetzner uses a project API token that Cua saves in its credential store. The guest dials out to the cua.ai relay, so nothing listens on the internet. cloud_test creates nothing; cloud_sweep deletes only what Cua tagged and recorded.
Methods of Spaces.
Spaces.cloud_status#
Your clouds: found credentials, the connected account and region,
what each can run at what hourly cost, and what Cua created there.
provider narrows it to one cloud.
async def cloud_status(self, provider: Optional[str]) -> CloudStatus| Parameter | Type | Default |
|---|---|---|
provider | Option<String> | required |
Returns CloudStatus · Async · Raises CuaError
Spaces.cloud_connect#
Connects a cloud account (after the checks cloud_test runs). With
make_default, Spaces are created there when no location is given.
ttl_hours (default 8, 0: never) deletes each Space there after
that long. options links without a stored key (auth: oidc) and
sets the cloud's own budget and largest machine; the result's
provider.status, next and verify say where it stands.
async def cloud_connect(self, target: CloudTarget, make_default: bool, ttl_hours: Optional[int], options: Optional[CloudConnectOptions] = None) -> CloudConnected| Parameter | Type | Default |
|---|---|---|
target | CloudTarget | required |
make_default | bool | required |
ttl_hours | Option<u32> | required |
options | Option<CloudConnectOptions> | None |
Returns CloudConnected · Async · Raises CuaError
Spaces.cloud_test#
Checks a cloud account without creating anything.
async def cloud_test(self, target: CloudTarget) -> CloudTestReport| Parameter | Type | Default |
|---|---|---|
target | CloudTarget | required |
Returns CloudTestReport · Async · Raises CuaError
Spaces.cloud_disconnect#
Forgets a connected cloud. Refused (listing them) while Cua
resources still run there; with delete_resources, deletes everything Cua
created there first and disconnects once the cloud confirms.
async def cloud_disconnect(self, provider: str, delete_resources: bool = False) -> CloudDisconnected| Parameter | Type | Default |
|---|---|---|
provider | String | required |
delete_resources | bool | false |
Returns CloudDisconnected · Async · Raises CuaError
Spaces.cloud_sweep#
What Cua left in your clouds (expired Spaces, resources whose Space
is gone; with all, everything Cua created there). Deletes it
unless dry_run. Only resources tagged and recorded as Cua's are
ever touched.
async def cloud_sweep(self, provider: Optional[str], dry_run: bool, all: bool) -> CloudSweepReport| Parameter | Type | Default |
|---|---|---|
provider | Option<String> | required |
dry_run | bool | required |
all | bool | required |
Returns CloudSweepReport · Async · Raises CuaError
Spaces.cloud_audit#
What Cua did in your clouds, newest last (default the newest 50).
async def cloud_audit(self, limit: Optional[int] = None) -> List[CloudAuditEntry]| Parameter | Type | Default |
|---|---|---|
limit | Option<u32> | None |
Returns Vec<CloudAuditEntry> · Async · Raises CuaError
Spaces.cloud_approve#
Approves what an agent asked for on provider (its link, or a
raise of its limits), or with deny declines it. Only for a person:
refused when an agent calls, and never offered to agents over MCP.
async def cloud_approve(self, provider: str, deny: bool = False) -> CloudProvider| Parameter | Type | Default |
|---|---|---|
provider | String | required |
deny | bool | false |
Returns CloudProvider · Async · Raises CuaError
Spaces.cloud_cost#
What the machines Cua created cost (an estimate: list price times
runtime), grouped by space, agent, day or cloud, since
since (YYYY-MM-DD; default the first of this month), for one
provider or every cloud.
async def cloud_cost(self, by: str = "space", since: Optional[str] = None, provider: Optional[str] = None) -> CloudCostReport| Parameter | Type | Default |
|---|---|---|
by | String | "space" |
since | Option<String> | None |
provider | Option<String> | None |
Returns CloudCostReport · Async · Raises CuaError
CloudTarget record#
Where in a cloud account Spaces go. AWS, Google Cloud and Modal use
their own CLI sign-in; Hetzner takes its API token in token (or
HCLOUD_TOKEN).
| Field | Type | Default | Description |
|---|---|---|---|
provider | String | aws, gcp, hetzner or modal. | |
profile | Option<String> | None | AWS or Modal profile. |
region | Option<String> | None | AWS or GCP region, or Hetzner location (fsn1). |
zone | Option<String> | None | GCP zone. |
project | Option<String> | None | GCP project. |
environment | Option<String> | None | Modal environment. |
token | Option<String> | None | Hetzner: the project's Read & Write API token. Secret: used for the checks, saved in the Cua credential store when they pass, never printed. |
CloudStatus record#
cloud_status.
Returned by Spaces.cloud_status.
| Field | Type | Default | Description |
|---|---|---|---|
default_on / defaultOn | String | default.on, for example aws. | |
providers | Vec<CloudProvider> | ||
resources | Vec<CloudResource> |
CloudProvider record#
One cloud as cloud_status lists it.
Returned by Spaces.cloud_approve.
| Field | Type | Default | Description |
|---|---|---|---|
name | String | aws, gcp, hetzner, modal. | |
title | String | AWS, Google Cloud, Hetzner Cloud, Modal. | |
tier | String | vm or sandbox. | |
connected | bool | ||
default | bool | Whether it is the default location (default.on). | |
credentials | CloudCredentials | ||
account | String | The account, project or workspace (after a test or connect). | |
profile | String | ||
region | String | ||
zone | String | ||
project | String | ||
environment | String | ||
label | String | "AWS · us-west-2". | |
ttl_hours / ttlHours | u32 | Hours after which a Space there deletes itself (0: never). | |
kinds | Vec<CloudKind> | ||
auth | String | cli (the cloud CLI's sign-in), oidc (no stored key) or sealed; empty when not connected. | |
status | String | connected, waiting-for-approval, not-connected; from cloud_connect also needs-trust, checking, failed. | |
budget_usd_month / budgetUsdMonth | Option<f64> | The monthly budget in US dollars, when set. | |
max_size / maxSize | String | The largest machine (4x16: vCPUs x GiB), empty: no limit. | |
spent_month / spentMonth | f64 | Estimated US dollars this calendar month. | |
running | u32 | Machines Cua runs there now. | |
approval | String | connection or limits while a person's approval is pending. | |
approval_agent / approvalAgent | String | The agent whose request waits for approval. | |
pending_budget_usd_month / pendingBudgetUsdMonth | Option<f64> | The monthly budget an agent asked for, waiting for approval. | |
pending_max_size / pendingMaxSize | String | The largest machine an agent asked for (4x16), waiting for approval. | |
can_approve / canApprove | bool | Whether this caller (a person) can approve or deny what waits (cloud_approve). | |
suggest_auth / suggestAuth | String | oidc when this link could switch to linking without a stored key (an AWS link through the CLI sign-in), else empty. | |
issue | String | What is wrong with the link and what to do, one sentence, or empty. | |
holders | Vec<String> | sealed: the devices that can open the account's API token ("Can open it"). |
CloudKind record#
What a cloud can run for one image family, and the estimated cost.
| Field | Type | Default | Description |
|---|---|---|---|
image | String | linux, linux-slim, windows, omarchy, macos. | |
kind | String | container or vm. | |
supported | bool | ||
reason | String | Why not, or how it runs (one line). | |
machine_type / machineType | String | The machine type Cua picks (t3.medium, e2-medium). | |
usd_per_hour / usdPerHour | f64 | Estimated on-demand US dollars per hour while it runs. |
CloudCredentials record#
Where a cloud's credentials were found on this machine (never a secret).
| Field | Type | Default | Description |
|---|---|---|---|
found | bool | ||
source | String | "~/.aws profile default", "gcloud account ada@x.io". |
CloudResource record#
One thing Cua created in a cloud.
| Field | Type | Default | Description |
|---|---|---|---|
provider | String | ||
id | String | The cloud's id. | |
resource_type / resourceType | String | instance, security_group, firewall, sandbox, ... | |
sandbox | String | The sandbox it belongs to (aws:<name>), empty for shared resources. | |
machine | String | The relay machine the sandbox joined as (its Space is relay:<machine>). | |
region | String | ||
state | String | ||
created | String | RFC 3339. | |
expires | String | RFC 3339, empty: never. | |
expired | bool | ||
started_by / startedBy | String | Who started it: an agent's name, or user (empty for records made before it was kept). | |
cost_usd / costUsd | f64 | Estimated US dollars it cost so far (list price times runtime). |
CloudConnected record#
cloud_connect: the cloud (its status is the outcome), the checks it
ran, the next step and the command that verifies it.
Returned by Spaces.cloud_connect.
| Field | Type | Default | Description |
|---|---|---|---|
provider | CloudProvider | ||
checks | Vec<CloudCheck> | ||
next | Option<CloudNext> | None: nothing left to do. | |
verify | String | cua cloud status aws. |
CloudCheck record#
One check cloud_test ran.
| Field | Type | Default | Description |
|---|---|---|---|
name | String | ||
ok | bool | ||
detail | String |
CloudTestReport record#
cloud_test.
Returned by Spaces.cloud_test.
| Field | Type | Default | Description |
|---|---|---|---|
provider | String | ||
ok | bool | ||
account | String | ||
checks | Vec<CloudCheck> |
CloudDisconnected record#
cloud_disconnect.
Returned by Spaces.cloud_disconnect.
| Field | Type | Default | Description |
|---|---|---|---|
provider | String | ||
disconnected | bool | ||
left | Vec<CloudResource> | Resources Cua still records there. | |
deleted | Vec<CloudResource> | With delete: what was deleted from the account first. |
CloudAuditEntry record#
One line of the cloud audit log (cloud_audit). Never a secret.
Returned by Spaces.cloud_audit.
| Field | Type | Default | Description |
|---|---|---|---|
ts | String | When (RFC 3339, UTC). | |
action | String | connect, disconnect, resource_recorded, resource_created, resource_confirmed or resource_deleted. | |
provider | String | ||
kind | String | The resource type; empty for connect and disconnect. | |
id | String | ||
space | String | The Space it belongs to. | |
actor | String | user, sweep, auto-sweep, disconnect or rollback. | |
outcome | String | ok, failed or refused. | |
detail | String | ||
source | String | device (this cua home's log) or account (Cua's issuer, for clouds linked to the account); empty from an older daemon (this device). |
CloudSweepReport record#
cloud_sweep.
Returned by Spaces.cloud_sweep.
| Field | Type | Default | Description |
|---|---|---|---|
dry_run / dryRun | bool | ||
resources | Vec<CloudSweepItem> |
CloudSweepItem record#
One row of cloud_sweep.
| Field | Type | Default | Description |
|---|---|---|---|
resource | CloudResource | ||
action | String | delete (dry run), deleted, keep or failed. | |
reason | String |
CloudConnectOptions record#
How cloud_connect links a cloud, beyond where.
| Field | Type | Default | Description |
|---|---|---|---|
auth | Option<String> | None | cli (default), oidc (AWS, Google Cloud, Azure: no stored key; Azure always) or sealed. |
budget_usd_month / budgetUsdMonth | Option<f64> | None | The monthly budget, US dollars. |
max_size / maxSize | Option<String> | None | The largest machine, 4x16. |
account_id / accountId | Option<String> | None | AWS oidc: the 12-digit account id. |
role_arn / roleArn | Option<String> | None | AWS oidc: the role ARN when it is not cua-spaces. |
project_number / projectNumber | Option<String> | None | Google Cloud oidc: the project number (implies oidc). |
service_account / serviceAccount | Option<String> | None | Google Cloud oidc: a service account to act as. |
subscription_id / subscriptionId | Option<String> | None | Azure: the subscription id. |
tenant_id / tenantId | Option<String> | None | Azure: the Microsoft Entra tenant id. |
client_id / clientId | Option<String> | None | Azure: the cua-spaces managed identity's client id. |
resource_group / resourceGroup | Option<String> | None | Azure: the resource group (default cua-spaces). |
check | bool | false | oidc: prove the link (nothing is created) and save it. |
agent | Option<String> | None | The agent making the change; its changes wait for approval. |
CloudCostReport record#
cloud_cost: an estimate from list price times runtime.
Returned by Spaces.cloud_cost.
| Field | Type | Default | Description |
|---|---|---|---|
by | String | space, agent, day or cloud. | |
since | String | The first day counted (YYYY-MM-DD). | |
until | String | Up to when (RFC 3339). | |
rows | Vec<CloudCostRow> | ||
total_usd / totalUsd | f64 |
CloudCostRow record#
One row of cloud_cost.
| Field | Type | Default | Description |
|---|---|---|---|
key | String | The Space, agent, day (YYYY-MM-DD) or cloud. | |
usd | f64 | Estimated US dollars, to the cent. | |
hours | f64 | Machine hours. | |
machines | u32 | How many machines ran. |
CloudNext record#
The next step of a cloud_connect: a command for the agent, or a page
for a person (and what to paste there), and why.
| Field | Type | Default | Description |
|---|---|---|---|
run | Option<String> | ||
open | Option<String> | ||
paste | Option<String> | ||
why | String |