beaver-gateway
A gateway for personal agents built on the Claude Agent SDK: conversations
with a lifecycle, windows to talk through, jobs, memory hooks, and a policy
boundary - without an opinion about what the agent is for. A setup is one
config.py (or a package next to it) that assembles a Gateway; this repo
holds the primitives, beaver-agent
is a full setup built on them.
What it gives a setup
- agents/ - what an agent is: a Claude agent with a prompt per
conversation kind, skill sets per kind, gateway tools, a
PreToolUsepolicy; a Raycast agent for cheap fast answers. - backends/ - how a turn runs: the Claude Agent SDK subprocess with a session pool, transcripts and session stores; the Raycast wire.
- conversations/ - the model of a conversation: kinds (master, branch, deep, job, fork), rows and windows, the inject queue with priorities, seeds, turns, questions, closing through a distiller, master rotation, the envelope, the in-process gateway tools.
- jobs/ - cron, webhook and event jobs on pgqueuer, deferred injects, the subscription budget.
- frontends/ - the windows: Telegram (master = General, topic = branch),
markdown files in a vault,
/api+ the admin SPA, an Anthropic-compatible/anthropic/v1/messages, MCP re-exposure at/mcp/<name>, andWebhookFrontendfor a window a setup declares itself - its own request and response schema, its own agent, its own token scope (docs/FRONTEND-PLUGINS.md). - mcp/ - MCP servers a setup declares (stdio, http, python tools), aggregated in-process and handed to agents by name.
- vault/ - watching a directory of notes for the envelope.
- security/ - bearer tokens, the audit log, credential redaction.
- events/ - the in-process bus every frontend taps, and the stream event protocol backends emit.
- storage/ - SQLModel tables and the Postgres session store.
config.py defines Gateway and loads a setup; app.py builds the runtime
from it; cli.py is the entrypoint. The admin SPA in ui/ is the browser
window on all of it: conversations by day, the thread with the tree of tool
calls, the context of the last turn, memory, jobs, usage, tokens and the audit.
Every string the gateway puts in front of
a model or a user has an English default and is overridable
(ConversationTexts, TelegramTexts).
Run
cd examples
CLAUDE_CODE_OAUTH_TOKEN=$(claude setup-token) docker compose up --build
examples/config.py is the smallest setup that starts: one agent, one
python tool, one cron job, the built-in frontends on port 8000; the compose
file next to it adds Postgres. Without Docker: uv sync, build the SPA with
cd ui && bun install && bun run build, then run uv run beaver-gateway with
DATABASE_URL and CONFIG_PATH set. A setup's own secrets come from .env
next to its config (load_dotenv runs before the config is executed).
Develop
make check # ruff format --check, ruff check, ty, pytest
make fix
No comments in code: modules carry a one-line docstring saying what they are for, public configuration fields carry a one-line docstring saying what they mean; everything else is the code.

