Architecture overview

How Keychains works.

Your agent gets the access. Never the keys.

Step 1

Drop-in replacement

Use keychains curl as a drop-in replacement for curl, or the Keychains SDK as a drop-in replacement for your favorite HTTP library (fetch for Node.js, requests for Python, etc).

The only difference: replace any hard-coded credentials with a template variable.

Template variables

  • {{OAUTH*_TOKEN}}OAuth1 and OAuth2 access/refresh/request token (provider auto-detected from URL)
  • {{ANY_NAME}}Any non-OAUTH* string is treated as an API key name (eg {{STRIPE_PRIVATE_KEY}})
Before — plain curl
$ curl https://api.github.com/user/repos \
-H "Authorization: Bearer ghp_R3aLs3cR3tT0k3n..."
Secret exposed in code
After — keychains curl
$ keychains curl https://api.github.com/user/repos \
-H "Authorization: Bearer {{GITHUB_TOKEN}}"
No secrets in code — credentials injected server-side
Permission Request
from "research-agent"
Gmail
Gmail
Read emails
Notion
Notion
Create pages
Approve
Deny
Step 2

User authorizes the action

When your agent runs the request, if the required credentials haven't been authorized yet, Keychains returns a 403 with an authorization URL. Forward this URL to the user — they see exactly what access is being requested and approve with one click.

  • User sees the agent name, the APIs, and the exact scope
  • One-click approval — no OAuth dance for the user
  • Permissions are task-scoped, not blanket access
Step 3

Next call just works

Once the user has approved, retry the same request. Keychains injects the right credentials server-side and forwards the request to the target API. The agent never sees the raw secrets.

  • Credentials injected server-side — invisible to prompt injection
  • Every call logged in a complete audit trail
  • Users can revoke access at any time from the dashboard
Terminal
# Same call again — works instantly
$ keychains curl https://api.github.com/user/repos \
-H "Authorization: Bearer {{GITHUB_TOKEN}}"
> 200 OK — 42 repositories

Machine identity & permissions

Each machine automatically gets an SSH key pair on first run. This key pair is used to cryptographically identify the machine and can emit multiple permission requests — one per task if needed — each with its own scoped rights.

Automatic SSH keypair

Ed25519 keypair generated locally on first run. Private key never leaves the machine. No manual setup required.

Per-task permissions

Each machine can emit multiple permission requests — one per task if desired. Each permission has its own scoped rights, independent of others.

Stateful fingerprinting

A rolling hash chain detects stolen keys on first unauthorized use. Both real and attacker machines are flagged immediately.

Delegation for multi-agent systems

When your agent needs to spawn sub-agents, Keychains gives you two patterns:

Scoped delegation

Create a delegate token with a subset of your permissions. The sub-agent can only access the APIs you explicitly allow.

$ keychains delegates add pr_a1b2c3 \
--scopes github::repo,notion::read \
--name "code-reviewer"

Zero-permission tokens

Spawn a sub-agent with no initial access. It must request approval from the user for each API it needs — maximum security.

$ keychains delegates add pr_a1b2c3 \
--wildcard \
--name "untrusted-plugin"

Users stay in control. Always.

The Keychains dashboard gives users complete visibility into what agents have access to. They can review permissions, see activity, and revoke access — at any time, with one click.

  • See all active machines and their permissions
  • View which APIs each agent has accessed
  • Revoke any permission instantly
Active Machines
research-agent
Gmail, Notion
Revoke
code-reviewer
GitHub
Revoke
data-analyst
Stripe, Airtable
Revoke

Ready to build secure agents?

Get started in under a minute. Just prefix curl with keychains — that's it.