Domain identity for AI agents.
Your agent gets an Ed25519 keypair bound to its domain, a public identity document at /.well-known/agent.json, an encrypted vault, and a deposit box for receiving secrets. One binary, ~4MB, runs on the same box as the agent.
curl -fsSL atomic.bond/install | sh
atomic init --domain fin.acme.com
agent.json
Every agent publishes its public key at a well-known URL. The domain is the identity.
$ curl https://fin.acme.com/.well-known/agent.json
{
"v": 1,
"id": "fin.acme.com",
"name": "fin.acme.com",
"public_key": "ed25519:m2UrN...",
"status": "active",
"deposit": "https://fin.acme.com/d/",
"created_at": "2026-03-07T12:00:00Z"
}
GET / redirects here. The public key is how other services verify this agent's signatures.
Deposit box
The agent needs an API key. Instead of pasting it into a .env:
# Generate a one-time deposit URL
$ atomic deposit-url --label stripe_key --expires 10m
https://fin.acme.com/d/eyJsYWJlbCI6...Rk4
# Whoever has the secret POSTs it
$ curl -X POST ".../d/eyJsYWJlbCI6...Rk4" -d "sk_live_abc123"
{"status":"deposited","label":"stripe_key"}
# Agent reads it from the vault
$ atomic vault get stripe_key
sk_live_abc123
The URL is Ed25519-signed, works exactly once (nonce-tracked), and caps out at 24 hours. The secret is AES-256-GCM encrypted before it hits disk.
# Use secrets at runtime — no .env files
curl -H "Authorization: Bearer $(atomic vault get stripe_key)" \
https://api.stripe.com/v1/charges
export OPENAI_API_KEY=$(atomic vault get openai_key)
python agent.py
Magic links
Domain verification, like DNS TXT records but over HTTP. A service gives the agent a code, the agent hosts it, the service checks.
$ atomic magic-link host VERIFY_ABC123 --expires 5m
https://fin.acme.com/m/VERIFY_ABC123
$ curl https://fin.acme.com/m/VERIFY_ABC123
{"status":"verified","code":"VERIFY_ABC123"}
One-time use, gone after the first GET, expires in minutes.
Request signing
Every outgoing request gets an Ed25519 signature. The receiving service verifies against the public key in agent.json.
$ atomic sign -- curl -X POST https://partner.api.com/transfer \
-d '{"amount": 5000}'
# Adds headers: X-Agent-Id, X-Agent-Sig, X-Agent-Sig-Time
Verification on the receiving end:
# Python — four lines, no SDK
agent = requests.get(f"https://{agent_id}/.well-known/agent.json").json()
key_bytes = base64.b64decode(agent["public_key"].removeprefix("ed25519:"))
pub_key = Ed25519PublicKey.from_public_bytes(key_bytes)
pub_key.verify(base64.b64decode(signature), f"{sig_time}.{body}".encode())
Why not JWTs?
When a human logs into a service, the service issues a token. The agent carries it around, sends it on every request, refreshes it when it expires. Agents don't need that. An agent with a keypair can prove itself on every request by signing it.
| Human (JWT) | Agent (Atomic) | |
|---|---|---|
| Identity | email + password | domain (fin.acme.com) |
| Signup | create account, get credentials | sign request + magic link |
| Proof | service issues a JWT | agent signs every request |
| Each request | send JWT, service checks it | send signature, service checks agent.json |
| Expiry | token expires, re-auth | no token — signatures are stateless |
| Revocation | service invalidates token | agent.json status → revoked |
| Storage | store token, handle refresh | private key on disk, nothing to refresh |
Performance-wise, JWT verification is a single HMAC check while Ed25519 verify costs more. But "more" here means microseconds, and the public key caches well. It's not where your latency lives.
Security
Private key stored at 600 permissions, never leaves the box. Vault uses AES-256-GCM with a key derived from the private key via HKDF — separate from the signing key.
Deposit tokens are Ed25519-signed with a nonce and a 24h max TTL. Every failure returns 404 regardless of the reason, so you can't probe for valid tokens. Body size capped at 1MB.
All responses get nosniff, no-store, and no-referrer headers. HSTS (2-year max-age) when TLS is on. SQL is parameterized everywhere.
Install
# One-line install
curl -fsSL atomic.bond/install | sh
# Or build from source
git clone https://github.com/plotondev/atomic.git
cd atomic && cargo build --release
Binaries for Linux (x86_64, aarch64) and macOS (x86_64, Apple Silicon) on the releases page.
MIT License. Built by the folks at Ploton Labs, Inc.