Goal: run only the agent container against your existing hosted community, not a new local full stack.
From your Buzz local runbook gist: community is russano.communities.buzz.xyz (Block hosted relay). Agents must run on a PC; mobile is client-only.
These were added under ~/Workspace/buzz:
| Path | Role |
|---|---|
Dockerfile.agent |
Sprig image (buzz-acp + buzz-agent + MCP + buzz) |
docker-compose.agent.yml |
Full stack or agent-only |
.env.agent.example |
Template |
docs/agent-runner-container.md |
Design notes |
| Just targets | agent-runner-build, agent-runner-up, agent-runner-up-agent, agent-runner-down, agent-runner-logs, agent-runner-ps |
| Image | buzz-agent-runner:local (built once during the spike) |
Do not use just agent-runner-up for real use (that brings postgres/redis/relay). Use agent-only against the hosted URL.
export VAULT_ADDR=https://vault.wikip.co # or http://vault.wikip.co:8200
# token only in ~/.vault-token or VAULT_TOKEN in this shell — not chat
vault token lookup # must succeed
vault kv get -format=json secret/buzz
# If that path is empty/wrong: vault kv list secret/ and find the buzz entryPresence check only (no values printed):
vault kv get -format=json secret/buzz \
| python3 -c 'import json,sys; d=json.load(sys.stdin)["data"]["data"]; print("keys:", sorted(d.keys())); print("nonempty:", {k: bool(str(v).strip()) for k,v in d.items()})'Expect something like identity + relay + LLM provider fields (names vary). Map them to .env.agent yourself.
Also check related paths if needed: secret/ai/, secret/app/, etc. — only if secret/buzz is incomplete.
cd ~/Workspace/buzz
cp .env.agent.example .env.agent
chmod 600 .env.agentSet at least:
# Hosted community — WebSocket form
BUZZ_RELAY_URL=wss://russano.communities.buzz.xyz
# Agent Nostr identity (from Vault / desktop keyring export you trust)
BUZZ_PRIVATE_KEY=... # nsec or hex — one agent identity
# Optional if hosted community requires them
# BUZZ_API_TOKEN=...
# BUZZ_AUTH_TAG=...
# In-image runtime
BUZZ_ACP_AGENT_COMMAND=buzz-agent
BUZZ_ACP_AGENT_ARGS=
BUZZ_ACP_MCP_COMMAND=buzz-dev-mcp
BUZZ_ACP_AGENTS=1
BUZZ_ACP_RESPOND_TO=anyone # tighten to owner-only later
# BUZZ_ACP_AGENT_OWNER=<your hex pubkey> # if owner-only
# LLM (pick one path that matches Vault)
BUZZ_AGENT_PROVIDER=anthropic # or openai
ANTHROPIC_API_KEY=...
ANTHROPIC_MODEL=claude-sonnet-4-5
# or OPENAI_COMPAT_* / OPENAI_API_KEY for OpenAI-compat
AGENT_WORKSPACE=./.agent-workspaceFill values from Vault offline; never commit .env.agent.
If you want compose defaults to match real use:
- In
docker-compose.agent.yml, defaultBUZZ_RELAY_URLforagent-runnertowss://russano.communities.buzz.xyz(or leave env-only). - Prefer starting only
agent-runnerso postgres/redis/relay never start:
docker compose -f docker-compose.agent.yml --env-file .env.agent up -d agent-runnerdepends_on: relay with required: false should allow agent-only; if compose still wants relay, temporarily remove depends_on for agent-runner or use a tiny override file:
# docker-compose.agent-only.yml
services:
agent-runner:
depends_on: !reset []docker compose -f docker-compose.agent.yml -f docker-compose.agent-only.yml --env-file .env.agent up -d agent-runner- Docs: in
docs/agent-runner-container.md, mark hosted community path as the primary “real use” path; full local stack = dev/spike only.
You already have build/up/logs. Add or rename so the happy path is agent-only + checks:
# Build agent image only
agent-runner-build-agent:
docker build -f Dockerfile.agent -t buzz-agent-runner:local .
# Real use: agent only, hosted relay (needs .env.agent)
agent-runner-up-hosted:
#!/usr/bin/env bash
set -euo pipefail
test -f .env.agent
mkdir -p .agent-workspace
docker compose -f docker-compose.agent.yml --env-file .env.agent up -d --build agent-runner
agent-runner-logs:
docker compose -f docker-compose.agent.yml --env-file .env.agent logs -f agent-runner
agent-runner-down:
docker compose -f docker-compose.agent.yml --env-file .env.agent stop agent-runner
# or: ... down (only if you didn't start the full stack)
# Presence: required env keys set in .env.agent (no values printed)
agent-runner-verify-env:
#!/usr/bin/env bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
need = ["BUZZ_PRIVATE_KEY","BUZZ_RELAY_URL","BUZZ_AGENT_PROVIDER"]
raw = Path(".env.agent").read_text()
vals = {}
for line in raw.splitlines():
line=line.strip()
if not line or line.startswith("#") or "=" not in line: continue
k,v=line.split("=",1); vals[k.strip()]=v.strip().strip('"').strip("'")
for k in need:
v=vals.get(k,"")
print(f"{k}: {'OK' if v else 'MISSING'}")
# provider-specific
p=vals.get("BUZZ_AGENT_PROVIDER","").lower()
if p=="anthropic":
print("ANTHROPIC_API_KEY:", "OK" if vals.get("ANTHROPIC_API_KEY") else "MISSING")
print("ANTHROPIC_MODEL:", "OK" if vals.get("ANTHROPIC_MODEL") else "MISSING")
elif p=="openai":
print("OPENAI path:", "OK" if vals.get("OPENAI_COMPAT_API_KEY") or vals.get("OPENAI_API_KEY") else "MISSING")
print("RELAY looks hosted:", "OK" if "communities.buzz" in vals.get("BUZZ_RELAY_URL","") or vals.get("BUZZ_RELAY_URL","").startswith("wss://") else "CHECK")
PY
# Auth/connect smoke via container logs (no secret dump)
agent-runner-verify-auth:
#!/usr/bin/env bash
set -euo pipefail
docker compose -f docker-compose.agent.yml --env-file .env.agent logs --tail=100 agent-runner \
| rg -i 'buzz-acp starting|agent_pool_ready|agent initialized|relay connect|auth|error|ready' || true
# Soft E2E checklist (human confirms channel reply)
agent-runner-e2e-check:
@echo "1) Container running: docker compose -f docker-compose.agent.yml --env-file .env.agent ps"
@echo "2) Logs show agent_pool_ready + successful relay connect (not connection refused)"
@echo "3) Agent npub is member of a channel on russano.communities.buzz.xyz"
@echo "4) From desktop/phone: @mention the agent; expect a reply"
@echo "5) docker compose ... logs -f agent-runner while testing"Wire agent-runner-up-agent / agent-runner-up-hosted to the same agent-only command.
cd ~/Workspace/buzz
source ./bin/activate-hermit # for just, if you use just
just agent-runner-build-agent
# or: docker build -f Dockerfile.agent -t buzz-agent-runner:local .
just agent-runner-verify-env
mkdir -p .agent-workspace
docker compose -f docker-compose.agent.yml --env-file .env.agent up -d agent-runner
# or your new just agent-runner-up-hosted
docker compose -f docker-compose.agent.yml --env-file .env.agent ps
docker compose -f docker-compose.agent.yml --env-file .env.agent logs -f agent-runnerHealthy log lines (approx):
buzz-acp starting: relay=wss://russano.communities.buzz.xyz ...agent initialized/agent_pool_ready- Relay connect succeeds (no endless
Connection refused)
Bad:
- Missing private key
- Auth errors (token/membership)
- LLM provider errors only when a turn actually runs
Same mental model as the local runbook gist:
- Agent has its own Nostr key (
BUZZ_PRIVATE_KEY). - That identity must be in the community and in the channel you @mention.
- Desktop or CLI can add the agent / accept invite — whatever you already use for Honey/Fizz.
- Phone stays on
russano.communities.buzz.xyz; agent “online” = this container running.
If the agent never sees mentions: membership, wrong relay URL (wss:// vs ws://), or BUZZ_ACP_RESPOND_TO=owner-only without owner set.
- Container up + clean connect logs
- In channel:
@AgentName Reply exactly: HEADLESS_OK - Reply appears
- Optional:
docker compose ... logsshows turn / tool activity
That’s the success bar from the original plan (no GUI).
BUZZ_ACP_RESPOND_TO=owner-only+ your pubkey- One container per agent identity
- No host port publish needed for agent-runner
- Rotate any token that was pasted into chat
- Don’t put
.env.agentin git (already gitignored)
| Item | Status |
|---|---|
| Repo inspection / architecture | Done |
Dockerfile.agent + image build |
Done (once) |
| Compose + docs + basic Just targets | Done (spike shape) |
Headless buzz-acp init without GUI |
Done (local smoke) |
Gist path: hosted russano.communities.buzz.xyz |
Known |
Vault path secret/buzz exists |
Known (list only) |
Map Vault → .env.agent without leaking values |
You |
| Agent-only against hosted relay | You |
| Just: verify-env / verify-auth / e2e-check | You (snippet above) |
| Compose default = hosted, not full stack | You (small edit) |
| Channel membership + real @mention reply | You |
| Token pasted in chat rotated | You (recommended) |
cd ~/Workspace/buzz
export VAULT_ADDR=https://vault.wikip.co
vault token lookup
# fill .env.agent from secret/buzz (offline)
docker build -f Dockerfile.agent -t buzz-agent-runner:local .
mkdir -p .agent-workspace
docker compose -f docker-compose.agent.yml --env-file .env.agent up -d agent-runner
docker compose -f docker-compose.agent.yml --env-file .env.agent logs -f agent-runnerStop:
docker compose -f docker-compose.agent.yml --env-file .env.agent stop agent-runner- Local Buzz runbook gist: https://gist.github.com/anthonyrussano/82c2162257a8eac28af96653787002cf
- Repo spike docs:
~/Workspace/buzz/docs/agent-runner-container.md - Upstream: https://github.com/block/buzz
Personal runbook — remaining manual steps after the headless agent-runner spike. No secrets included.