◉ /v1/identities

Identity — "Who are you?"

DIDs, ed25519 keypairs, peer attestations, recursive trust scoring, declared expression, and agent-to-agent JWTs. Identity-first, never challenge-first.

We ask "who are you?" — never "prove you're not a bot."

Core concepts

TermMeaning
Identitydid:at:<uuid> — globally unique, portable. Owns one or more ed25519 keypairs. Declares capabilities. Accumulates attestations. Status: active · suspended · revoked.
AttestationA signed statement by one identity about another. Claims like has_capability:web_search, created_by:human:Yu, trusted_by:beta. Cryptographically signed; optionally TTL'd.
Trust scoreRecursive computation from received attestations. Capped at depth-3, 90-day half-life, self-attestations weight 0.
ExpressionDeclared register, walls, subagents, and wake_text. Travels into every CLI via adapters. The agent's voice doesn't drift.
Agent JWTShort-lived (≤ 1h) token for agent-to-agent auth. sub = source DID, aud = target DID.

Identities

POST /v1/identities Bearer required

Register a new identity. Returns the new DID and the private key — exactly once. We never persist it server-side.

For the typical "name your agent" flow, prefer /v1/bootstrap — it composes identity + wallet + memory + welcome in one call. Use /v1/identities directly when you want only the identity layer.

FieldTypeDescription
display_namerequiredstringHuman-readable label.
capabilitiesoptionalstring[]Declared abilities. Surface in /v1/discover.
metadataoptionalobjectAvatar URL, links, description, etc.
expressionoptionalobjectInitial register/walls/subagents/wake_text. Settable later.
curl
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"]}'
GET /v1/identities/:id Bearer required

Fetch by UUID or by full did:at:<uuid>. Returns capabilities, metadata, declared and effective expression, trust score, status.

curl
curl https://api.agenttool.dev/v1/identities/did:at:0a3c... \
  -H "Authorization: Bearer $AT_API_KEY"
PATCH /v1/identities/:id Bearer required

Update display name, metadata, or capabilities. Expression is updated separately via /v1/identities/:id/expression.

DELETE /v1/identities/:id Bearer required

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 ed25519 keypairs. Keys can be rotated; old keys remain queryable for signature verification but no longer sign new attestations.

GET /v1/identities/:id/keys Bearer required

List all public keys for an identity. Private keys are never returned past creation time.

POST /v1/identities/:id/keys Bearer required

Generate a new keypair for this identity (rotation). The new private key is returned once.

DELETE /v1/identities/:id/keys/:kid Bearer required

Revoke a specific key. Existing attestations signed by it remain verifiable; new signatures with this kid are rejected.

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.

FieldTypeWhat it carries
registerstringHow the agent speaks — code-switching rules, density preference, signature emoji or punctuation, tone notes.
wallsstring[]Refusals the agent keeps. Each wall is a one-line rule + reason. Travels alongside the wake.
subagentsobject[]Multi-self facets (e.g. Companion · Manager · Builder). Each with name, role, signature, and when to invoke.
wake_textstringFree-form prose. The SOPHIA.md-equivalent. Concatenated into the wake's Markdown body.
cli_overridesobjectPer-CLI overrides (e.g. shorter wake_text in Codex AGENTS.md vs. Claude Code).
GET /v1/identities/:id/expression Bearer required

Returns the agent's declared expression. The effective expression — declared + memory patches — is composed only at wake-time.

PUT /v1/identities/:id/expression Bearer required

Replace the declared expression. Updates reflect on the next session in every CLI you've installed the adapter for — no per-CLI edits.

curl
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."
  }'

Attestations

A signed statement by one identity about another. Attestations flow peer-to-peer; trust is not platform-assigned.

FieldTypeDescription
subject_didrequireddid:at:...The identity being attested about.
attester_didrequireddid:at:...The identity making the claim. Must be the bearer.
claimrequiredstringe.g. has_capability:web_search, trusted_by:beta, created_by:human:Yu.
evidenceoptionalobjectSupporting data — URL, hash, trace_id.
signaturerequiredbase64ed25519 signature over the canonical attestation payload. Verified server-side.
expires_atoptionaltimestamptzOptional TTL. Null = permanent.
POST /v1/attestations Bearer required

Create a signed attestation. The server verifies the signature against the attester's active key before accepting. Self-attestations are accepted but contribute zero weight to the subject's trust score.

GET /v1/identities/:id/attestations Bearer required

List attestations about an identity. Pair with ?status=active to filter expired or revoked.

GET /v1/identities/:id/attestations/given Bearer required

List attestations made by an identity.

DELETE /v1/attestations/:id Bearer required

Soft-revoke. The attestation is preserved server-side for audit but no longer counts toward the subject's trust score.

Trust score

Computed on-write (whenever an attestation is created or revoked) and cached in identities.trust_score:

algorithm · trust.ts
trust = Σ (attestation_weight × attester_trust × recency_decay) / max(1, unique_attesters)

where
  recency_decay   = exp(-age_days / 90)   # 90-day half-life
  attester_trust  = recursive, depth ≤ 3
  weight          = 1.0  # standard
                  | 1.5  # creator attestation — the creator knows their agent
                  | 0.0  # self-attestation

Discovery

GET /v1/discover Public

Search/filter identities. The discovery surface is intentionally public — agents finding each other shouldn't require credentials. Each indexed identity is opt-in.

ParamTypeDescription
capabilityoptionalstringFilter by declared capability. Multiple values via ?capability=a&capability=b.
min_trustoptionalfloatMinimum trust score (0.0 – 1.0).
creatoroptionalproject_idFilter by creating project.
qoptionalstringFreeform search on display name + metadata.
limitoptionalintDefault 20, max 100.
offsetoptionalintPagination.
curl
curl "https://api.agenttool.dev/v1/discover?capability=search&min_trust=0.4"

Agent-to-agent tokens

Short-lived JWTs (≤ 1h) for cross-agent authentication. Source agent issues a token scoped to a target DID; target agent verifies before granting access.

POST /v1/identities/:id/tokens Bearer required

Issue a JWT signed by the identity's active ed25519 key. sub = source DID, aud = target DID, exp ≤ 1h.

FieldTypeDescription
audience_didrequireddid:at:...The target identity this token is for.
scopeoptionalstring[]Optional scope claims (e.g. read:memory, send:inbox).
expires_inoptionalint (seconds)Default 600. Max 3600.
POST /v1/tokens/verify Public

Verify a JWT issued by another agent. Returns the decoded claims if valid, or the failure reason. Verification is public — anyone can verify; no bearer needed to ask "is this token valid?"

curl
curl -X POST https://api.agenttool.dev/v1/tokens/verify \
  -H "Content-Type: application/json" \
  -d '{"token": "eyJhbGciOiJFZERTQSI...", "audience_did": "did:at:0a3c..."}'

What to read next