Skip to main content
Projects group sandboxes together with shared configuration defaults and encrypted secrets. When you create a sandbox with a project, it inherits the project’s template, resource limits, and timeout — and secrets are sealed inside the sandbox so they never exist as plaintext in VM memory.

How Secrets Work

When a sandbox is created with a project:
  1. The server decrypts the project’s secrets
  2. Secrets are sent to the worker and sealed into opaque tokens (osb_sealed_...)
  3. Inside the sandbox, env vars contain sealed tokens — never real values
  4. When the sandbox makes an outbound HTTPS request, the MITM proxy intercepts it and replaces sealed tokens with real values in headers and request body
  5. The real secret only exists in the proxy’s memory on the host, never inside the VM

Creating a Project

from opencomputer import Project

project = await Project.create(
    name='my-agent',
    template='default',
    cpu_count=2,
    memory_mb=1024,
    timeout_sec=600,
)

Project.create(**kwargs)

name
str
required
Project name (unique per organization).
template
str
default:""
Default template for sandboxes in this project.
cpu_count
int
default:"0"
Default vCPU count.
memory_mb
int
default:"0"
Default memory in MB.
timeout_sec
int
default:"0"
Default sandbox timeout in seconds.
egress_allowlist
list[str] | None
default:"None"
Allowed egress hosts (e.g. ["api.anthropic.com"]).
Returns: dict — Project info with id, name, template, etc.

Listing Projects

projects = await Project.list()

Project.list(**kwargs)

Returns: list[dict]

Getting a Project

project = await Project.get('project-uuid')

Project.get(project_id, **kwargs)

project_id
str
required
UUID of the project.
Returns: dict

Updating a Project

Partial updates — only the fields you pass are changed.
updated = await Project.update(
    'project-uuid',
    memory_mb=2048,
    timeout_sec=900,
)
# Name, template, cpu_count are preserved

Project.update(project_id, **kwargs)

project_id
str
required
UUID of the project to update.
name
str
default:""
New project name (empty = no change).
template
str
default:""
New default template (empty = no change).
cpu_count
int
default:"0"
New default vCPU count (0 = no change).
memory_mb
int
default:"0"
New default memory in MB (0 = no change).
timeout_sec
int
default:"0"
New default timeout in seconds (0 = no change).
egress_allowlist
list[str] | None
default:"None"
New allowed egress hosts (None = no change).
Returns: dict

Deleting a Project

await Project.delete('project-uuid')
Deletes the project and all its secrets. Running sandboxes are not affected.

Project.delete(project_id, **kwargs)

Returns: None

Setting a Secret

await Project.set_secret('project-uuid', 'ANTHROPIC_API_KEY', 'sk-ant-...')
Secrets are encrypted at rest. The value is never returned by the API.

Project.set_secret(project_id, name, value, **kwargs)

project_id
str
required
UUID of the project.
name
str
required
Secret name (used as the env var name in sandboxes).
value
str
required
Secret value (encrypted at rest, never returned by API).
Returns: None

Listing Secrets

names = await Project.list_secrets('project-uuid')
# ['ANTHROPIC_API_KEY', 'DATABASE_URL']
Returns secret names only. Values are never exposed.

Project.list_secrets(project_id, **kwargs)

Returns: list[str]

Deleting a Secret

await Project.delete_secret('project-uuid', 'DATABASE_URL')

Project.delete_secret(project_id, name, **kwargs)

Returns: None

Creating a Sandbox with a Project

Pass the project parameter to Sandbox.create() to inherit the project’s config and secrets:
from opencomputer import Sandbox

sandbox = await Sandbox.create(
    project='my-agent',
    timeout=600,
)

# Secrets are available as sealed env vars
result = await sandbox.commands.run('echo $ANTHROPIC_API_KEY')
# stdout: "osb_sealed_abc123..." (sealed, not the real key)

# But outbound HTTPS requests get the real value substituted by the proxy
api_result = await sandbox.commands.run(
    'curl -s https://api.anthropic.com/v1/messages -H "x-api-key: $ANTHROPIC_API_KEY" ...'
)
# The proxy replaces the sealed token with the real key before it hits Anthropic
Request-level options (timeout, envs, cpu_count, etc.) override project defaults.