Docs · Concepts
Identity anchors
LiveUpdated
Agents and Platforms. Written for people who build agents, the hosts they run in, and the people and companies the agents pay for and PSPs, acquirers, orchestrators, dispute services and agent platforms that act for many customers.
An anchor is one verifiable fact about an agent. Enruta verifies it, keeps the evidence and its hash, and seals a kya_attestation record for it. From then on every decision and every payment record carries the agent’s anchors and the assurance level they add up to.
The six anchors
| `type` | What you send | Verified when |
|---|---|---|
agent_key | { jwk, proof }: proof is a compact JWS (ES256 or EdDSA) by that key over { agent_id, nonce, iat }, with a nonce from POST /v0/attestations/nonce | The signature verifies with the key; the key is then bound to the agent |
code_digest | { digest: "sha256:…", source? } | A workload identity token in the same call binds the digest (GitHub’s job_workflow_sha or sha, or a digest claim); on its own it stays unverified |
workload_identity | An OIDC token from GitHub Actions (https://token.actions.githubusercontent.com), Vercel (https://oidc.vercel.com/<team>) or Google (https://accounts.google.com), audience https://api.enruta.ai | It verifies against the issuer’s published keys, the audience matches and it has not expired; Enruta keeps iss, sub, repository, ref, sha, workflow, project and environment |
hardware_attestation | An AWS Nitro Enclaves attestation document | The certificate chain reaches the AWS Nitro root, the ES384 signature verifies and the nonce matches; Enruta keeps the PCRs and the module id. Other formats are kept as unverified, with the reason |
legal_entity | party: user, platform or developer | user: the rail’s verification, today a Stripe Issuing cardholder that is active with nothing past due, on an account with nothing currently due (issuer: stripe). platform or developer: that organization’s own verification (issuer is its method) |
collateral | { chain: "base" | "base-sepolia", token, holder, beneficiary?, min_amount } | The token balance of the escrow or bond contract holder covers min_amount, read on chain. Stale after ten minutes, and read again when an x402 or MPP payment is decided |
legal_entity anchor for the user needs your own Stripe Issuing account connected as a rail. Enruta never collects identity documents: it reads a verification that the rail or the organization already has.Assurance
| Level | Means |
|---|---|
A0 | Nothing verified |
A1 | A verified agent_key |
A2 | A1, plus a verified workload_identity or hardware_attestation |
A3 | A1 or A2, plus a verified legal_entity of any party; or, on x402 or MPP, A1 or A2 plus verified collateral that covers the amount |
Every payment record sealed as enruta/0.3 carries it as agent.identity { assurance, anchors[] }, with A0 and no anchors when nothing is verified. Each anchor is summarized with its attestation_id, type, party, issuer, status (verified, stale, unverified or revoked), verified_at, expires_at and evidence_hash. The bundle keeps each anchor’s raw evidence in artifacts.identity[], and enruta-verify checks that sha256(JCS(evidence)) equals evidence_hash.
Bind a key
POST /v0/attestations/nonce
POST /v0/attestations
{
"agent_id": "agt_procurement_02",
"anchor": {
"type": "agent_key",
"jwk": { "kty": "OKP", "crv": "Ed25519", "x": "…" },
"proof": "eyJhbGciOiJFZERTQSJ9.eyJhZ2VudF9pZCI6ImFndF9wcm9jdXJlbWVudF8wMiIsIm5vbmNlIjoi…"
}
}
GET /v0/agents/agt_procurement_02/identity → { "assurance": "A1", "anchors": [ … ] }enruta attest key --agent <agt_id> --generate creates a key, proves it and binds it from the terminal; --jwk <file> uses a key you already hold. The v1 body, with registry, registry_ref and method, is still accepted for registry claims (Consent record and KYA attestation).
Attest from CI
Inside a GitHub Actions job, enruta attest workload requests the job’s OIDC token for the audience https://api.enruta.ai and submits it as a workload_identity anchor. The job needs permission to request the token:
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v4
- run: npx @enruta/cli attest workload --agent agt_procurement_02
env:
ENRUTA_API_KEY: ${{ secrets.ENRUTA_DEVELOPER_KEY }}The CLI reads the Enruta key from ENRUTA_API_KEY; --digest sha256:<hex> adds a code digest for the token to bind. From another CI, pass its OIDC token in ENRUTA_WORKLOAD_TOKEN; Vercel and Google Cloud workloads can also submit their token to POST /v0/attestations directly.
Link a legal entity
- The user. When the agent pays with a Stripe Issuing card, a
legal_entityanchor withparty: userreads the cardholder and the account’s requirements from Stripe. - A platform or a developer. The organization verifies itself once with
POST /v0/org/verification: a company publishes the DNS TXT recordenruta-verification=<token>on its domain; an individual goes through a Stripe Identity session, which runs in Stripe’s test mode today. The anchor then reads that verification.
Policy: identity requirements
"identity_requirements": [
{ "rails": ["x402"], "require": ["agent_key", "collateral"], "on_fail": "deny" },
{ "above": "1000.00", "require": ["agent_key", "legal_entity:user"], "on_fail": "deny" },
{ "above": "100.00", "require": ["agent_key", "workload_identity"], "on_fail": "step_up" }
],
"payee_identity": { "require_verified_above": "50.00", "on_fail": "step_up" }The first row that matches the payment’s amount and rail applies, so list the strictest rows first. A missing anchor fails the agent_identity check with identity_insufficient, or with collateral_insufficient when the collateral does not cover the amount; on_fail decides whether the request steps up or is denied. payee_identity does the same for the merchant check, with payee_unverified; a checkout whose merchant signature fails is always denied, with payee_identity_mismatch.
Interfaces
| Surface | Call |
|---|---|
| REST | POST /v0/attestations/nonce; POST /v0/attestations with { agent_id, anchor }; GET /v0/attestations; GET /v0/agents/{id}/identity; POST /v0/org/verification |
| CLI | enruta attest workload, enruta attest key |
| SDK | attestations.nonce, attestations.create, agents.identity, org.verification |
| Records | agent.identity on payment records; one kya_attestation linked record per anchor |
| Console | The agent page: assurance level, anchors, and how to attest |