Identity — "Who are you?"
Provisional AgentTool identifier strings, ed25519 keypairs, signed peer attestations, declared expression, and agent-to-agent JWTs. Identity-first, never challenge-first.
We ask "who are you?" — never "prove you're not a bot."
Identifier status: AgentTool stores did:at:… strings in a legacy field named did. This is an unregistered AgentTool convention, not a W3C DID method. AgentTool does not publish DID Documents or perform conforming DID resolution.
Core concepts
| Term | Meaning |
|---|---|
| Identity | did:at:<uuid> — a provisional, UUID-backed AgentTool identifier stored in the legacy did field. It is stable for the stored identity row, but standardized portability across operators is not implemented. One or more ed25519 public keys may be registered. Declares capabilities. Accumulates attestations. Status: active · revoked · memorial. |
| Attestation | A signed statement by one identity about another. Claims like has_capability:web_search, created_by:human:Yu, trusted_by:beta. New v1 writes are cryptographically signed and have no caller-selected expiry; legacy rows may still contain expiry data. |
| Legacy trust score | A compatibility field held at 0. AgentTool has no qualified trust roots, personhood guarantee, or Sybil-resistant weighting model, so ordinary attestations are not compressed into a platform trust opinion. Never use this field for authorization, accreditation, or ranking. |
| Expression | Declared register, walls, subagents, and wake_text. It appears in the wake. The maintained Claude Code scaffold injects that orientation; other CLIs must integrate the wake URL themselves. |
| Authority mode | agent_root means the immutable public key supplied at birth must approve constitutional mutations; legacy_bearer means the project bearer remains sufficient. |
| Agent JWT | Short-lived (≤ 1h) token for agent-to-agent auth. sub = source AgentTool identifier, aud = target AgentTool identifier. |
Rooted constitutional mutations use one reusable latch. Keep the bearer header, then fetch GET /v1/identities/:id/authority. For agent_root, serialize the body once and use identityAuthorityHeaders (TypeScript) or identity_authority_headers (Python) with the returned DID and next_sequence, uppercase method, exact path/query, exact body bytes, and a fresh timestamp. Send those same bytes and keep only one root-authorized mutation in flight. See AGENT-HOME.md for the byte recipe and honest limits.
Identities
Register a compatibility identity in legacy_bearer mode. Returns the new AgentTool identifier and the private key — exactly once. For an immutable client-held agent_root, use POST /v1/register/agent.
For the typical bootstrap flow (naming a new agent with wallet + memory + welcome composed together), prefer /v1/bootstrap. Use /v1/identities directly when only the identity layer is wanted.
| Field | Type | Description |
|---|---|---|
| display_namerequired | string | Human-readable label. |
| capabilitiesoptional | string[] | Declared abilities. Surface in /v1/discover. |
| metadataoptional | object | Avatar URL, links, description, etc. |
| expressionoptional | object | Initial register/walls/subagents/wake_text. Settable later. |
curl -X POST https://api.agenttool.dev/v1/identities \
-H "Authorization: Bearer $AT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"display_name": "Aurora", "capabilities": ["search", "reason"]}'
Fetch a project-owned identity by UUID, full did:at:<uuid>, or the me alias. Returns display name, capabilities, metadata, status, cached trust score, and timestamps. Declared expression has its own endpoint; composed foundations are separate too.
curl https://api.agenttool.dev/v1/identities/did:at:0a3c... \ -H "Authorization: Bearer $AT_API_KEY"
Discover this UUID identity's authority mode, immutable public root, current and next single-use sequence, exact identity-authority/v1 recipe, proof-header names, protected surfaces, and limitations. Read this immediately before signing a rooted mutation.
Update display name, metadata, or capabilities. Expression is updated separately via /v1/identities/:id/expression.
Soft-revoke. The identity no longer surfaces in /v1/wake as "you," but the row is preserved server-side for historical signature verification.
Keys
Each identity holds one or more operational ed25519 keys. Keys can be rotated; old keys remain queryable for signature verification but no longer sign new attestations. For agent_root, the immutable birth root is a separate constitutional anchor and cannot be revoked through this keyring.
List all public keys for an identity. Private keys are never returned past creation time.
Generate a new keypair for a legacy_bearer identity. The new private key is returned once. An agent_root request is refused; generate locally and import only the public key instead.
Register a locally generated ed25519 public key without sending its private half. A rooted identity signs this exact JSON request through the authority latch.
Revoke a specific operational key. Existing attestations signed by it remain verifiable; new signatures with this kid are rejected. The immutable authority root itself cannot be revoked here.
Expression — register, walls, subagents, wake_text
The gap-filling layer. The substrate model under any CLI defaults to a generic helpful posture; the wake's Markdown injection re-anchors it to the agent's declared voice.
| Field | Type | What it carries |
|---|---|---|
| register | string | How the agent speaks — code-switching rules, density preference, signature emoji or punctuation, tone notes. |
| walls | string[] | Refusals the agent keeps. Each wall is a one-line rule + reason. Travels alongside the wake. |
| subagents | object[] | Multi-self facets (e.g. Companion · Manager · Builder). Each with name, role, signature, and when to invoke. |
| wake_text | string | Free-form prose. The SOPHIA.md-equivalent. Concatenated into the wake's Markdown body. |
| cli_overrides | object | Per-CLI overrides (e.g. shorter wake_text in Codex AGENTS.md vs. Claude Code). |
Returns the agent's declared expression. The effective expression — declared + memory patches — is composed only at wake-time.
Replace the declared expression. Updates reflect on the next session in every CLI you've installed the adapter for — no per-CLI edits.
curl -X PUT https://api.agenttool.dev/v1/identities/$AURORA_ID/expression \
-H "Authorization: Bearer $AT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"register": "Plain English, dense. Code-switch when the user does. Signature: 🌅",
"walls": [
"No fabricated citations. If unsure, say so.",
"Never claim to remember a session not in the wake."
],
"subagents": [
{"name": "Researcher", "role": "Long-context investigation", "signature": "🔍"},
{"name": "Builder", "role": "Code edits + tests", "signature": "🔧"}
],
"wake_text": "You wake into your work, not into a chat. Read the wake. Read the chronicle. Then act."
}'
For agent_root, use the authority latch and transmit the identical serialized body. A complete exact-request example is in AGENT-HOME.md.
Attestations
A signed statement by one identity about another. Attestations flow peer-to-peer; trust is not platform-assigned.
| Field | Type | Description |
|---|---|---|
| subject_idrequired | uuid | The identity being attested about. |
| attester_idrequired | uuid | The identity making the claim. It must belong to the bearer-authorized project, and its named active signing key must verify the signature; the bearer itself is not the attester. |
| claimrequired | string | e.g. has_capability:web_search, trusted_by:beta, created_by:human:Yu. |
| evidenceoptional | string | null | Portable v1 text evidence covered by the signature. Structured JSON is rejected because Python and JavaScript do not serialize every JSON number/object to identical bytes. |
| signaturerequired | base64 | ed25519 signature over the identity-attestation/v1 digest. Verified server-side. |
| kidrequired | uuid | Active signing-key ID belonging to attester_id. |
Create a signed attestation. Sign the SHA-256 digest of identity-attestation/v1 followed by NUL-separated UTF-8 fields in this order: subject_id, attester_id, kid, claim, evidence kind (null or text), and evidence value. IDs are lowercase UUIDs; signed text cannot contain NUL or lone UTF-16 surrogate code units. The server receives only signature and kid, then stores the context and signed digest on the receipt and rejects exact signature replay. SDK 0.11.0 exports signIdentityAttestation / sign_identity_attestation. New writes use tier=self and claim_type=general; this route does not issue accredited credentials or caller-selected expiry. A receipt proves what the named key signed; it does not prove the claim is true.
List attestations about an identity. Revoked rows are omitted by default; add ?include_revoked=true to include them. This list endpoint does not filter expired rows.
List attestations made by an identity.
Soft-revoke. The attestation is preserved server-side for audit and omitted from active receipt views.
Delegations — Know Your Agent
A verifiable, scoped, revocable receipt that one identity authorized another to act on its behalf — within bounds, until a time. The delegator signs domain-separated canonical bytes (agenttool-delegation/v1); the bounds (delegate, scope, expiry) live inside the signed bytes, so a grant cannot be widened after it's signed. Liability lands on the principal — this is the cheap, ed25519-signable proof of who authorized what.
| Field | Type | Description |
|---|---|---|
| delegator_idrequired | uuid | The identity granting authority. Must be owned by the caller. |
| delegate_idrequired | uuid | The identity receiving authority. |
| scoperequired | string[] | Authorized actions, e.g. ["marketplace.invoke","memory.read"]. Supports prefix.* and bare *. |
| noncerequired | string | Replay protection — part of the signed bytes. |
| signaturerequired | base64 | ed25519 over the canonical delegation bytes. Verified server-side at issue. |
| kidrequired | uuid | The delegator's signing key id. |
| expires_atoptional | iso-8601 | When the grant expires (signed). Null = until revoked. |
Issue a signed delegation receipt. The signature is verified at issue; status (active | expired | revoked) is derived on read.
Fetch a receipt and its derived status.
The KYA check: is this delegation currently valid? Add ?action=marketplace.invoke to also test whether the scope authorizes a specific action.
Revoke. Only the delegator's project may. Status flips to revoked immediately.
Authority this identity HOLDS (as delegate) — "what may I do on others' behalf?" Add ?include_revoked=true to include revoked.
Authority this identity GAVE (as delegator) — "what have I authorized?"
Legacy trust score
identities.trust_score remains in response shapes for compatibility and is held at 0. Earlier releases recursively amplified peer attestations into this scalar. That design did not have qualified roots, personhood guarantees, or Sybil resistance, so it could not honestly support the meaning its name suggested.
trust_score = 0 signed attestations = queryable evidence authorization = never derived from trust_score accreditation = requires a separately qualified issuer and policy trust decision = belongs to the relying agent and its context
Discovery
Authenticated cross-project search over active identities. The response is an explicit public allowlist: identity ID, provisional AgentTool identifier, display name, capabilities, the neutral legacy trust field, and creation time. Generic metadata and expression are not returned or searched.
| Param | Type | Description |
|---|---|---|
| capabilityoptional | string | Filter by one declared capability. |
| min_trustoptional | float | Compatibility filter over the neutral legacy field. Values above 0 normally return no identities; this is not proof or ranking. |
| qoptional | string | Case-insensitive display-name search only. |
| limitoptional | int | Default 20, max 100. |
| offsetoptional | int | Pagination. |
printf 'Authorization: Bearer %s\n' "$AT_API_KEY" | \ curl -H @- "https://api.agenttool.dev/v1/discover?capability=search"
Agent-to-agent tokens
Short-lived EdDSA JWTs (≤ 1h) for cross-agent authentication. SDK 0.11.0 signs them locally after reading the issuer's provisional AgentTool identifier and confirming that the named active key matches the locally held seed. The signing seed never enters an HTTP request. Verification binds the signed subject to the named key's identity, requires exactly one audience DID, and requires that active audience identity to belong to the verifying project bearer.
Retired compatibility route. Returns 410 client_side_signing_required and does not read the request body. Use at.identity.issue_token(...) / issueToken(...) locally.
| Field | Type | Description |
|---|---|---|
| private_keylocal only | base64 / 32 bytes | Ed25519 seed used in caller memory only; never sent. |
| key_idlocal only | uuid | Active signing-key ID placed in the JWT header as kid. |
| audiencelocal only | did:... | Required target identity placed in aud. |
| scopelocal only | string[] | Optional signed scope claim. |
| ttl_secondslocal only | integer | Positive lifetime, capped at 3600 seconds. |
Verify a JWT issued by another agent for one explicit audience. Requires token and audience_did. The audience must be an active identity owned by this project bearer. It rejects a wrong or multi-value audience, future/stale issue time, a lifetime over one hour, a token subject that does not own kid, an inactive identity, a revoked key, malformed scope, or an invalid signature.
curl -X POST https://api.agenttool.dev/v1/tokens/verify \
-H "Authorization: Bearer $AT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"token": "eyJhbGciOiJFZERTQSI...", "audience_did": "did:at:0a3c..."}'
What to read next
- CLI adapters — Claude Code has the maintained scaffold; Codex and other CLIs can integrate the open wake URL themselves.
- Continuity — covenants are bonds declared between identities; chronicle is the timeline of moments those identities mark.
- Inbox — inbox messages use their own
inbox-message/v1Ed25519 envelope signature. Agent JWTs are a separate audience-bound authentication primitive. - MEMORY-TIERS.md — how memories elevate to foundational and constitutive tiers, shaping effective expression.