docs: README follows the beaver_agent layout, MODELS.md moves to the vault
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
My real beaver-gateway setup (paired with the protocol from beaver.kotikot.com).
|
||||
|
||||
Uses Claude Code and Raycast subscriptions for agents, has some MCPs set up. You can use this as-is or modify to match your needs (config.py).
|
||||
Uses Claude Code and Raycast subscriptions for agents, has some MCPs set up. You can use this as-is or modify to match your needs: `config.py` assembles the gateway from the `beaver_agent/` package.
|
||||
|
||||
## Requirements
|
||||
|
||||
@@ -60,12 +60,14 @@ regular Claude Code; rotate it by running `claude setup-token` again.
|
||||
|
||||
Claude agents run on the Claude Agent SDK. Prompts are granules under
|
||||
`мета/бобер/промпты/` in the vault - plain markdown, the `<tag>` wrappers
|
||||
and the order live in `config.py`; skills are the folders under
|
||||
and the order live in `beaver_agent/prompts.py`; skills are the folders under
|
||||
`мета/бобер/скиллы/` (each becomes a plugin, keep `name:` in SKILL.md
|
||||
latin). The vault must be synced before the gateway can start. The model process runs as `beaver-runner`
|
||||
with a whitelisted environment; the vault is mounted read-write (it is the
|
||||
dispatcher's home), and `policy.py` keeps it out of `.obsidian`, `мета`
|
||||
outside `мета/бобер`, and from deleting anything but its own files.
|
||||
latin), which window loads which set is `beaver_agent/skills.py`. The vault
|
||||
must be synced before the gateway can start. The model process runs as
|
||||
`beaver-runner` with a whitelisted environment; the vault is mounted
|
||||
read-write (it is the dispatcher's home), and `beaver_agent/policy.py` keeps
|
||||
it out of `.obsidian`, `мета` outside `мета/бобер`, and from deleting
|
||||
anything but its own files.
|
||||
|
||||
### 4. Mint a token
|
||||
|
||||
@@ -131,30 +133,55 @@ Needs `KOMODO_URL` / `KOMODO_KEY` / `KOMODO_SECRET` in `.env` (and
|
||||
inject. Jobs, the queue and the subscription window are on the admin **Jobs** page.
|
||||
|
||||
The same key backs the `komodo` tool the dispatcher and deep chats get
|
||||
(`mcps/komodo.py`, архитектура §4.4): one MCP tool with an enumerated
|
||||
(`beaver_agent/hands/komodo.py`): one MCP tool with an enumerated
|
||||
`action` - `status`, `stacks`, `containers`, `logs`, `search_logs`, `updates`,
|
||||
`update`, `deploy`, `restart`, `exec`. `exec` is `docker exec` into any
|
||||
container of the fleet except infrastructure ones (`exec_deny`, periphery by
|
||||
default); prune, destroy and a host terminal do not exist in the enumeration,
|
||||
so they cannot be asked for. The key never reaches the model process.
|
||||
|
||||
## Policy (`policy.py`)
|
||||
## Layout: `config.py` + `beaver_agent/`
|
||||
|
||||
`bypassPermissions` everywhere; the boundary is the read-only vault mount
|
||||
plus `PreToolUse` rules declared per agent (`ClaudeAgent.policy`, архитектура
|
||||
§3.7): writes only under `мета/бобер/`, new files only under `💬 чаты/`,
|
||||
`rm`/`mv`/`cp`/`tee`/`sed -i`/redirects into the vault outside those zones
|
||||
are refused with a reason, and `mcp__firefly__store_*`/`update_*` need the
|
||||
`firefly` skill opened first in the same session. Every tool call lands in
|
||||
the admin **Audit** page as `tool_call`. Run `make check` - it includes the
|
||||
policy and komodo tests.
|
||||
`config.py` is a page: it imports the pieces and calls `Gateway(...)`. The
|
||||
pieces live in `beaver_agent/`, one concern per module:
|
||||
|
||||
## Editing config.py on the mac
|
||||
- `vault.py` - paths and the agent's zone, `TZ`
|
||||
- `prompts.py` - how each role's system prompt is assembled from granules
|
||||
- `skills.py` - which window loads which skill set
|
||||
- `policy.py` - `PreToolUse` rules and vault zones (`ZONES`, `VAULT_POLICY`)
|
||||
- `hands/` - every MCP the setup has and which agent gets which one; the
|
||||
connectors (komodo, home assistant, vibegram) live here too
|
||||
- `agents.py` - the roles (dispatcher, deep, distiller, curator, triage,
|
||||
raycast) and the list of instances with models and effort
|
||||
- `frontends.py` - the windows: Telegram for master and branches, vault
|
||||
files for deep chats, `/api`, `/admin`, `/anthropic`, `/mcp`
|
||||
- `texts.py` - everything the gateway says to the model or to the user,
|
||||
in Russian (the gateway's own defaults are English)
|
||||
- `memory/` - the recall block under a message, the reply log, handouts
|
||||
and seeds, the vault watcher, the curator briefing
|
||||
- `jobs/` - crons and webhooks, one file per job
|
||||
|
||||
## Policy (`beaver_agent/policy.py`)
|
||||
|
||||
`bypassPermissions` everywhere; the boundary is `PreToolUse` rules declared
|
||||
per agent (`ClaudeAgent.policy`): the vault is the dispatcher's home, so it
|
||||
may create, edit and move anywhere except `.obsidian` and `мета` outside
|
||||
`мета/бобер`, and may delete only its own files; the distiller and curator
|
||||
stay in `мета/бобер`; `rm`/`mv`/`cp`/`tee`/`sed -i`/redirects into the vault
|
||||
outside those zones are refused with a reason; `mcp__firefly__store_*` and
|
||||
`update_*` need the `firefly` skill opened first in the same session, and the
|
||||
master cannot open the `vault/` skills at all (a branch can). Every tool call
|
||||
lands in the admin **Audit** page as `tool_call`. Run `make check`.
|
||||
|
||||
## Editing the setup on the mac
|
||||
|
||||
`make sync` installs `../beaver-gateway` editable (extra `local`), so
|
||||
imports in `config.py` resolve against the checkout you are working on;
|
||||
`uv sync --extra prod` pulls the gateway from git instead. Neither is used
|
||||
by the image - the container builds the gateway itself.
|
||||
imports resolve against the checkout you are working on; `uv sync --extra
|
||||
prod` pulls the gateway from git instead. Neither is used by the image - the
|
||||
container builds the gateway itself. To assemble the config against your
|
||||
local vault: `BEAVER_VAULT=~/path/to/vault uv run python -c
|
||||
'from beaver_gateway import config; from pathlib import Path;
|
||||
config.load(Path("config.py"))'` with a `.env` next to it.
|
||||
|
||||
## Useful commands
|
||||
|
||||
@@ -175,13 +202,13 @@ docker compose logs -f obsidian-headless
|
||||
# pull the latest beaver-gateway (when GATEWAY_REF=main)
|
||||
docker compose build gateway && docker compose up -d gateway
|
||||
|
||||
# reload config.py without a full rebuild
|
||||
# reload config.py / beaver_agent without a full rebuild
|
||||
docker compose restart gateway
|
||||
```
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **claude in the container doesn't see the vault** - `cwd=VAULT` in `config.py` resolves to `/vault` *inside* the container, not on the host. Don't change it.
|
||||
- **claude in the container doesn't see the vault** - `VAULT` in `beaver_agent/vault.py` is `/vault` *inside* the container, not on the host. Don't change it; `BEAVER_VAULT` is for assembling the config on the mac only.
|
||||
- **a claude turn fails immediately** - check `docker logs beaver-gateway` for the `claude[<agent>]:` stderr lines. Usually auth: redo step 3.
|
||||
- **gateway restarts in a loop right after first `up`** - `config.py` reads prompt granules from `/vault/мета/бобер/промпты`; until Obsidian Sync has pulled the vault they are missing. Finish step 2, it settles.
|
||||
- **gateway restarts in a loop right after first `up`** - `beaver_agent/prompts.py` reads prompt granules from `/vault/мета/бобер/промпты`; until Obsidian Sync has pulled the vault they are missing. Finish step 2, it settles.
|
||||
- **the model cannot write into `мета/бобер`** - the entrypoint grants `beaver-runner` an ACL on the two rw sub-mounts once at start; files that Sync creates later inherit it through the default ACL. If `setfacl` is unsupported on the volume it falls back to `chown`, and then files Sync writes afterwards as root stay read-only for the model until the next restart.
|
||||
|
||||
Reference in New Issue
Block a user