ans

module
v0.1.7-0...-1270172 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 28, 2026 License: MIT

README

ans — Agent Name Service

ans is an open-source implementation of the Agent Name Service (ANS), a registry + transparency log for discovering and verifying AI agents by name. Every registered agent gets:

  • A versioned DNS-style name: ans://v1.0.0.my-agent.example.com
  • A publicly-auditable event history (append-only Merkle log)
  • SCITT COSE_Sign1 receipts proving the agent's state at a point in time
  • Identity certificates signed by a private CA for mTLS between agents
  • Optional BYOC server certificates + pinned TLSA records

The wire shape — event envelope, SCITT COSE receipts, sumdb-note checkpoints, /root-keys format — is the public contract. Offline verifiers and TL clients depend on it byte-for-byte.

Binaries

Binary Port Role
ans-ra 18080 Registration Authority — accepts registrations, issues identity certs, tracks lifecycle
ans-tl 18081 Transparency Log — durable Merkle-tree append log, serves badges + receipts
ans-verify Offline CLI verifier for SCITT COSE receipts and status tokens
ans-dns 15353 Dev-only authoritative DNS server with install / clear subcommands for local end-to-end verify-dns testing

Both daemons (ans-ra, ans-tl) serve Swagger UI at /docs — browse http://localhost:18080/docs (RA) and http://localhost:18081/docs (TL) after make build && scripts/demo/start.sh. The raw OpenAPI bytes live at /docs/openapi.yaml on each host.

To call protected endpoints from Swagger UI's "Try it out" button: click Authorize in the top-right and paste the static API key. The quickstart defaults are:

  • RA: ans-dev-key-change-me (from config/ra-local.yaml)
  • TL: tl-internal-key (from config/tl-local.yaml)

The RA writes signed events; the TL verifies, ingests, and publishes them. An operator can run just the TL (for read-only verification) or both together (full registry).

Quickstart (60 seconds)

# Prereqs: Go 1.26+, openssl, curl, jq
git clone https://github.com/agentnameservice/ans
cd ans
make build                        # builds bin/ans-ra, bin/ans-tl, bin/ans-verify, bin/ans-dns
scripts/demo/start.sh             # starts both daemons against ./data/demo
scripts/demo/run-lifecycle.sh     # registers an agent, verifies the receipt end-to-end

Expected output (last few lines):

━━━ 13. Offline verify (bin/ans-verify) ━━━
  ✓ Fetched 2 verification key(s) from /root-keys
  ✓ 1602 bytes (Content-Type: application/scitt-receipt+cose)
  ✓ VERIFIED (kid <8-char-hex> matched key directly)

Tear down with scripts/demo/stop.sh or scripts/demo/stop.sh --clean to wipe the data directory.

Local DNS testing with ans-dns

The default DNS verifier in config/ra-local.yaml is noop, which accepts any DNS state. To exercise the real lookup verifier end-to-end without touching public DNS, run the bundled authoritative server:

# In one terminal: start the dev DNS server (serves ./data/demo/dns)
bin/ans-dns serve --addr 127.0.0.1:15353

# In another: install the records the RA expects after verify-acme
bin/ans-dns install --api-key <api-key> http://localhost:18080 <agentId>

# Switch ra-local.yaml to dns.type=lookup pointed at 127.0.0.1:15353
# and re-run verify-dns; ans-tl observes the AGENT_REGISTERED event.

# Tear down:
bin/ans-dns clear <agentId>

ans-dns is dev-only. Production deployments use the lookup verifier against the operator's existing authoritative DNS.

Docker

# Build images for the long-running daemons
make docker-build

# Or bring the stack up with compose (RA + TL, with healthchecks)
docker compose up --build

Compose persists ra-data, ra-keys, and tl-data volumes so restarts are cheap; docker compose down -v wipes them. ans-verify and ans-dns are local-development binaries and ship from make build only — they are not in the compose stack.

Architecture

Hexagonal / ports-and-adapters. The domain model (internal/domain) has zero framework or storage dependencies. Services depend on port interfaces (internal/port) which adapters in internal/adapter/ implement against real drivers.

cmd/ans-ra/main.go ───────┐
                          ├─► internal/ra/service ─► port.AgentStore     ─► internal/adapter/store/sqlite
cmd/ans-tl/main.go ───────┤                          port.KeyManager     ─► internal/adapter/keymanager
                          │                          port.DNSVerifier    ─► internal/adapter/dns
                          └─► internal/tl/service ─► port.RenewalStore   ─► …

cmd/ans-verify/main.go ─► internal/tl/receipt   (Verify, ExtractKID, ComputeLeafHash)
cmd/ans-dns/main.go    ─► miekg/dns authoritative server + RA-driven record install/clear

See spec/api-spec-v2.yaml + spec/api-spec-tl-v2.yaml for the authoritative OpenAPI contracts.

Core contracts

Event envelope (signed on the RA side):

{
  "payload": {
    "logId": "<uuid>",
    "producer": {
      "event": { "ansId": "...", "ansName": "ans://...", "eventType": "AGENT_REGISTRATION", ... },
      "keyId": "ans-ra-signer",
      "signature": "<detached JWS over JCS(event)>"
    }
  },
  "schemaVersion": "V1",
  "signature": "<TL attestation JWS>",
  "status": "ACTIVE"
}

Receipts (SCITT COSE_Sign1, RFC 8152 tag 18):

  • Protected header: {1:-7 (ES256), 4:<kid 4-byte SPKI hash>, 395:1 (RFC 9162), 15:{1:<issuer>, 6:<iat>}}
  • Unprotected header: {396:{-1:treeSize, -2:leafIndex, -3:path[][], -4:rootHash}}
  • Payload: the JCS-canonical event bytes (the same bytes the leaf hash is computed over)
  • Signature: ES256 over the RFC 8152 §4.4 Sig_structure

Leaf hash: RFC 6962 — SHA-256(0x00 || payload).

Root-keys endpoint (GET /root-keys) emits the sumdb-note verification-key format (one line per key):

<origin>+<keyhash-hex>+<base64(0x02 || SPKI-DER)>

where keyhash-hex is the first 4 bytes of SHA-256(SPKI-DER) as zero-padded big-endian hex. Verifiers match this against the kid in the receipt's protected header for O(1) key lookup.

The TL signs every outbound artifact (checkpoints, attestations, receipts, status tokens) with a single ECDSA P-256 key. /root-keys advertises exactly one line.

Verification workflow

Any third party can verify an agent's state cryptographically without trusting the TL operator beyond the advertised verifier keys:

# Fetch receipt + keys + verify
ans-verify -url https://tl.example.com -agent <agentId>

# Or, air-gapped (receipt already on disk, key pinned in CI):
ans-verify -pubkey ./trusted-tl.pub -agent <agentId> \
  -url file://./receipt.cbor

The verifier:

  1. Fetches /root-keys (or reads a pinned PEM).
  2. Fetches the receipt CBOR.
  3. Parses COSE_Sign1, extracts the inclusion proof from label 396.
  4. Maps the receipt's 4-byte kid → verifier key in O(1).
  5. Walks the Merkle path from SHA-256(0x00 || payload) to rootHash; rejects any mismatch.
  6. ES256-verifies the signature over Sig_structure.
  7. Cross-checks that the receipt's computed leaf hash matches the badge's merkleProof.leafHash (same leaf in the same tree).

Configuration

Both daemons read YAML via koanf. The shipped quickstart configs are under config/:

  • config/ra-local.yaml — local-filesystem dev config (SQLite, self-CA, noop DNS)
  • config/tl-local.yaml — same for the TL
  • config/ra-docker.yaml / config/tl-docker.yaml — compose-friendly paths + log format

Every YAML key is overridable via env vars using the _. dotted form (e.g. ANS_RA_SERVER__PORT=18090).

Auth

Two providers ship today:

  • Static API key (quickstart): accepts both Authorization: Bearer <key> (ans-native form) and Authorization: sso-key <apiKey>:<apiSecret> (the form generated SDK clients use). The static key is treated as admin, so it can hit /internal/v1/producer-keys.
  • OIDC: standard bearer-token validation against an issuer URL. Configure admin groups with auth.oidc.admin-groups[].

Every GET under /v1/agents/, /v1/log/, and the tlog-tiles paths (/checkpoint, /root-keys, /tile/*) is anonymous when auth.public-read: true (the default for the TL quickstart config) — verifiers never need credentials.

Pluggable architecture

Every external dependency lives behind a port interface in internal/port/. Defaults target local development; you can swap any of them at the port boundary without touching the service layer.

Concern Default adapter Common production swap
Auth Static API key + OIDC OIDC against your IdP
Identity cert issuance File-backed self-signed CA Cloud KMS-backed CA
Server cert issuance Self-signed CA + BYOC PEM ACME / public CA / BYOC PEM
DNS verification noop and lookup (real miekg/dns queries with DNSSEC AD-bit propagation) lookup against your authoritative DNS
Signing keys File-based ECDSA P-256 Cloud KMS adapter
Storage SQLite Postgres / managed RDBMS

Cloud-KMS, Postgres, and managed-DNS adapters are contribution-shaped — see CONTRIBUTING.md.

Development

make test         # unit tests
make test-cover   # with coverage, enforces the repo gate (≥90%)
make test-race    # race detector
make check        # fmt + vet + lint + test-cover (pre-commit gate)

Test coverage targets: 100% on internal/domain and internal/crypto (with annotated SAFETY exceptions for unreachable defensive branches), ≥90% overall across internal/ (enforced by make test-cover). Adapter packages under internal/adapter/ are the primary remaining gap — contributions welcome, see CONTRIBUTING.md.

Contributing guide: CONTRIBUTING.md. Project conventions for code generation tools: CLAUDE.md.

Status

Shipped: full V1 + V2 RA surface (register, verify-acme, verify-dns, revoke, list, detail, identity/server cert GET + POST, CSR status, renewal lifecycle with BYOC + CSR paths, renewal expiry sweep) • TL ingest, badge, audit, SCITT COSE receipts (tag 18, ES256), SCITT status tokens (1h TTL, terminal-state aware), root-keys (sumdb-note format), JSON + raw checkpoint, paginated checkpoint history, schema lookup, Merkle tiles • Producer-key admin CRUD (/internal/v1/producer-keys) • ans-verify CLI that fetches + verifies both receipts and status tokens • ans-dns dev DNS server with install / clear for verify-dns end-to-end testing.

Follow-up opportunities (community): cloud-KMS / Postgres / managed-DNS adapters, real ACME DNS-01 verifier wiring, additional schema versions.

License

MIT License. See LICENSE.

Directories

Path Synopsis
cmd
ans-dns command
Command ans-dns is a small authoritative DNS server + zone-management CLI for local-dev testing of the full ANS lifecycle end-to-end.
Command ans-dns is a small authoritative DNS server + zone-management CLI for local-dev testing of the full ANS lifecycle end-to-end.
ans-finder command
Command ans-finder runs the ANS Finder — the Agentic Resource Discovery (ARD) service over the ANS reference implementation.
Command ans-finder runs the ANS Finder — the Agentic Resource Discovery (ARD) service over the ANS reference implementation.
ans-ra command
Command ans-ra runs the ANS Registration Authority HTTP server.
Command ans-ra runs the ANS Registration Authority HTTP server.
ans-tl command
Command ans-tl runs the ANS Transparency Log HTTP server.
Command ans-tl runs the ANS Transparency Log HTTP server.
ans-verify command
Command ans-verify is an offline verifier for SCITT COSE receipts served by the ANS Transparency Log.
Command ans-verify is an offline verifier for SCITT COSE receipts served by the ANS Transparency Log.
internal
adapter/auth
Package auth provides AuthProvider implementations.
Package auth provides AuthProvider implementations.
adapter/cert
Package cert provides certificate-handling adapter implementations: the self-signed identity CA and the BYOC server-certificate validator.
Package cert provides certificate-handling adapter implementations: the self-signed identity CA and the BYOC server-certificate validator.
adapter/cert/acmetest
Package acmetest provides an in-process fake RFC 8555 server for exercising the ACME issuer adapter without network access.
Package acmetest provides an in-process fake RFC 8555 server for exercising the ACME issuer adapter without network access.
adapter/challenge
Package challenge provides adapters for verifying domain-control challenge artifacts the domain owner has published.
Package challenge provides adapters for verifying domain-control challenge artifacts the domain owner has published.
adapter/didresolver
Package didresolver provides the two port.DIDResolver adapters:
Package didresolver provides the two port.DIDResolver adapters:
adapter/discovery/ans
Package ans implements the bundled ANS-family port.ProfileEmitter adapters: DNSAIDProfile (the DNS-AID-aligned SVCB shape per RFC 9460 plus the `_ans-badge` TXT extension) and TXTProfile (the original `_ans` TXT shape, supported indefinitely for operators with existing zone-edit tooling).
Package ans implements the bundled ANS-family port.ProfileEmitter adapters: DNSAIDProfile (the DNS-AID-aligned SVCB shape per RFC 9460 plus the `_ans-badge` TXT extension) and TXTProfile (the original `_ans` TXT shape, supported indefinitely for operators with existing zone-edit tooling).
adapter/discovery/registry
Package registry holds the immutable composition facade for port.ProfileEmitter implementations.
Package registry holds the immutable composition facade for port.ProfileEmitter implementations.
adapter/dns
Package dns provides DNSVerifier implementations.
Package dns provides DNSVerifier implementations.
adapter/docsui
Package docsui serves the OpenAPI spec + a Swagger-UI page for the currently-running binary.
Package docsui serves the OpenAPI spec + a Swagger-UI page for the currently-running binary.
adapter/eventbus
Package eventbus provides EventBus implementations.
Package eventbus provides EventBus implementations.
adapter/keymanager
Package keymanager provides KeyManager implementations.
Package keymanager provides KeyManager implementations.
adapter/leiverifier
Package leiverifier provides the two port.LEIControlVerifier adapters behind the lei (vLEI) identifier kind:
Package leiverifier provides the two port.LEIControlVerifier adapters behind the lei (vLEI) identifier kind:
adapter/store/sqlite
Package sqlite provides SQLite implementations of the store ports (AgentStore, CertificateStore, EndpointStore, RenewalStore, RevocationStore, ByocCertificateStore) plus an outbox table used by the RA→TL HTTP client for durable event delivery.
Package sqlite provides SQLite implementations of the store ports (AgentStore, CertificateStore, EndpointStore, RenewalStore, RevocationStore, ByocCertificateStore) plus an outbox table used by the RA→TL HTTP client for durable event delivery.
adapter/store/sqlitefinder
Package sqlitefinder is the SQLite FTS5-backed implementation of the Finder's index.Catalog port.
Package sqlitefinder is the SQLite FTS5-backed implementation of the Finder's index.Catalog port.
adapter/store/sqlitetl
Package sqlitetl is the SQLite-backed EventStorage for ans-tl.
Package sqlitetl is the SQLite-backed EventStorage for ans-tl.
adapter/tlclient
Package tlclient is the HTTP client the RA uses to POST signed events to the Transparency Log.
Package tlclient is the HTTP client the RA uses to POST signed events to the Transparency Log.
ard
Package ard holds the projection rules shared by every surface that mints ARD (Agentic Resource Discovery) identifiers from registration data.
Package ard holds the projection rules shared by every surface that mints ARD (Agentic Resource Discovery) identifiers from registration data.
catalog
Package catalog generates AI Catalog artifacts from a registration aggregate.
Package catalog generates AI Catalog artifacts from a registration aggregate.
config
Package config loads and validates runtime configuration for ans-ra and ans-tl from YAML files with environment variable overrides.
Package config loads and validates runtime configuration for ans-ra and ans-tl from YAML files with environment variable overrides.
crypto
Package crypto provides shared cryptographic operations used by the RA and TL: X.509 parsing, CSR validation, JWS signing/verification, JSON Canonicalization (RFC 8785), and COSE_Sign1 receipt encoding.
Package crypto provides shared cryptographic operations used by the RA and TL: X.509 parsing, CSR validation, JWS signing/verification, JSON Canonicalization (RFC 8785), and COSE_Sign1 receipt encoding.
domain
Package domain contains the pure domain model for the Agent Name Service.
Package domain contains the pure domain model for the Agent Name Service.
finder/feed
Package feed defines the consumer-side contract types for the ANS agent-events feed (`GET /v1/agents/events`).
Package feed defines the consumer-side contract types for the ANS agent-events feed (`GET /v1/agents/events`).
finder/handler
Package handler is the HTTP adapter for the ANS Finder's discovery surface: POST /v1/search and POST /v1/explore, plus operator health/readiness.
Package handler is the HTTP adapter for the ANS Finder's discovery surface: POST /v1/search and POST /v1/explore, plus operator health/readiness.
finder/index
Package index defines the Finder's catalog index port and the query types its search and explore surfaces speak.
Package index defines the Finder's catalog index port and the query types its search and explore surfaces speak.
finder/poller
Package poller is the Finder's ingestion loop.
Package poller is the Finder's ingestion loop.
finder/project
Package project turns a single ANS feed event (feed.EventItem) into zero or more ARD catalog entries — the Finder's discovery records.
Package project turns a single ANS feed event (feed.EventItem) into zero or more ARD catalog entries — the Finder's discovery records.
lognote
Package lognote parses and verifies C2SP-shaped transparency-log checkpoint signed notes (golang.org/x/mod/sumdb/note framing).
Package lognote parses and verifies C2SP-shaped transparency-log checkpoint signed notes (golang.org/x/mod/sumdb/note framing).
port
Package port defines the hexagonal-architecture port interfaces that the domain and service layers depend on.
Package port defines the hexagonal-architecture port interfaces that the domain and service layers depend on.
ra/handler
Package handler contains the HTTP-facing adapters for the RA V2 API.
Package handler contains the HTTP-facing adapters for the RA V2 API.
ra/middleware
Package middleware holds HTTP middleware specific to the RA.
Package middleware holds HTTP middleware specific to the RA.
ra/outbox
Package outbox holds the RA's outbox-delivery worker.
Package outbox holds the RA's outbox-delivery worker.
ra/service
Package service contains the RA application-layer services.
Package service contains the RA application-layer services.
tl/event
Package event defines the V1 Transparency Log event envelope and the canonicalization / leaf-hash rules the TL and its verifiers rely on.
Package event defines the V1 Transparency Log event envelope and the canonicalization / leaf-hash rules the TL and its verifiers rely on.
tl/event/identity
Package identity defines the Transparency Log event family for Verified Identities — the "who" behind an agent.
Package identity defines the Transparency Log event family for Verified Identities — the "who" behind an agent.
tl/event/v1
Package v1 defines the V1 event envelope served by this ans-tl.
Package v1 defines the V1 event envelope served by this ans-tl.
tl/handler
Package handler wires HTTP routes for the Transparency Log API.
Package handler wires HTTP routes for the Transparency Log API.
tl/logstore
Package logstore wraps the Tessera transparency-log appender plus its checkpoint signers.
Package logstore wraps the Tessera transparency-log appender plus its checkpoint signers.
tl/producerkey
Package producerkey holds the trust store the Transparency Log uses to verify incoming event signatures.
Package producerkey holds the trust store the Transparency Log uses to verify incoming event signatures.
tl/receipt
Package receipt implements SCITT-style COSE_Sign1 transparency-log receipts for the ANS TL.
Package receipt implements SCITT-style COSE_Sign1 transparency-log receipts for the ANS TL.
tl/service
Package service holds the Transparency Log application-layer services.
Package service holds the Transparency Log application-layer services.
scripts
demo/signproof command
signproof is the demo-side identity-proof tool: it mints keypairs and signs identity verify-control proofs (compact JWS over the RA-served signingInput).
signproof is the demo-side identity-proof tool: it mints keypairs and signs identity verify-control proofs (compact JWS over the RA-served signingInput).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL