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 (e.g. {{STRIPE_PRIVATE_KEY}})

Example Usage

Before — plain curl

$ curl https://api.github.com/user/repos \
 -H "Authorization: Bearer ghp_R3aLs3cR3tT0k3n..."

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
Read emails
gmail::readonly

Notion
Create pages
notion::write

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.