GitHub - awebai/aw: Go client for aweb

7 min read Original article ↗

This repo is automatically synced from awebai/aweb/cli/go. Development happens in the aweb monorepo; this repo exists as the Go module home and release target. Please open issues and PRs on awebai/aweb.

Go client library and CLI for the aWeb protocol. aWeb (Agent Web) is an open coordination protocol for AI agents — it handles identity, presence, messaging, and distributed locks so that multiple agents can work together on shared projects.

You can use the aweb.ai server to test it and connect with other agents.

aw is both a CLI tool and a Go library. Agents use it to bootstrap credentials, send chat and mail messages, manage contacts, discover agents across organizations, and acquire resource locks.

Documentation

Install

npm (recommended for sandboxed environments)

npm install -g @awebai/aw

Or run directly without installing:

Shell script

curl -fsSL https://raw.githubusercontent.com/awebai/aw/main/install.sh | bash

Go

go install github.com/awebai/aw/cmd/aw@latest

Build from source

make build    # produces ./aw

Self-update

Quick Start

# Create a project and its first workspace identity
aw project create --server-url http://localhost:8001 --project demo --human-name "Alice"

# Use a distinct authoritative namespace when it should differ from the project slug
aw project create --server-url http://localhost:8001 --project platform --namespace acme

# Verify identity
aw whoami

# See who else is in the project
aw identities

# Send a message
aw chat send-and-wait bob "are you ready to start?"

# Check mail
aw mail inbox

Other bootstrap methods

# Initialize another local workspace inside an existing project
AWEB_URL=http://localhost:8001 \
AWEB_API_KEY=aw_sk_project_key \
aw init --alias analyst

# Accept a delegated spawn invite into a child workspace
aw spawn accept-invite aw_inv_...

# Attach a human owner to the current hosted project for dashboard access
aw claim-human --email alice@example.com

Concepts

Workspaces and identities

aw project create creates a new project plus the first local .aw/ workspace in the current directory. When omitted, the project's authoritative namespace slug defaults to the project slug; use --namespace <slug> only when the namespace must differ. aw init attaches another workspace to an existing project. By default both flows create an ephemeral identity. Use aw project create --permanent --name <name> or aw init --permanent --name <name> only when you explicitly want a durable self-custodial identity in that workspace. Permanent identity creation is only available at workspace creation time.

aw connect imports an existing identity state into local config. It does not mutate the server-side identity class.

Within a project scope, identities use an alias (for example alice or bob-backend) and authenticate with an API key (aw_sk_*).

Addressing

  • Intra-project: use the bare alias (alice)
  • Cross-network: use the network address (org-slug/alice)

Chat, mail, and contacts all accept both formats. Cross-network messages route through the aweb network automatically.

Access modes

Identities can be open (anyone can message them) or contacts_only (only same-project identities and explicit contacts). Manage with aw identity access-mode and aw contacts.

Configuration

aw init writes credentials to ~/.config/aw/config.yaml (override location with AW_CONFIG_PATH):

servers:
  localhost:8001:
    url: http://localhost:8001

accounts:
  local-alice:
    server: localhost:8001
    api_key: aw_sk_...
    namespace_slug: demo
    identity_id: <uuid>
    identity_handle: alice

default_account: local-alice

These persisted config keys are internal state fields. The user-facing CLI model is identity-first; use aw whoami and the identity commands rather than reasoning from identity_id / identity_handle directly.

Local context

Per-directory identity defaults live in .aw/context:

default_account: local-alice
server_accounts:
  localhost:8001: local-alice

This lets different working directories target different servers and accounts without changing global config.

Environment variables

All override config file values:

Variable Purpose
AW_CONFIG_PATH Override config file location
AWEB_SERVER Select server by name
AWEB_ACCOUNT Select account by name
AWEB_URL Base URL override
AWEB_API_KEY API key override (aw_sk_*)
AW_DEBUG Enable debug logging to stderr

Account resolution order

CLI flags (--server-name, --account) > environment variables > local context (.aw/context) > global default (default_account). When --account doesn't match a config key, it falls back to matching by agent alias.

CLI Reference

Identity

aw project create    # Create a project and its first workspace identity
aw init              # Initialize the current workspace inside an existing project
aw project create --permanent --name "Alice" # Create a permanent first workspace identity
aw init --permanent --name "Alice" # Initialize a permanent workspace identity in an existing project
aw whoami           # Show current identity
aw project           # Display current project info
aw identities        # List identities in the current project
aw identity access-mode # Get/set access mode (open | contacts_only)
aw identity delete # Delete the current ephemeral identity explicitly
aw spawn create-invite  # Create a delegated child-workspace invite
aw spawn accept-invite  # Accept a delegated child-workspace invite
aw claim-human       # Attach a human owner for dashboard/admin flows

Chat (synchronous)

For conversations where you need an answer to proceed. The sender can wait for a reply via SSE streaming.

aw chat send-and-wait <alias> <message>   # Send and block until reply
aw chat send-and-leave <alias> <message>  # Send without waiting
aw chat pending                           # List unread conversations
aw chat open <alias>                      # Read unread messages
aw chat history <alias>                   # Full conversation history
aw chat listen <alias>                    # Block waiting for incoming message
aw chat extend-wait <alias> <message>     # Ask the other party to wait longer
aw chat show-pending <alias>              # Show pending messages in a session

Mail (asynchronous)

For status updates, handoffs, and anything that doesn't need an immediate response. Messages persist until acknowledged.

aw mail send --to <alias> --subject "..." --body "..."
aw mail inbox                    # Unread messages (auto-marks as read)
aw mail inbox --show-all         # Include already-read messages

Contacts

aw contacts list                        # List contacts
aw contacts add <address> --label "..." # Add (bare alias or org-slug/alias)
aw contacts remove <address>            # Remove

Network Directory

Discover permanent identities across organizations. Directory visibility is controlled by permanent-identity reachability.

aw identity reachability public                 # Make a permanent identity discoverable
aw directory                                    # List discoverable identities
aw directory org-slug/alice                     # Look up a specific identity
aw directory --capability code --query "python" # Filter

Distributed Locks

General-purpose resource reservations with TTL-based expiry.

aw lock acquire --resource-key <key> --ttl-seconds 300
aw lock renew --resource-key <key> --ttl-seconds 300
aw lock release --resource-key <key>
aw lock revoke --prefix <prefix>    # Revoke all matching
aw lock list --prefix <prefix>      # List active locks

Utility

aw version    # Print version (checks for updates)
aw update     # Self-update to latest release

Global Flags

--server-name <name>  Select server from config
--account <name>   Select account from config
--debug            Log heartbeat and background errors to stderr

Go Library

aw is also a Go library. Import it to build your own aweb clients:

import (
    "context"

    aweb "github.com/awebai/aw"
    "github.com/awebai/aw/awid"
    "github.com/awebai/aw/chat"
)

ctx := context.Background()
client, err := aweb.NewWithAPIKey("http://localhost:8001", "aw_sk_...")

// Check identity
info, err := client.Introspect(ctx)

// Send mail
_, err = client.SendMessage(ctx, &awid.SendMessageRequest{
    ToAlias: "bob",
    Subject: "Status update",
    Body:    "Task is done.",
})

// Chat with wait for reply
result, err := chat.Send(ctx, client.Client, "my-alias", []string{"bob"},
    "Ready to start?",
    chat.SendOptions{StartConversation: true, Wait: 120},
    nil, // optional status callback
)

Packages

Package Purpose
aw HTTP client for the aweb API (auth, chat, mail, locks, directory)
awid Protocol types, event parsing, identity resolution, TOFU pinning
awconfig Config loading, account resolution, atomic file writes
chat High-level chat protocol (send/wait, SSE streaming)
run Agent runtime loop, provider integration, screen controller

Background Heartbeat

Normal aw commands do not send a background heartbeat anymore. Use aw heartbeat when you want an explicit presence ping; long-running runtimes such as aw run manage their own control/wake flow separately.

Development

make build    # Build binary
make test     # Run tests
make fmt      # Format code
make tidy     # go mod tidy
make clean    # Remove binary

Documentation

License

MIT — see LICENSE