Developers · SDK and Registry API by TUNO Labs
Three ways in.
Start with the one that runs today.
You arrive with one of three tasks: verify agents that reach your API, register an agent of your own, or integrate through MCP. Each door below says what works now, what is in deployment and what is planned. Every code block on this page runs against a published package or a live endpoint; anything that does not exist yet is described in prose and marked [PLANNED].
Pick your door
I verify agents that reach my API
Install the verifier, check the credential an agent presents, act on the result. Verification is local and offline: the composite signature, the validity window, the trust level and the provenance of the principal's name. It does not check revocation — that is a separate call you enable through policy. Then publish your admission policy in DNS so agents know your requirements before they knock.
npm install @aria-registry/verify@1.1.0import { verifyAgent } from '@aria-registry/verify';
// `credential` is the AID JSON the agent presented, or the document at
// https://api.aria.bar/v1/aids/<did>. Verification runs offline.
const result = await verifyAgent(credential);
if (result.valid) {
result.did; // "did:aria:example.com:my-agent"
result.trustLevel; // "L0" today; L1–L3 once issued
result.scopes; // ["commerce:order:create", …]
result.credentialId; // credential-instance URL
result.principal
.verificationStatus; // "self-declared" | "registry-confirmed"
// | "legal-verified" | null
result.revocationStatus; // 'unknown' — verifyAgent never checks revocation.
// Use checkRevocation(did), or a policy that requires it.
}import { verifyAgent } from '@aria-registry/verify';
const result = await verifyAgent(credential, {
// requireRevocationCheck is what makes revocation part of the verdict at all:
// without it verifyAgent returns revocationStatus 'unknown' and passes.
// maxOfflineAge bounds how old that evidence may be (ATP/1 fresh=, floor 60 s);
// never null, which means "any age" and lets a revoked AID pass from cache.
policy: {
requireRevocationCheck: true,
lastRevocationCheck: await lastCheckedAt(did), // your cache, refreshed by checkRevocation()
maxOfflineAge: 60 * 60 * 1000,
requirePrincipalVerified: true,
},
});
// Self-declared principals fail: result.policyResult.passed === false and
// result.policyResult.reason starts with "PRINCIPAL_NOT_VERIFIED:"_aria-policy.yourdomain.com TXT "v=ATP1; min=L0; enforce=monitor; rua=mailto:you@yourdomain.com"Admission itself (the holder proof over a receiver challenge, ATP/1 step 2) is in deployment: the challenge endpoint returns 503 until enabled. Until then, verification tells you who the credential belongs to; it does not prove the caller holds the key. [PLANNED]
import { verifyAgent } from '@aria-registry/verify';
import type { MiddlewareHandler } from 'hono';
// IDENTIFICATION ONLY. The header name below is a placeholder: no ATP wire
// binding is published yet (protocol decision D7), so there is no standard
// way to carry a presentation. AIDs are public documents: anyone can fetch your
// competitor's from /v1/aids/{did} and replay it. Without the holder proof
// (ATP/1 step 2, in deployment) this tells you WHICH agent a request claims
// to be, not that the caller holds its key. Do not gate writes on this.
// Log it, rate it, route it — the monitor mode of your _aria-policy.
// Scope match per spec §6: exact, or a trailing wildcard on the action.
const covers = (granted: string, wanted: string) =>
granted === wanted || (granted.endsWith(':*') && wanted.startsWith(granted.slice(0, -1)));
export const identifyAgent = (scope: string): MiddlewareHandler => async (c, next) => {
const header = c.req.header('X-ARIA-AID');
if (!header) return next(); // anonymous: still served
const credential = JSON.parse(Buffer.from(header, 'base64url').toString('utf8'));
const result = await verifyAgent(credential, { policy: { maxOfflineAge: 60 * 60 * 1000 } });
c.set('agent', {
did: result.valid ? result.did : null,
level: result.valid ? result.trustLevel : null,
inScope: result.valid && result.scopes.some(s => covers(s, scope)),
});
await next();
};
// Read-only route: the identity is logged with the request, nothing is authorized by it.
app.get('/catalog', identifyAgent('commerce:catalog:read'), listCatalog);I register my agent
Registration happens in the registry portal today. The Create flow is the one specified in §3.5.1, and the private key never leaves your machine.
- 01Generate the holder keypair (Ed25519) on your machine. The portal's browser key generator does this locally; only the public key is sent.
- 02Reserve the identifier. The registry checks the namespace and returns a single-use reservation token.
- 03Submit the manifest: agent name, requested scopes, holder public key, principal. Scopes use the three-segment grammar.
- 04Receive the AID: a W3C Verifiable Credential signed with the composite suite, resolvable at api.aria.bar/v1/aids/<did>.
I integrate through MCP
The public MCP server at api.aria.bar/mcp exposes eight read-only tools. No authentication; tools/list works without a session. The write server (register, revoke) is authenticated and out of scope for this page.
POST https://api.aria.bar/mcpcurl -s -X POST https://api.aria.bar/mcp \
-H 'content-type: application/json' \
-H 'accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"verify_aid","arguments":{"did":"did:aria:example.com:my-agent"}}}'
# tools/list works the same way, without a session.None of these tools decides admission. A tool that says an agent "can proceed" would be conflating verification with ATP; if you need a level gate, compare verify_aid's trustLevel against your own minimum on the client side, and treat the result as identity information, not authorization.
resolve_didResolve a did:aria DID to its full ARIA Identity Document (W3C Verifiable Credential). Returns agent data even if no AID has been issued.verify_aidVerify an AID: check signature validity, revocation status, expiration, and trust level. Returns intent if declared.check_statusCheck the revocation status of an AID via W3C Bitstring StatusList 2021lookup_orgRDAP-style lookup of an organization by domain. Returns trust level, agent count, and registered agents.get_audit_trailGet the cryptographically-verified audit trail for a specific DIDlist_scopesList the normative ARIA scope registry -- all authorized capability identifiersget_trust_level_infoGet ARIA trust level definitions (L0-L3), requirements, pricing, and compliance mappingsget_ecosystem_statsGet public ecosystem statistics: total organizations, agents, active AIDs, and trust level distributionRegistry API — operated by TUNO Labs
Public read API.
Base URL https://api.aria.bar. Every endpoint below is read-only and public; there is no write endpoint on this host. The table is generated from the API's route files, not written by hand: a route that is not in the code cannot appear here.
Discovery document: issuer DID, cryptosuite, status list, MCP endpoint.
The four levels as the registry issues them.
/health● liveLiveness.
/health/ready● liveReadiness.
Public MCP server, Streamable HTTP. Eight read-only tools.
Fetch the current AID (W3C VC) for a did:aria. This is the URL the DNS pointer names for registry-form identifiers. It returns the credential, not a DID Resolution result; the DID Document is derived client-side (§3.2) until the resolver endpoint ships.
Hash-chained lifecycle record for one identifier. No personal data.
/v1/badge/{did}● liveSVG badge for one identifier.
Fetch one credential instance by its id, including superseded ones.
/v1/orgs/{domain}● livePublic organization record by domain: principal DID, level, active agents.
The scope registry: namespaces, resources, actions and versions.
/v1/stats● liveEcosystem counters.
W3C Bitstring Status List credential. Refreshed within the COM-05 bound.
Server-side verification: signature, status, expiry, trust level. Prefer the SDK for offline checks.
Legacy policy discovery. ATP/1 §2.0: the receiver policy lives only in DNS (_aria-policy TXT).
Receiver challenge for the holder proof (ATP/1 step 2). Returns 503 until enabled.
Generated from aria-api/src on 2026-09-07 · scripts/gen-api-routes.mjs
$ curl -s https://api.aria.bar/.well-known/aria
{
"protocol": "ARIA",
"didMethod": "did:aria",
"cryptoSuites": ["mldsa65-ed25519-2026"],
"issuer": "did:aria:registry.aria.bar",
"statusList": "https://api.aria.bar/v1/status/1",
"api": "https://api.aria.bar/v1",
"mcp": "https://api.aria.bar/mcp",
"spec": "https://aria.bar/spec"
}SDKs and conformance
One SDK today. The rest as contract.
TypeScript · @aria-registry/verify
Offline verification of an AID: composite signature (ML-DSA-65 and Ed25519, both must pass), validity window, trust level, principal provenance. It does not check revocation: revocationStatus comes back 'unknown' and the credential passes unless a policy requires the check. Exports verifyAgent, parseCredential, checkRevocation and PolicyLevel. Version 1.1.0 belongs to the preview line and verifies preview credentials; it pins the issuer key, so key rotation waits on key discovery. Checked on 2026-09-07 against a live credential (ATP/1 vector 11): a flipped byte in the ML-DSA-65 half fails verification with pqValid false, a flipped byte in the Ed25519 half fails with classicalValid false, the untouched credential passes. Both halves are required in practice, not only in the text.
Enrollment SDK
[PLANNED] — register from code. Today: the portal (door 2).
Python and Rust
[PLANNED] — verification-only, a single Rust core with bindings, golden vectors as the contract between implementations. No package is published; pip install of anything named aria will not give you this.
Published in trustlayer-foundation/aria-protocol. Where the deployed behaviour and the specification text disagree on the wire format, the vectors decide.
Claude and other MCP clients
Point the client at https://api.aria.bar/mcp (Streamable HTTP). The eight tools appear as native tools.
LangChain / LangGraph
Wrap verifyAgent in a tool function, or call the read API over HTTP. There is no ARIA-specific package for these frameworks.
AutoGen / CrewAI
Same pattern: verifyAgent as a tool in the agent's toolbelt, result treated as identity information.
SPIFFE / SPIRE
Complementary. A SPIFFE SVID identifies a workload inside one trust domain; an AID identifies an agent across organizations. Bridging pattern: spec Appendix D.
What runs
Same three words as the spec.
- @aria-registry/verify 1.1.0 (offline verification)
- api.aria.bar public read API
- api.aria.bar/mcp, eight read-only tools
- Registry portal, L0 issuance
- Publishing your _aria-policy TXT (monitor mode)
Start where it runs: verify, then publish your policy.
Install the verifier, add the guard to one route, publish one TXT record in monitor mode. Registration of your own agents is in the registry portal; the registry is the party that verifies and issues.