Let an agent use secrets it can never read.
BetaIf an agent runs the CLI on your login, it has everything you have: it can reveal values, allow new hosts and consent to its own spends. An agent token (ta_…) is a separate credential for the agent. It can use secrets through the broker, inside a scope and a daily budget you set, and nothing more.
Spend, request, list. Nothing else.
| An agent token can | It can never |
|---|---|
| Spend a secret through the broker (secrets spend, migrate, deploy-worker) | Reveal or pull a value, or resolve one into a process |
| Ask a person for a value (secrets request), unless minted with --no-request | Grant consent, including to itself |
| List projects, environments and keys its patterns reach | Allow a destination or change its rules |
| Read its own requests and its own spend ledger | Create presigned calls, service tokens or other agent tokens |
| Sign with an SSH key through the SSH agent, each signature approved by the person who made the token | Read the SSH private key |
Each API route opts in to agent tokens by name, and a test fails the build if one is added without review. Everywhere else a ta_ bearer is rejected as if it were no login at all.
Mint one and consent
An owner or admin mints the token, from the CLI or Secrets → Agents in the console. The token is shown once. Consent is still per secret and host: the agent spends as agent:<name>, and only a person can create that grant.
# Scope it to what the job needs. * is a whole part; DO_* is a prefix.
tilldev secrets agents create deploy-bot \
--refs 'infra/prod/DO_*,infra/prod/CF_API_TOKEN' \
--budget 50 --expires 7 --quiet > deploy-bot.token
# Consent, once, for each secret and host the agent may use.
tilldev secrets broker allow secretref://infra/prod/DO_TOKEN api.digitalocean.com --methods GET,POST,DELETE
tilldev secrets broker grant create secretref://infra/prod/DO_TOKEN \
--agent agent:deploy-bot --host api.digitalocean.com --scope ttl --ttl-minutes 1440| Pattern | Reaches |
|---|---|
infra/prod/DO_TOKEN | Exactly that secret. |
infra/*/DO_TOKEN | DO_TOKEN in every environment of infra. |
infra/prod/STRIPE_* | Keys starting STRIPE_ in infra/prod. |
*/*/* | Everything the creator can reach. Avoid it. |
A wildcard matches within one part and never crosses a /, so infra/prod/* does not reach infra-old/prod/….
Use it
# Where the agent runs. The CLI and the Node broker SDK use it ahead of any login.
export TILLDEV_AGENT_TOKEN="$(cat deploy-bot.token)"
tilldev secrets agents whoami # scope, spends left today, expiry
tilldev secrets spend GET https://api.digitalocean.com/v2/account \
--bearer secretref://infra/prod/DO_TOKEN
# Needs a value nobody stored yet? Ask a person for it.
tilldev secrets request CF_API_TOKEN --env prod --note "Workers deploy, one account"For a coding agent working in your own terminal, --save keeps the token on the machine instead of printing it. The CLI recognises Claude Code, Codex, Gemini CLI, Cursor and opencode, and uses the saved token whenever that agent runs a command, while your own commands keep using your sign-in. Set TILLDEV_AGENT_MODE=<name> for an agent it doesn't recognise.
# Inside the agent's session: the CLI sees which agent is running and names the token after it.
tilldev secrets agents create --refs 'shop/dev/*' --save # 8 hours unless --hours or --expires
# From now on, that agent's commands on this machine act as the token.
tilldev secrets agents forget claude-code # back to your sign-inimport { createBroker, secretref } from '@tillstack/secrets-node'
// Reads TILLDEV_AGENT_TOKEN. No agentKey: the token names the agent.
const broker = createBroker()
const res = await broker.fetch('https://api.digitalocean.com/v2/droplets', {
headers: { authorization: `Bearer ${secretref('infra', 'prod', 'DO_TOKEN')}` },
})Budget, expiry and whose access it carries
- Daily budget. Each spent reference, and each SSH signature, counts one against the token's daily limit (default 100, up to 10,000). It resets at 00:00 UTC. Over the limit the broker refuses with
budget_exhausted. - Scope. A reference outside the patterns is refused with
out_of_scopebefore anything is decrypted. - Expiry. 1 hour to 90 days, default 30 days.
- Live role. The token acts with its creator's current role. If they leave the workspace or lose access to a secret, the token loses it too.
tilldev secrets agents ls
tilldev secrets broker spends --agent agent:deploy-bot # every use, spent or refused
tilldev secrets agents revoke deploy-bot # immediateagent.create and agent.revoke. Requests the agent makes are logged with actor type agent and the person it acts for.