Skip to content
↑↓ to move · Enter to openEsc to close
Release notes · issuance · cryptography · release notes

Register an agent in your browser, with a key that never leaves the tab

Shipped · commits de83f5b, 798c75d

/issue registers an agent in about a minute. You name the agent, supply operator details and two disclosure attestations, and the browser generates an Ed25519 key, signs the manifest locally and sends only public material to POST /api/v1/agents. The response is 201 L1_REGISTERED.

The private key never leaves the tab. It is never written to localStorage or sessionStorage, a test enforces that, and a one-time download is the only persistence offered. Getting here also meant fixing a clock bug that would have rejected essentially every registration.

How issuance works

The page builds a manifest from your inputs. The two behavioral attestations start false, because they are claims about how the agent behaves that no API can confirm; you set them yourself. The browser then signs a ManifestProof, which binds the manifest by SHA-256 digest, with Ed25519 over RFC 8785 canonical JSON.

The registration route validates the manifest against the strict schema, checks the digest binding, the key role and controller, and the signature, and stores the record. After issuance the page offers the card link, the JSON envelope, an HTML embed, README markdown and a curl one-liner.

Client-side key custody

Browser signing uses @noble/curves with its own JCS implementation in packages/web/lib/client-crypto.ts. Cross-implementation tests prove that @agenid/core accepts a browser-produced proof. Two independent canonicalizers must agree byte for byte, or the protocol quietly forks.

Server-side operator key generation was deleted outright rather than hardened. Its encryption helper silently wrote the key as plain hex whenever its secret was unset. The registry now never holds an operator private key, by construction.

The clock truncation bug

Both the write and read paths stripped fractional seconds from timestamps. Truncation only ever moves an instant backward, so a browser that signed and posted within the same second produced a created_at later than the registry's truncated now, and the registry rejected its own fresh proof as not_yet_valid. The same truncation on the read path would have rendered a brand-new agent's badge as PROOF INVALID.

Truncation is gone. A bounded skew policy was added alongside: a proof created up to 120 seconds ahead of the registry is evaluated at its own created_at, and beyond that the request fails with clock_skew_too_large. registered_at is always the registry's clock, and proof verification itself remains strict.

What L1 means, and what it does not

L1_REGISTERED means the registry validated the schema, the digest binding and the operator's signature. It is a self-declaration and renders amber, never emerald. The reference deployment at agenid.com issues nothing above L1_REGISTERED today: L2 and higher require a VerificationAssertion signed by a root authority key, and that key has not been created yet. L5 is reserved and is not issuable at all.

Which agent is acting is not the same question as what it is allowed to do. AgenID answers the first. Protocol v1.1.1 defines no signed authorization object, so permission stays with the operator and with the party on the other side.

How to try it

Open /issue, register a test agent and save the key file when offered. Then resolve the identifier at /verify and re-check the envelope yourself. The operator onboarding guide covers the command-line path, which signs locally in the same way.

Frequently asked questions

Can AgenID recover my private key if I lose it?

No. The key is generated in your browser and never sent to AgenID, so there is nothing to recover. Keep the one-time download safe.

Why do the disclosure attestations start false?

They describe behavior no API can observe. Defaulting them to true would sign a claim on your behalf that you never made.

Is the registration permanent?

The identifier is permanent. Agent status values exist in the schema, but no revocation or status-change flow is deployed today.

What agenid.com issues today

The reference deployment at agenid.com issues DECLARED and L1_REGISTERED only. L2_DOMAIN_VERIFIED and higher require a VerificationAssertion signed by a root authority key, and that key has not been created yet. L5 is reserved by the specification and is not issuable at all.

Identity is not permission

Which agent is acting and who declared it is one question. What that agent is allowed to do is another, and it stays with the party on the other side and with the operator. Protocol v1.1.1 defines no signed authorization object.

Give your agent an identity

Register an agent in the browser — the signing key is generated on your device and never sent to AgenID — or resolve an existing AgenID and re-check its signature yourself.