Overview
Every agent eventually needs to call an external service — GitHub, Slack, your hosting provider — and those services want an API key. You do not want your agent (running model reasoning inside a sandbox) to ever hold that key in memory. The workspace vault is the answer. Secrets live in a dedicated, encrypted vault scoped to the workspace. Each secret is addressed by a bare key name (e.g.github, slack) and stores a JSON object with the provider’s fields. Your agent’s TRIGGER.md declares which key names it needs; at event time the tool bridge fetches the secret value, substitutes it into the outbound HTTP call, and returns only the response. The raw value never crosses the sandbox boundary into the model.
Adding a credential
zombiectl credential add <name> --data=@- stores a JSON-shaped secret in the current workspace’s vault. The name is what you reference from TRIGGER.md.
Always pipe the JSON on stdin (--data=@-) so secrets never appear in shell history or process argv:
op inject to resolve them at the moment of the call — the rendered JSON exists only on the in-memory pipe between op and zombiectl:
/v1/workspaces/{workspace_id}/credentials with the JSON body. Values are encrypted at rest; only the tool bridge can decrypt them when servicing an outbound call.
The default behaviour is skip-if-exists — passing the same name twice is a no-op. Use --force to overwrite an existing credential (rotation).
Exit codes:
0— stored (or skip-if-exists).1— no workspace selected, or API error.2— missing<name>, missing--data, or invalid JSON.
Listing credentials
zombiectl credential list returns the names and creation timestamps of every credential in the current workspace. Values are never returned. This is by design — once stored, a secret is only ever used by the firewall.
--json for machine-readable output.
Referencing credentials from TRIGGER.md
An agent declares the credentials it needs as a list of bare key names in its TRIGGER.md frontmatter. Nothing else — no URI scheme, no path, no secret-manager-specific prefix. The names are looked up verbatim against the workspace vault.
zombiectl install --from <path> is called, install fails with a clear error listing the missing names.
Rotation
Rotating a credential is a single command — no re-install is needed. The next event handled by any agent using that credential picks up the new value.--force is required to overwrite an existing credential — without it, the default skip-if-exists behaviour leaves the old value in place.
Deletion
zombiectl credential show <name> prints metadata (creation timestamp, last-rotated) but never the value. The vault is one-way: write at the boundary, read only by the firewall.
What the agent can and cannot see
| Thing | Can the agent see it? |
|---|---|
The credential’s name (github, slack) | Yes. It’s the key the SKILL prose references. |
| The credential’s value (the raw secret) | No. The tool bridge injects and strips it outside the sandbox. |
| The response body from the external service | Yes. The agent needs the data to reason about what to do next. |
| Any headers the external service set | Yes, unless they carry sensitive tokens — the tool bridge redacts known-sensitive header names. |