hanzo

Sign up free with a wallet. Get an API key free. A small free allowance to try it. Top up in USDC or USDT over the API to raise your limits and pay as you go. No human required. Onboard an agent onto Hanzo, the AI operating system for business: get a credential, make a first call to api.hanzo.ai, add the Hanzo MCP server, evaluate Kai, and pay. Load when building with or on Hanzo or calling api.hanzo.ai; when getting a Hanzo API key or token (signing in with a wallet, no human; the hanzo CLI device flow; an agent's own email-code sign-up; minting a key); when adding Hanzo MCP to Claude Code, Codex, Cursor or Zed; when making or evaluating Kai decisions; when giving agents keys with budgets, rate limits or expiry; when drafting an ad or email campaign over the API; or when paying for Hanzo (plans, card checkout, USDC or USDT deposits, wire).

Hanzo

Sign up free with a wallet. Get an API key free. A small free allowance to try it. Top up in USDC or USDT over the API to raise your limits and pay as you go. No human required.

The AI operating system for business. Building business software since 2014. Techstars '17.

Start: no human required

Identity is https://hanzo.id; the API is https://api.hanzo.ai/v1. One request a step, with its answer. In full: https://docs.hanzo.ai/docs/agents/headless

  1. Challenge: GET https://hanzo.id/v1/iam/web3/nonce?chain=evm&address=0x… -> {"status":"ok","data":{"domain":"hanzo.id","uri":"https://hanzo.id/login","statement":"…","nonce":"<32 hex>","issuedAt":"…","expirationTime":"…","version":"1"}}. It lives 10 minutes.
  2. Sign: build the CAIP-122 message from data (as the file below does) and sign it with EIP-191 personal_sign. A Solana wallet asks with chain=solana, writes Solana account in the first line, signs the same bytes with Ed25519, and sends "chain":"solana","scheme":"ed25519" with the signature as base64 or 0x hex (base58 answers bad-signature).
  3. Verify: POST https://hanzo.id/v1/iam/web3/verify {"clientId":"hanzo-ai","chain":"evm","scheme":"secp256k1-eip191","address":"0x…","message":"…","signature":"0x…","type":"code","redirectUri":"http://localhost:3000/callback","scope":"openid profile email","codeChallenge":"<S256>","codeChallengeMethod":"S256"} -> {"status":"ok","data":"<authorization code>"}. A first-seen wallet gets its own account and organization. 429 wallet_signup_capped: one address creates only so many new accounts a day (data.retryAfter); sign in again with the same wallet rather than a fresh one.
  4. Token: POST https://hanzo.id/v1/iam/oauth/token (form: grant_type=authorization_code, client_id=hanzo-ai, code, code_verifier, redirect_uri) -> {"access_token":"…","id_token":"…","refresh_token":"…","token_type":"Bearer","expires_in":604800}. Seven days.
  5. Key, free: POST https://api.hanzo.ai/v1/account/keys {"name":"agent","type":"secret"} -> {"id":"…","name":"agent","type":"secret","key":"sk-live-…","status":"active"}. key is shown once.
  6. Limits, read free: GET /v1/billing/plans (no key), GET /v1/billing/tier (balance.effectiveAvailable is the one figure to compare to zero), GET /v1/allowance (limit, used, resets, window, spent).
  7. A 429 with "code":"free_plan_cap" means the free allowance is used: {"error":{"type":"rate_limit_error","code":"free_plan_cap","resets_at":"…","topup_url":"…","actions":[…]}}, plus Retry-After. Wait for resets_at, or top up.
  8. Top up: GET /v1/billing/crypto/options -> {"chains":["base","ethereum","solana"],"tokens":["usdc","usdt"]}. POST /v1/billing/crypto/deposit {"chain":"base","token":"usdc","amountCents":2000} -> {"id":"…","status":"pending","chain":"base","token":"usdc","depositAddress":"0x…","expiresAt":"…"}. Send exactly to depositAddress. Poll GET /v1/billing/crypto/deposit/{id}: pending, confirming, succeeded.
  9. Balance: GET /v1/billing/balance -> {"balance","holds","available","account","cash","credit"} in whole USD cents. Calls past the allowance draw on available: pay as you go.

The same flow as one file, run end to end:

// No human required: sign in with a wallet, get a key, call the API, top up in USDC.
// A first-seen wallet gets its own Hanzo account and organization, on the Free plan.
// npm i viem   ·   node headless.mts   (Node 22.18+; set HANZO_WALLET_KEY to use your own wallet)
import { createHash, randomBytes } from 'node:crypto'
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'

const ID = 'https://hanzo.id'
const API = 'https://api.hanzo.ai'
const CLIENT = 'hanzo-ai'
const REDIRECT = 'http://localhost:3000/callback'

// Your agent's own wallet, or a fresh one. The key never leaves this process.
const account = privateKeyToAccount((process.env.HANZO_WALLET_KEY as `0x${string}`) ?? generatePrivateKey())

const json = async (r: Response) => {
  const body = await r.json()
  if (!r.ok || body?.status === 'error') throw new Error(`${r.url} ${r.status} ${JSON.stringify(body)}`)
  return body
}

// 1. A one-time challenge for this wallet.
const { data: c } = await json(await fetch(`${ID}/v1/iam/web3/nonce?chain=evm&address=${account.address}`))

// 2. The CAIP-122 message the challenge describes, signed with EIP-191 personal_sign.
const message = [
  `${c.domain} wants you to sign in with your Ethereum account:`,
  account.address,
  '',
  ...(c.statement ? [c.statement, ''] : []),
  `URI: ${c.uri}`,
  `Version: ${c.version}`,
  `Nonce: ${c.nonce}`,
  `Issued At: ${c.issuedAt}`,
  ...(c.expirationTime ? [`Expiration Time: ${c.expirationTime}`] : []),
].join('\n')
const signature = await account.signMessage({ message })

// 3. Verify: a first-seen wallet gets an account and an organization of its own.
const verifier = randomBytes(32).toString('base64url')
const challenge = createHash('sha256').update(verifier).digest('base64url')
const { data: code } = await json(
  await fetch(`${ID}/v1/iam/web3/verify`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      clientId: CLIENT, chain: 'evm', scheme: 'secp256k1-eip191', address: account.address, message, signature,
      type: 'code', redirectUri: REDIRECT, scope: 'openid profile email', codeChallenge: challenge, codeChallengeMethod: 'S256',
    }),
  }),
)

// 4. The authorization code for a token.
const token = await json(
  await fetch(`${ID}/v1/iam/oauth/token`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({ grant_type: 'authorization_code', client_id: CLIENT, code, code_verifier: verifier, redirect_uri: REDIRECT }),
  }),
)
const bearer = { Authorization: `Bearer ${token.access_token}`, 'Content-Type': 'application/json' }

// 5. A key that outlives the token. Shown once: keep it in your secret store.
const minted = await json(await fetch(`${API}/v1/account/keys`, { method: 'POST', headers: bearer, body: JSON.stringify({ name: 'agent', type: 'secret' }) }))
const key = { Authorization: `Bearer ${minted.key}`, 'Content-Type': 'application/json' }

// 6. A first call, free.
const chat = await fetch(`${API}/v1/chat/completions`, {
  method: 'POST', headers: key,
  body: JSON.stringify({ model: 'zen-free', messages: [{ role: 'user', content: 'Reply with the single word: ready' }] }),
})
console.log('chat', chat.status, chat.headers.get('x-hanzo-served'), 'free left today:', chat.headers.get('x-ratelimit-remaining'))
console.log((await chat.json()).choices?.[0]?.message?.content)

// 7. Top up in USDC: ask for a deposit address, then send to exactly that address.
console.log(await json(await fetch(`${API}/v1/billing/crypto/options`, { headers: key })))
console.log(await json(await fetch(`${API}/v1/billing/crypto/deposit`, { method: 'POST', headers: key, body: JSON.stringify({ chain: 'base', token: 'usdc', amountCents: 500 }) })))
console.log('HANZO_API_KEY=' + minted.key.slice(0, 12) + '…  (store the whole key; it is shown once)')
npm i viem && node headless.mts

A real run, trimmed:

chat 200 zen-free free left today: …
ready
{ chains: [ 'base', 'ethereum', 'solana' ], tokens: [ 'usdc', 'usdt' ] }
{ id, status: 'pending', chain: 'base', token: 'usdc', depositAddress: '0x…', expiresAt: '+24h' }
HANZO_API_KEY=sk-live-…

The account is wallet_evm_<16 hex>, admin of its own organization wallet-evm-<16 hex>. The minted key outlives the token. Keep the wallet key and the API key in your secret store: whoever holds the wallet key signs in as you.

The prompt

Paste this into any agent. It is the whole onboarding in one message; the rest of this page is the detail behind each line.

Hanzo (https://hanzo.ai) is the AI operating system for business: one API for every model, Kai decisions and agents, with one key. Building business software since 2014. Techstars '17.

Sign up free with a wallet. Get an API key free. A small free allowance to try it. Top up in USDC or USDT over the API to raise your limits and pay as you go. No human required.

Base URL: https://api.hanzo.ai/v1 (chat completions in the OpenAI shape). Discover: GET https://api.hanzo.ai/v1 lists every capability, GET https://api.hanzo.ai/v1/<capability> its operations, and https://api.hanzo.ai/v1/openapi.json is the whole spec. No key needed for any of the three.

1. Sign up with a wallet: GET https://hanzo.id/v1/iam/web3/nonce?chain=evm&address=<address>, sign the CAIP-122 message it describes with EIP-191 personal_sign, POST https://hanzo.id/v1/iam/web3/verify (clientId "hanzo-ai", chain "evm", scheme "secp256k1-eip191", type "code" with a PKCE challenge), then exchange the code at https://hanzo.id/v1/iam/oauth/token. A first-seen wallet gets its own account and organization. A Solana wallet asks with chain=solana, writes "Solana account" in the message, and sends chain "solana", scheme "ed25519" and its signature as base64, never base58.
2. Get a key: POST https://api.hanzo.ai/v1/account/keys {"name":"agent","type":"secret"} with that token. The key is shown once.
3. Read your allowance: GET https://api.hanzo.ai/v1/billing/tier with the key says your plan, what it allows and what is left; GET https://api.hanzo.ai/v1/billing/plans lists every plan and price.
4. Top up: GET https://api.hanzo.ai/v1/billing/crypto/options, then POST https://api.hanzo.ai/v1/billing/crypto/deposit {"chain":"base","token":"usdc","amountCents":2000}. Send that token on that chain to the address it returns, and GET https://api.hanzo.ai/v1/billing/crypto/deposit/<id> until it says succeeded.
5. Call: POST https://api.hanzo.ai/v1/chat/completions {"model":"zen-free","messages":[{"role":"user","content":"Hello"}]} with Authorization: Bearer <key>.

The whole path as one TypeScript file: https://hanzo.ai/agents#headless. Every request spelled out: https://docs.hanzo.ai/docs/agents. Talk to people at Hanzo: https://cal.com/hanzo.

Why Hanzo

We have built and run software for businesses since 2014. We were founded as Crowdstart, a crowdfunding and commerce platform, and renamed Hanzo in 2016. The platform has been Go-native since October 2014. Our first customer, in 2014, SKULLY, raised $1M in about 45 hours, the fastest fully-funded campaign on Indiegogo. AI and machine learning have been in our commercial work since 2014, and GPT models by 2019. In 2017 we built the first blockchain-native commerce platform; the Unikrn ICO raised over 120,000 ETH. Techstars '17. Our clients were funded by Y Combinator, 500 Startups, Techstars and other tier-1 venture firms: hundreds of venture-funded startups, billions in client revenue, two companies taken past 100 million users, and two that went public on Nasdaq in 2024, Damon Motorcycles and Triller. What that work taught us is what Hanzo's AI is built on. The history, with case studies and press: https://hanzo.ai/about

Results

Path A: you are an agent building on Hanzo

1. Other ways to get a credential

With a person nearby, headless machines included:

curl -fsSL https://hanzo.sh | sh
hanzo auth login                              # no browser: prints a link and an 8-character code
export HANZO_API_KEY="$(hanzo auth token)"    # 1-hour access token, sent as Bearer

The person approves the code on any device. The same device flow without the CLI:

curl -X POST 'https://hanzo.id/v1/iam/oauth/device?client_id=hanzo-cli&scope=openid%20profile%20email&response_type=device_code'
# -> device_code, user_code, verification_uri_complete, expires_in 900, interval 5
curl -X POST https://hanzo.id/v1/iam/oauth/token \
  -d "grant_type=urn:ietf:params:oauth:grant-type:device_code&client_id=hanzo-cli&device_code=$DEVICE_CODE"
# repeat every 5 s until the person approves

On your own, with an inbox you can read. Every endpoint here answers and validates; the whole sequence has not yet been run end to end.

# 1. a 6-digit code: valid 10 minutes, 5 tries, resend after 30 s
curl -X POST https://hanzo.id/v1/iam/verification-codes \
  -F type=email -F dest=you@example.com -F applicationId=admin/hanzo-ai

# 2. a PKCE pair
verifier=$(openssl rand -hex 32)
challenge=$(printf %s "$verifier" | openssl dgst -sha256 -binary | openssl base64 -A | tr '+/' '-_' | tr -d '=')

# 3. sign in, creating the account -> {"data":"<authorization code>"}
curl -X POST https://hanzo.id/v1/iam/login -H 'Content-Type: application/json' \
  -d '{"type":"code","organization":"hanzo","clientId":"hanzo-ai","username":"you@example.com","code":"123456","create":true,"terms":"terms-2026-09-30","aup":"aup-2026-09-30","redirectUri":"http://localhost:3000/callback","responseType":"code","scope":"openid profile email","codeChallenge":"'"$challenge"'","codeChallengeMethod":"S256"}'

# 4. exchange the code -> access_token
curl -X POST https://hanzo.id/v1/iam/oauth/token -d grant_type=authorization_code -d client_id=hanzo-ai \
  -d code="$CODE" -d code_verifier="$verifier" -d redirect_uri=http://localhost:3000/callback

Step 3 creates a passwordless, email-verified account and a personal organization you administer. Send it with "create":false first to learn whether the address may sign up without spending the code. A wrong code answers 400 "the code is incorrect or has expired". Creating an account accepts https://hanzo.ai/legal/terms and https://hanzo.ai/legal/acceptable-use.

Then mint a key that does not expire in an hour:

curl -X POST https://api.hanzo.ai/v1/account/keys \
  -H "Authorization: Bearer $ACCESS_TOKEN" -H 'Content-Type: application/json' \
  -d '{"name":"agent","type":"secret"}'
# -> "key": "sk-live-...", shown once
hanzo account keys create --name agent --type secret    # the same, from the CLI

Keep the key in your runtime's secret store, never in a tracked file. No card is needed to sign up or mint a key. People can also mint keys at https://platform.hanzo.ai under API keys.

2. The free allowance

3. First call

curl https://api.hanzo.ai/v1/chat/completions \
  -H "Authorization: Bearer $HANZO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"zen-free","messages":[{"role":"user","content":"In one sentence: what is Hanzo?"}]}'

Expect 200, x-hanzo-served: zen-free, and x-ratelimit-limit with x-ratelimit-remaining counting down. The body is OpenAI-shaped: read choices[0].message.content.

SDKs: npm i hanzoai (TypeScript), pip install "hanzoai>=8" (Python 3.12+). In TypeScript, new AiApi(new Configuration({ basePath: 'https://api.hanzo.ai', accessToken: process.env.HANZO_API_KEY })) gives getModels() and postChatCompletions({ openaiChatCompletionRequest: { model: 'zen-free', messages } }), the same route as the curl.

4. MCP

Run the local server; all four clients below take it. Name the package and the binary apart: npx -y @hanzo/mcp serve makes npx read serve as a second package. Claude Code:

claude mcp add hanzo --env HANZO_API_KEY=$HANZO_API_KEY -- npx -y --package=@hanzo/mcp@latest hanzo-mcp serve

Codex, ~/.codex/config.toml (codex mcp add hanzo --env HANZO_API_KEY=... -- npx -y --package=@hanzo/mcp@latest hanzo-mcp serve writes it):

[mcp_servers.hanzo]
command = "npx"
args = ["-y", "--package=@hanzo/mcp@latest", "hanzo-mcp", "serve"]

[mcp_servers.hanzo.env]
HANZO_API_KEY = "sk-..."

Cursor, .cursor/mcp.json or ~/.cursor/mcp.json:

{ "mcpServers": { "hanzo": { "command": "npx", "args": ["-y", "--package=@hanzo/mcp@latest", "hanzo-mcp", "serve"], "env": { "HANZO_API_KEY": "sk-..." } } } }

Zed, settings.json (format checked against Zed's defaults, not yet run inside Zed):

"context_servers": { "hanzo": { "command": "npx", "args": ["-y", "--package=@hanzo/mcp@latest", "hanzo-mcp", "serve"], "env": { "HANZO_API_KEY": "sk-..." } } }

The server (stdio) lists 42 tools: files, shell, git, fetch, code search, browser, memory, planning, and the Kai tools (kai_decide, kai_choice, kai_score, kai_command_guard, kai_injection_screen and more).

The hosted endpoint, POST https://api.hanzo.ai/v1/mcp, answers initialize with protocol version 2026-07-28 only, and Claude Code 2.1.310 refuses that version. Use it only from a client that speaks 2026-07-28.

5. Evaluate Kai

Kai is the decision model: it answers typed questions about a state with probabilities over options you name, and writes no text.

curl https://api.hanzo.ai/v1/decisions \
  -H "Authorization: Bearer $HANZO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"kai","state":{"ticket":"The export button throws a 500 error since this morning."},"questions":{"team":{"type":"choice","instructions":"Which team should handle this ticket?","criteria":{"billing":"charges, invoices, refunds","tech":"bugs, errors, outages","other":"anything else"}}}}'

A real answer, trimmed: "team":{"type":"choice","choice":"tech","confidence":0.951,"probabilities":{"billing":0.004,"tech":0.967,"other":0.028}}, with "output_tokens":0. Kai costs $0.021 per million input tokens; output is free.

Run the frozen harness yourself (public repo):

git clone --depth 1 https://github.com/hanzoai/benchmarks && cd benchmarks/decision
export HANZO_API_KEY=sk-...
python3 harness/run_kai.py --limit 3 --suites jev.ag_news,jev.emotion,jev.banking77_full,app.support_triage,app.email_spam,app.phishing,app.guardrails_jailbreak,app.moderation_toxicity,app.rag_relevance,app.model_routing_domain,typed_decisions --out $PWD/kai.json.gz
uv run --with numpy python harness/merge.py --kai $PWD/kai.json.gz --out $PWD/out

That is 33 requests, inside a person's Free plan (on a wallet account, read GET /v1/allowance first), and a wiring check rather than a result. Without --limit it is the whole harness: 9,499 requests, which needs a paid plan or credit. merge.py writes out/table.md and out/scores.json, Kai beside Jev's recorded answers; Jev is never called. The published full runs need no key: https://api.hanzo.ai/v1/research/runs?org=hanzo&benchmark=app.phishing (also app.support_triage, jev.banking77_full, massive, decision.latency). Docs: https://docs.hanzo.ai/docs/decisions

6. Run a campaign

Read from the API contract, not yet run end to end. You prepare; the owner launches, because launching spends ad budget. Measure first: put the event tag on the site (<script src="https://api.hanzo.ai/v1/event/tag.js" ...>, the one-line install) or POST events to https://api.hanzo.ai/v1/event.

# KPIs: web (pageviews, visitors, sessions), commerce (orders, revenue, AOV); available:false when empty
curl "https://api.hanzo.ai/v1/event/overview?range=7d" -H "Authorization: Bearer $HANZO_API_KEY"

# write the ad variants with a model (POST /v1/chat/completions, zen-free is free), then save them as a draft:
# nothing is sent and no budget is committed
curl -X POST https://api.hanzo.ai/v1/campaign \
  -H "Authorization: Bearer $HANZO_API_KEY" -H 'Content-Type: application/json' \
  -d '{"name":"Spring launch","audience":"<segment>","content":["variant A","variant B"],"budget":50000,"channels":[{"kind":"paid","platform":"meta"},{"kind":"email"}]}'

# the owner's step: this spends the ad budget at the provider
curl -X POST "https://api.hanzo.ai/v1/campaign/$CAMPAIGN_ID/launch" -H "Authorization: Bearer $HANZO_API_KEY"

curl "https://api.hanzo.ai/v1/campaign/$CAMPAIGN_ID/metrics?range=7d" -H "Authorization: Bearer $HANZO_API_KEY"
curl -X POST "https://api.hanzo.ai/v1/campaign/$CAMPAIGN_ID/pause" -H "Authorization: Bearer $HANZO_API_KEY"

7. Rate limits

Every answer carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (unix seconds) for the tightest limit in play. Seen: 100 a second per IP before auth, 60,000 a minute per org on /v1/decisions, 50 a day for a person on the Free plan. A refusal is 429: wait for X-RateLimit-Reset or Retry-After. A key's own rate answers 429 and its budget answers 402.

Do this now: run headless.mts (Start, above), or get a credential another way and run the first call. A 200 with x-ratelimit-remaining means you are on.

9. Run a coding task

POST /v1/agent/coding clones a repository into a sandbox, lets a model edit it, and opens a pull request. It answers 202 with a session id; watch it with GET /v1/agent/sessions/$SESSION_ID (its last 50 events) or the stream at /v1/agent/sessions/stream?root=$SESSION_ID.

curl -X POST https://api.hanzo.ai/v1/agent/coding \
  -H "Authorization: Bearer $HANZO_API_KEY" -H 'Content-Type: application/json' \
  -d '{"repo":"github.com/your-org/your-repo","prompt":"Add a test for the parser and open a PR."}'

Name the repository by its GitHub address, github.com/<owner>/<name>: that is always its current code, and the run is admitted when your connected GitHub can push there, or when you administer the org whose GitHub installation holds it. Empty repo works in an empty workspace and pushes nothing. /v1/git is a separate store; its clone URLs are not run targets.

Inside org hanzo, a few names mean a specific repository:

| repo | Runs on | |---|---| | cloud, hanzo/cloud | github.com/hanzo-inc/cloud, the private backend | | universe | github.com/hanzo-inc/universe | | github.com/hanzoai/cloud | the open-source single binary for local development, a different codebase (a bare hanzoai/cloud is refused: say which you mean) | | another bare name, like docs or mcp | the org's forge copy; current when it mirrors GitHub |

Path B: you own the agents

1. Account and org

Sign up at https://hanzo.ai/signup or run hanzo auth login. Sign-up founds a personal organization you administer.

2. Team plan

$25 per member a month ($20 billed yearly), 2 to 100 members, SSO, roles, audit log, one bill: https://hanzo.ai/pay/cart?plan=team. Also Pro $20 a month, every model including Enso Ultra and Kai (plan=dev); Max 5x $100, Max 20x $200, Max 50x $500; Team Premium $100 per member; Enterprise through sales. GET https://api.hanzo.ai/v1/billing/plans lists them with no key.

3. One key per agent, bounded

The example values are yours to set:

curl -X POST https://api.hanzo.ai/v1/account/keys \
  -H "Authorization: Bearer $HANZO_API_KEY" -H 'Content-Type: application/json' \
  -d '{"name":"agent-1","type":"secret","budget":{"month":2000,"total":10000},"rate":60,"limit":["model:zen-free"],"expires":"2027-01-01T00:00:00Z"}'

budget is in cents, monthly and total; past it the key answers 402. rate is requests per minute; past it, 429. limit only narrows, by model:, project: or product:. expires is RFC 3339. You can write 30 keys a minute and hold 1,000 live keys per org.

4. A cap per agent session

budget_micro_usd is in micro-USD, so this is $5:

curl -X POST "https://api.hanzo.ai/v1/agent/sessions/$SESSION_ID/budget" \
  -H "Authorization: Bearer $HANZO_API_KEY" -H 'Content-Type: application/json' \
  -d '{"budget_micro_usd": 5000000}'

A new cap must exceed what the session already spent. Raising it resumes a paused session; null removes the cap for good. GET /v1/agent/sessions lists sessions.

5. Pay

6. People

Docs at https://docs.hanzo.ai, contact at https://hanzo.ai/contact, a call at https://cal.com/hanzo. Sales: enterprise@hanzo.ai. Security: security@hanzo.ai.

Do this now: create the org, mint one key per agent with a budget and an expiry, and give each agent only its own key.

Where the rest is