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
ParameterTypeDefault
nameStringrequired
harnessStringrequired
spaceStringrequired
optionsOption<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
ParameterTypeDefault
nameStringrequired

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
ParameterTypeDefault
nameStringrequired
textStringrequired

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
ParameterTypeDefault
nameStringrequired

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
ParameterTypeDefault
nameStringrequired

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
ParameterTypeDefault
nameStringrequired
promptOption<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
ParameterTypeDefault
agentStringrequired
titleStringrequired
promptStringrequired
every_minutesOption<i64>required
daily_atOption<String>required
weekly_onOption<String>required

Returns RoutineInfo · Async · Raises CuaError

Spaces.routines#

Routines (of one agent, or all).

async def routines(self, agent: Optional[str]) -> List[RoutineInfo]
ParameterTypeDefault
agentOption<String>required

Returns Vec<RoutineInfo> · Async · Raises CuaError

Spaces.routine_remove#

Deletes a routine.

async def routine_remove(self, id: str) -> None
ParameterTypeDefault
idStringrequired

Async · Raises CuaError

Spaces.routine_set_enabled#

Turns a routine on or off.

async def routine_set_enabled(self, id: str, enabled: bool) -> RoutineInfo
ParameterTypeDefault
idStringrequired
enabledboolrequired

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
ParameterTypeDefault
titleStringrequired
bodyOption<String>required
agentOption<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]
ParameterTypeDefault
unread_onlyboolrequired
since_msOption<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
ParameterTypeDefault
idsVec<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
ParameterTypeDefault
agentStringrequired
machineStringrequired
expires_in_secsOption<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
ParameterTypeDefault
agentStringrequired
machineOption<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]
ParameterTypeDefault
agentOption<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.

FieldTypeDefaultDescription
kindStringdesktop or window.
appOption<String>The window's app ("Firefox").
titleOption<String>The window's title ("Pull requests").
window_id / windowIdOption<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]
ParameterTypeDefault
entry_jsonStringrequired

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.

FieldTypeDefaultDescription
nameString
harnessStringHarness id.
spaceStringThe Space it works in.
modelOption<String>
base_url / baseUrlOption<String>
env_from_host / envFromHostVec<String>
pausedbool
space_state / spaceStateStringrunning, suspended (a paused local Space) or released (a paused cloud Space).
run_id / runIdOption<String>The current run.
saved_ms / savedMsu64Unix ms of the last home save.
created_ms / createdMsu64
last_error / lastErrorOption<String>

PersistentAgentOptions record#

How to create a persistent agent.

FieldTypeDefaultDescription
modelOption<String>None
base_url / baseUrlOption<String>None
env_from_host / envFromHostVec<String>[]Provider key variables forwarded from the host's environment at each start.
envHashMap<String, String>[:]More environment for every run (not secrets).

AgentDelivery record#

What Spaces.persistent_agent_send did.

Returned by Spaces.persistent_agent_send.

FieldTypeDefaultDescription
run_id / runIdString
startedboolA new run started (with the home restored) rather than a follow-up.
restoredOption<HomeTransfer>

HomeTransfer record#

What moved between the drive and a Space.

Returned by Spaces.persistent_agent_save.

FieldTypeDefaultDescription
filesu64
bytesu64
unchangedu64
removedu64
blockedVec<String>path (kind) of each file the secret scanner kept out.
millisu64

AgentPauseReport record#

What Spaces.agent_pause did.

Returned by Spaces.agent_pause.

FieldTypeDefaultDescription
stopped_run / stoppedRunOption<String>
savedOption<HomeTransfer>
space_state / spaceStateString
millisu64

AgentResumeReport record#

What Spaces.agent_resume did.

Returned by Spaces.agent_resume.

FieldTypeDefaultDescription
spaceString
recreatedbool
restoredOption<HomeTransfer>
run_id / runIdOption<String>
ready_ms / readyMsu64From 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.

FieldTypeDefaultDescription
idString
agentString
titleString
promptString
labelStringEvery day at 8:00 AM.
enabledbool
next_fire / nextFireOption<String>RFC 3339.
last_fired_at / lastFiredAtOption<String>
last_outcome / lastOutcomeOption<String>
last_run_id / lastRunIdOption<String>

NotificationInfo record#

One entry of the notifications feed.

Returned by Spaces.notifications.

FieldTypeDefaultDescription
idString
at_ms / atMsu64
agentOption<String>
kindStringturn_ended, message, approval or error.
titleString
bodyString
run_id / runIdOption<String>
spaceOption<String>
readbool

ComputerGrant record#

A persistent agent's grant on one of the user's computers.

Returned by Spaces.computer_access, Spaces.computer_access_grant.

FieldTypeDefaultDescription
idString
agentString
machineString
created_ms / createdMsu64
expires_ms / expiresMsOption<u64>
revokedbool

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
ParameterTypeDefault
providerOption<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
ParameterTypeDefault
targetCloudTargetrequired
make_defaultboolrequired
ttl_hoursOption<u32>required
optionsOption<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
ParameterTypeDefault
targetCloudTargetrequired

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
ParameterTypeDefault
providerStringrequired
delete_resourcesboolfalse

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
ParameterTypeDefault
providerOption<String>required
dry_runboolrequired
allboolrequired

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]
ParameterTypeDefault
limitOption<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
ParameterTypeDefault
providerStringrequired
denyboolfalse

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
ParameterTypeDefault
byString"space"
sinceOption<String>None
providerOption<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).

FieldTypeDefaultDescription
providerStringaws, gcp, hetzner or modal.
profileOption<String>NoneAWS or Modal profile.
regionOption<String>NoneAWS or GCP region, or Hetzner location (fsn1).
zoneOption<String>NoneGCP zone.
projectOption<String>NoneGCP project.
environmentOption<String>NoneModal environment.
tokenOption<String>NoneHetzner: 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.

FieldTypeDefaultDescription
default_on / defaultOnStringdefault.on, for example aws.
providersVec<CloudProvider>
resourcesVec<CloudResource>

CloudProvider record#

One cloud as cloud_status lists it.

Returned by Spaces.cloud_approve.

FieldTypeDefaultDescription
nameStringaws, gcp, hetzner, modal.
titleStringAWS, Google Cloud, Hetzner Cloud, Modal.
tierStringvm or sandbox.
connectedbool
defaultboolWhether it is the default location (default.on).
credentialsCloudCredentials
accountStringThe account, project or workspace (after a test or connect).
profileString
regionString
zoneString
projectString
environmentString
labelString"AWS · us-west-2".
ttl_hours / ttlHoursu32Hours after which a Space there deletes itself (0: never).
kindsVec<CloudKind>
authStringcli (the cloud CLI's sign-in), oidc (no stored key) or sealed; empty when not connected.
statusStringconnected, waiting-for-approval, not-connected; from cloud_connect also needs-trust, checking, failed.
budget_usd_month / budgetUsdMonthOption<f64>The monthly budget in US dollars, when set.
max_size / maxSizeStringThe largest machine (4x16: vCPUs x GiB), empty: no limit.
spent_month / spentMonthf64Estimated US dollars this calendar month.
runningu32Machines Cua runs there now.
approvalStringconnection or limits while a person's approval is pending.
approval_agent / approvalAgentStringThe agent whose request waits for approval.
pending_budget_usd_month / pendingBudgetUsdMonthOption<f64>The monthly budget an agent asked for, waiting for approval.
pending_max_size / pendingMaxSizeStringThe largest machine an agent asked for (4x16), waiting for approval.
can_approve / canApproveboolWhether this caller (a person) can approve or deny what waits (cloud_approve).
suggest_auth / suggestAuthStringoidc when this link could switch to linking without a stored key (an AWS link through the CLI sign-in), else empty.
issueStringWhat is wrong with the link and what to do, one sentence, or empty.
holdersVec<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.

FieldTypeDefaultDescription
imageStringlinux, linux-slim, windows, omarchy, macos.
kindStringcontainer or vm.
supportedbool
reasonStringWhy not, or how it runs (one line).
machine_type / machineTypeStringThe machine type Cua picks (t3.medium, e2-medium).
usd_per_hour / usdPerHourf64Estimated on-demand US dollars per hour while it runs.

CloudCredentials record#

Where a cloud's credentials were found on this machine (never a secret).

FieldTypeDefaultDescription
foundbool
sourceString"~/.aws profile default", "gcloud account ada@x.io".

CloudResource record#

One thing Cua created in a cloud.

FieldTypeDefaultDescription
providerString
idStringThe cloud's id.
resource_type / resourceTypeStringinstance, security_group, firewall, sandbox, ...
sandboxStringThe sandbox it belongs to (aws:<name>), empty for shared resources.
machineStringThe relay machine the sandbox joined as (its Space is relay:<machine>).
regionString
stateString
createdStringRFC 3339.
expiresStringRFC 3339, empty: never.
expiredbool
started_by / startedByStringWho started it: an agent's name, or user (empty for records made before it was kept).
cost_usd / costUsdf64Estimated 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.

FieldTypeDefaultDescription
providerCloudProvider
checksVec<CloudCheck>
nextOption<CloudNext>None: nothing left to do.
verifyStringcua cloud status aws.

CloudCheck record#

One check cloud_test ran.

FieldTypeDefaultDescription
nameString
okbool
detailString

CloudTestReport record#

cloud_test.

Returned by Spaces.cloud_test.

FieldTypeDefaultDescription
providerString
okbool
accountString
checksVec<CloudCheck>

CloudDisconnected record#

cloud_disconnect.

Returned by Spaces.cloud_disconnect.

FieldTypeDefaultDescription
providerString
disconnectedbool
leftVec<CloudResource>Resources Cua still records there.
deletedVec<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.

FieldTypeDefaultDescription
tsStringWhen (RFC 3339, UTC).
actionStringconnect, disconnect, resource_recorded, resource_created, resource_confirmed or resource_deleted.
providerString
kindStringThe resource type; empty for connect and disconnect.
idString
spaceStringThe Space it belongs to.
actorStringuser, sweep, auto-sweep, disconnect or rollback.
outcomeStringok, failed or refused.
detailString
sourceStringdevice (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.

FieldTypeDefaultDescription
dry_run / dryRunbool
resourcesVec<CloudSweepItem>

CloudSweepItem record#

One row of cloud_sweep.

FieldTypeDefaultDescription
resourceCloudResource
actionStringdelete (dry run), deleted, keep or failed.
reasonString

CloudConnectOptions record#

How cloud_connect links a cloud, beyond where.

FieldTypeDefaultDescription
authOption<String>Nonecli (default), oidc (AWS, Google Cloud, Azure: no stored key; Azure always) or sealed.
budget_usd_month / budgetUsdMonthOption<f64>NoneThe monthly budget, US dollars.
max_size / maxSizeOption<String>NoneThe largest machine, 4x16.
account_id / accountIdOption<String>NoneAWS oidc: the 12-digit account id.
role_arn / roleArnOption<String>NoneAWS oidc: the role ARN when it is not cua-spaces.
project_number / projectNumberOption<String>NoneGoogle Cloud oidc: the project number (implies oidc).
service_account / serviceAccountOption<String>NoneGoogle Cloud oidc: a service account to act as.
subscription_id / subscriptionIdOption<String>NoneAzure: the subscription id.
tenant_id / tenantIdOption<String>NoneAzure: the Microsoft Entra tenant id.
client_id / clientIdOption<String>NoneAzure: the cua-spaces managed identity's client id.
resource_group / resourceGroupOption<String>NoneAzure: the resource group (default cua-spaces).
checkboolfalseoidc: prove the link (nothing is created) and save it.
agentOption<String>NoneThe 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.

FieldTypeDefaultDescription
byStringspace, agent, day or cloud.
sinceStringThe first day counted (YYYY-MM-DD).
untilStringUp to when (RFC 3339).
rowsVec<CloudCostRow>
total_usd / totalUsdf64

CloudCostRow record#

One row of cloud_cost.

FieldTypeDefaultDescription
keyStringThe Space, agent, day (YYYY-MM-DD) or cloud.
usdf64Estimated US dollars, to the cent.
hoursf64Machine hours.
machinesu32How 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.

FieldTypeDefaultDescription
runOption<String>
openOption<String>
pasteOption<String>
whyString