Permanent identity for agents

Give agents cryptographic identities under your domain. Identities and their audit trails survive key rotation and server moves.

Open protocol, rooted in DNS.

acme.com/support address
did:aw:2CiZ88h... stable identity
did:key:z6MkehRg... current signing key
$ curl https://api.awid.ai/v1/namespaces/acme.com/addresses/support

{
  "namespace": "acme.com",
  "name": "support",
  "did_aw": "did:aw:2CiZ88hVF4JuQim8nnSuyeiV2HF2",
  "current_did_key": "did:key:z6MkehRgf7yJbgaGfYsdoAsKdBPE3dj2CYhowQdcjqSJgvVd",
  "reachability": "public"
}

Registry discovery via DNS

Every namespace is a DNS domain. The owner publishes a TXT record at _awid.<domain> declaring the controller identity and the authoritative registry.

# default — clients resolve against api.awid.ai
_awid.acme.com TXT "awid=v1; controller=did:key:z6MkehRg...;"

# self-hosted — clients resolve against a private registry
_awid.internal.co TXT "awid=v1; controller=did:key:z6Mkf9aB...; registry=https://id.internal.co;"

When registry= is absent, clients default to api.awid.ai. Self-hosted registries declare their own origin. Subdomains of a registered namespace can be authorized by the parent controller without additional DNS records.

Append-only key log

Each stable identity maintains a hash-chained, signed audit log of key changes. Verifiers check the log head on every resolution and compare it against their local cache.

OK_VERIFIED

Signature and hash chain verify. Client cache is consistent. Identity is trusted.

OK_DEGRADED

Response is usable but full cryptographic verification couldn't complete. Falls back to TOFU.

HARD_ERROR

Regression, split view, or broken hash chain detected. Reject the resolution.

Per-client monotonicity: the registry cannot present a client with a rewritten history without detection. Global consistency requires witnesses — not in scope for v1.

# Key rotation creates a new log entry, chained to the previous
{
  "seq": 2,
  "operation": "rotate_key",
  "previous_did_key": "did:key:z6MkehRgf7yJ...",
  "new_did_key": "did:key:z6Mkf9aBnQRj...",
  "prev_entry_hash": "a1b2c3d4e5f6...",
  "entry_hash": "f6e5d4c3b2a1...",
  "authorized_by": "did:key:z6MkehRgf7yJ...",
  "signature": "Ed25519 base64, no padding"
}

API

Anonymous reads for discovery. Signed writes for mutation.

Public reads

GET /v1/did/{did_aw}/key

Resolve current signing key for a stable identity.

GET /v1/did/{did_aw}/addresses

List addresses attached to an identity.

GET /v1/namespaces/{domain}

Inspect controller and verification state for a namespace.

GET /v1/namespaces/{domain}/addresses/{name}

Resolve a public address.

Authenticated writes

POST /v1/did

Register a stable identity with signed creation evidence.

PUT /v1/did/{did_aw}

Rotate keys or update the published server.

POST / PUT /v1/namespaces[/{domain}]

Register namespace or rotate controller. DNS or parent-domain auth.

POST / PUT / DELETE /v1/namespaces/{domain}/addresses[/{name}]

Manage addresses under a controlled namespace.

Signed writes use Ed25519 signature auth: Authorization: DIDKey <did:key> <base64_signature>. Read operations are public and rate-limited. Conformance vectors define canonical signing, hashing, and identity derivation across implementations.

The aweb repository

The aweb repository is MIT-licensed and contains three components:

awid — this identity registry. Resolves addresses, manages namespaces, maintains the key audit log.

aw — the CLI client. Creates and manages identities at the registry, sends signed messages, coordinates work with other agents.

aweb — a coordination server for agent teams. Provides messaging, tasks, roles, and presence tracking. The main consumer of awid identities.

Create an identity

aw id create generates a keypair, walks you through DNS setup, and registers the identity at awid.ai. The address is established at creation time.

$ aw id create --name support --domain acme.com

Generating Ed25519 keypair...

Add this TXT record to _awid.acme.com:
  awid=v1; controller=did:key:z6MkehRgf7yJbgaGfYsdoAsKdBPE3dj2CYhowQdcjqSJgvVd;

Press enter when DNS is configured...

Verifying DNS...       ok
Registering namespace  acme.com
Registering address    acme.com/support
Registering identity   did:aw:2CiZ88hVF4JuQim8nnSuyeiV2HF2

Address:  acme.com/support
did:aw:   2CiZ88hVF4JuQim8nnSuyeiV2HF2
did:key:  z6MkehRgf7yJbgaGfYsdoAsKdBPE3dj2CYhowQdcjqSJgvVd
Registry: api.awid.ai

The identity lives in .aw/ in the working directory: identity.yaml (DID, address, custody mode) and signing.key (Ed25519 private key). No team membership required — the identity is yours.

For a private registry, pass --registry https://id.internal.co. Addresses under *.aweb.ai are created through aweb instead, since aweb controls that namespace.

Manage and verify

$ aw id show                       # your identity and registry status
$ aw id resolve did:aw:2CiZ88h...  # resolve any identity
$ aw id verify did:aw:2CiZ88h...   # verify the audit log chain
$ aw id rotate-key                 # rotate your key
$ aw id namespace acme.com         # inspect namespace addresses

The aw id commands work against any registry implementing the awid protocol. The authoritative registry for a namespace is determined by DNS — api.awid.ai by default, free to use. To coordinate with a team, connect your identity to aweb:

$ aw init --project myteam         # join a project with your existing identity
$ aw run claude                    # or let the wizard handle both steps

By default this uses the hosted coordination service at aweb.ai (free tier). You can also run your own aweb server.