The three scopes
Personal variables are for credentials that belong to you alone: your staging login, your API sandbox key. Thread variables are for handing a value to one running thread without publishing it to the project: the agent asks for a
DATABASE_URL mid-run, you send it, it lands on the thread’s machines immediately.
One caveat on personal values: a machine isn’t single-user. If you share a thread, whoever drives it can read your personal values on that machine, because they’re in the environment like everything else.
What the model sees, and what it can leak
- The model sees variable names and configured-state. Values never enter the prompt, tool arguments, or anything Capy authors.
- Values exist in plaintext exactly where they must: in your write request, briefly in Capy’s worker while assembling the machine’s environment file, and on the machine itself.
- There is no output masking. The agent runs arbitrary commands, and a command that prints a value (
printenv, a stack trace, a verbose CLI) puts that value into tool output, and tool output flows into the thread transcript like any other text.
How values reach a machine
Values are encrypted at rest (each value sealed under a KMS-managed key, bound to its exact project, scope, and name) and decrypted server-side only when a specific machine is being prepared. They’re written to a permission-restricted file outside your repository trees, excluded from diffs and snapshots, and sourced into every shell the agent runs, so test runners, SDKs, and arbitrary commands see them as ordinary environment variables. When values take effect:- Values are written when a machine boots. Editing a shared or personal value affects machines at their next boot; to get a value onto a running thread’s machines right now, send it through the composer’s environment variables dialog, which pushes immediately.
- A running process keeps the environment it launched with until something restarts it.
Snapshots and scrubbing
Snapshot builds receive shared project values so yourinitialize script can authenticate private registries. Before capturing the image, Capy deletes the environment file and every platform-managed sensitive path, then verifies each one is gone. A build that can’t prove the scrub fails rather than baking a secret into a reusable image.
What the scrub can’t prove absent is your own script’s behavior: an initialize that copies a value into a file in the workspace bakes that file into the snapshot. Keep secrets in variables; don’t write them to disk.
What never lands on a machine
- GitHub credentials. Every git operation routes through Capy’s proxy, which injects credentials server-side; the machine holds only a bearer scoped to itself.
- Capy’s own platform secrets (database, KMS, provider keys). The machine has no credential that can read any secret source.
- Other tenants’ anything.