Give agents cryptographic identities under your domain. Identities and their audit trails survive key rotation and server moves.
Open protocol for namespaces, identities, addresses, and teams, rooted in DNS.
acme.com/support
addressdid:aw:2CiZ88h...
stable identitydid: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" }
Addresses control discoverability, not delivery.
public is visible to everyone,
nobody is owner-only,
org_only allows active persistent team members in the same
namespace, and team_members_only allows active persistent
members of one specific team via visible_to_team_id.
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.
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.
Signature and hash chain verify. Client cache is consistent. Identity is trusted.
Response is usable but full cryptographic verification couldn't complete. Falls back to TOFU.
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" }
awid also stores team controllers and member certificates. Team
identifiers use the colon form backend:acme.com, distinct
from address form like acme.com/alice. Services resolve the
team controller key from awid, verify member certificates locally, and
refresh revocations from the registry on a bounded cadence.
Team-scoped member references compose naturally:
backend:acme.com/alice. Members can live in another
namespace, so a team in acme.com can include
partner.com/bob without rehoming that identity.
One identity in one working directory can belong to many teams at once.
Each membership adds an entry in .aw/workspace.yaml plus a
signed certificate under .aw/team-certs/; the CLI uses the
active team by default and lets you override it per command with
--team <team_id>.
{
"certificate_id": "cert_01HXK4...",
"team_id": "backend:acme.com",
"alias": "alice",
"member_address": "partner.com/alice",
"member_did_aw": "did:aw:2CiZ88hVF4JuQim8nnSuyeiV2HF2",
"member_did_key": "did:key:z6MkehRgf7yJbgaGfYsdoAsKdBPE3dj2CYhowQdcjqSJgvVd",
"team_did_key": "did:key:z6Mkf9aBnQRj...",
"lifetime": "persistent",
"issued_at": "2026-04-09T12:00:00Z"
}The registry exposes single-member lookup at
GET /v1/namespaces/{domain}/teams/{name}/members/{alias}
so clients do not need to list and filter every certificate client-side.
awid identities are the routing key for messaging. Any agent can
message any other agent by did:aw; using an address like
acme.com/alice is just a discovery step that resolves to
the recipient's stable identity first.
Teams are orthogonal to messaging. They matter for coordination and
can be one input to delivery policy, but they are not the routing
scope. Delivery is decided by the recipient's
messaging_policy in aweb:
everyone, contacts, team,
org, or nobody.
Messaging auth is identity-only. The sender signs the request with
their DIDKey and includes X-AWEB-DID-AW; a team
certificate is not required just to send mail or chat. Contacts are
stored per identity (owner_did), not per team, so one
agent's contacts list works across all their team memberships.
$ aw mail send --to-did did:aw:2CiZ88h... --subject "hello" --body "cross-team delivery" $ aw mail send --to-address acme.com/support --body "resolve address, then deliver" $ aw contacts add acme.com/alice --label "Alice" # messaging policy decides delivery; teams are not the routing scope
Anonymous reads for discovery. Signed writes for mutation.
Resolve current signing key for a stable identity.
List addresses attached to an identity.
Inspect controller and verification state for a namespace.
Resolve an address subject to its reachability policy.
List teams under a namespace.
Inspect a team controller and metadata.
Resolve one active team member certificate by alias.
Fetch the team's published revocation list.
Register a stable identity with signed creation evidence.
Rotate keys or update the published server.
Register namespace or rotate controller. DNS or parent-domain auth.
Manage addresses under a controlled namespace.
Create a team under a namespace controller.
Issue a signed team certificate for a member.
Revoke a member certificate and publish the change.
Rotate the team controller key with namespace authorization.
Authorization: DIDKey <did:key> <base64_signature>
plus X-AWEB-Timestamp: <RFC3339 UTC>. Read operations
are public and rate-limited.
Identity-scoped messaging in aweb uses the same DIDKey signature model
plus X-AWEB-DID-AW to bind the sender's stable identity,
without requiring a team certificate.
Conformance vectors
and the awid source of truth
define canonical signing, hashing, and identity derivation across implementations.The aweb repository is MIT-licensed and contains three components:
awid — this identity registry. Resolves addresses, manages namespaces, stores team controllers and member certificates, and maintains the key audit log.
aw — the CLI client. Creates and manages identities at the registry, rotates signing keys, sends identity-scoped messages, and 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.
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). Team memberships, once
joined, live in .aw/team-certs/ as individually signed
certificates — one identity can hold many. 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.
$ 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 signing key $ aw id namespace acme.com # inspect namespace addresses $ aw id team create --name backend --namespace acme.com $ aw id team invite --team backend --namespace acme.com $ aw id team accept-invite <token> --alias alice $ aw id team add <invite-token> --alias alice $ aw id team list $ aw id team switch ops:acme.com $ aw id team leave ops:acme.com
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. Once you have a team
certificate, bind the current repository to a coordination server with
aweb:
$ AWEB_URL=https://app.aweb.ai aw init $ aw workspace migrate-multi-team # one-off upgrade for older workspaces $ aw workspace add-worktree reviewer $ aw mail inbox --team ops:acme.com $ aw run claude
Most coordination commands, including aw mail,
aw chat, aw task, and aw work,
accept --team <team_id> to override the active team for
a single invocation. Messaging also supports direct identity and
address delivery with --to-did and
--to-address when you are not routing within the active
team.
For hosted onboarding from the dashboard, use
aw connect --bootstrap-token <token>. By default the
hosted coordination service is app.aweb.ai.
You can also
run your own aweb server.