@animalabs/connectome-host 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +20 -0
- package/.github/workflows/publish.yml +65 -0
- package/ARCHITECTURE.md +355 -0
- package/CHANGELOG.md +30 -0
- package/HEADLESS-FLEET-PLAN.md +330 -0
- package/README.md +189 -0
- package/UNIFIED-TREE-PLAN.md +242 -0
- package/bun.lock +288 -0
- package/docs/AGENT-MEMORY-GUIDE.md +214 -0
- package/docs/AGENT-ONBOARDING.md +541 -0
- package/docs/ATTENTION-AND-GATING.md +120 -0
- package/docs/DEPLOYMENTS.md +130 -0
- package/docs/DEV-ENVIRONMENT.md +215 -0
- package/docs/LIBRARY-PIPELINE.md +286 -0
- package/docs/LOCUS-ROUTING-DESIGN.md +115 -0
- package/docs/claudeai-evacuation.md +228 -0
- package/docs/debug-context-api.md +208 -0
- package/docs/webui-deployment.md +219 -0
- package/package.json +33 -0
- package/recipes/SETUP.md +308 -0
- package/recipes/TRIUMVIRATE-SETUP.md +467 -0
- package/recipes/claude-export-revive.json +19 -0
- package/recipes/clerk.json +157 -0
- package/recipes/knowledge-miner.json +174 -0
- package/recipes/knowledge-reviewer.json +76 -0
- package/recipes/mcpl-editor-test.json +38 -0
- package/recipes/prompts/transplant-addendum.md +17 -0
- package/recipes/triumvirate.json +63 -0
- package/recipes/webui-fleet-test.json +27 -0
- package/recipes/webui-test.json +16 -0
- package/recipes/zulip-miner.json +87 -0
- package/scripts/connectome-doctor +373 -0
- package/scripts/evacuator.ts +956 -0
- package/scripts/import-claudeai-export.ts +747 -0
- package/scripts/lib/line-reader.ts +53 -0
- package/scripts/test-historical-thinking.ts +148 -0
- package/scripts/warmup-session.ts +336 -0
- package/src/agent-name.ts +58 -0
- package/src/commands.ts +1074 -0
- package/src/headless.ts +528 -0
- package/src/index.ts +867 -0
- package/src/logging-adapter.ts +208 -0
- package/src/mcpl-config.ts +199 -0
- package/src/modules/activity-module.ts +270 -0
- package/src/modules/channel-mode-module.ts +260 -0
- package/src/modules/fleet-module.ts +1705 -0
- package/src/modules/fleet-types.ts +225 -0
- package/src/modules/lessons-module.ts +465 -0
- package/src/modules/mcpl-admin-module.ts +345 -0
- package/src/modules/retrieval-module.ts +327 -0
- package/src/modules/settings-module.ts +143 -0
- package/src/modules/subagent-module.ts +2074 -0
- package/src/modules/subscription-gc-module.ts +322 -0
- package/src/modules/time-module.ts +85 -0
- package/src/modules/tui-module.ts +76 -0
- package/src/modules/web-ui-curve-page.ts +249 -0
- package/src/modules/web-ui-module.ts +2595 -0
- package/src/recipe.ts +1003 -0
- package/src/session-manager.ts +278 -0
- package/src/state/agent-tree-reducer.ts +431 -0
- package/src/state/fleet-tree-aggregator.ts +195 -0
- package/src/strategies/frontdesk-strategy.ts +364 -0
- package/src/synesthete.ts +68 -0
- package/src/tui.ts +2200 -0
- package/src/types/bun-ffi.d.ts +6 -0
- package/src/web/protocol.ts +648 -0
- package/test/agent-name.test.ts +62 -0
- package/test/agent-tree-fleet-launch.test.ts +64 -0
- package/test/agent-tree-reducer-parity.test.ts +194 -0
- package/test/agent-tree-reducer.test.ts +443 -0
- package/test/agent-tree-rollup.test.ts +109 -0
- package/test/autobio-progress-snapshot.test.ts +40 -0
- package/test/claudeai-export-importer.test.ts +386 -0
- package/test/evacuator.test.ts +332 -0
- package/test/fleet-commands.test.ts +244 -0
- package/test/fleet-no-subfleets.test.ts +147 -0
- package/test/fleet-orchestration.test.ts +353 -0
- package/test/fleet-recipe.test.ts +124 -0
- package/test/fleet-route.test.ts +44 -0
- package/test/fleet-smoke.test.ts +479 -0
- package/test/fleet-subscribe-union-e2e.test.ts +123 -0
- package/test/fleet-subscribe-union.test.ts +85 -0
- package/test/fleet-tree-aggregator-e2e.test.ts +110 -0
- package/test/fleet-tree-aggregator.test.ts +215 -0
- package/test/frontdesk-strategy.test.ts +326 -0
- package/test/headless-describe.test.ts +182 -0
- package/test/headless-smoke.test.ts +190 -0
- package/test/logging-adapter.test.ts +87 -0
- package/test/mcpl-admin-module.test.ts +213 -0
- package/test/mcpl-agent-overlay.test.ts +126 -0
- package/test/mock-headless-child.ts +133 -0
- package/test/recipe-cache-ttl.test.ts +37 -0
- package/test/recipe-env.test.ts +157 -0
- package/test/recipe-path-resolution.test.ts +170 -0
- package/test/subagent-async-timeout.test.ts +381 -0
- package/test/subagent-fork-materialise.test.ts +241 -0
- package/test/subagent-peek-scoping.test.ts +180 -0
- package/test/subagent-peek-zombie.test.ts +148 -0
- package/test/subagent-reaper-in-flight.test.ts +229 -0
- package/test/subscription-gc-module.test.ts +136 -0
- package/test/warmup-handoff.test.ts +150 -0
- package/test/web-ui-bind.test.ts +51 -0
- package/test/web-ui-module.test.ts +246 -0
- package/test/web-ui-protocol.test.ts +0 -0
- package/tsconfig.json +14 -0
- package/web/bun.lock +357 -0
- package/web/index.html +12 -0
- package/web/package.json +24 -0
- package/web/src/App.tsx +1931 -0
- package/web/src/Context.tsx +158 -0
- package/web/src/ContextDocument.tsx +150 -0
- package/web/src/Files.tsx +271 -0
- package/web/src/Lessons.tsx +164 -0
- package/web/src/Mcpl.tsx +310 -0
- package/web/src/Stream.tsx +119 -0
- package/web/src/TreeSidebar.tsx +283 -0
- package/web/src/Usage.tsx +182 -0
- package/web/src/main.tsx +7 -0
- package/web/src/styles.css +26 -0
- package/web/src/tree.ts +268 -0
- package/web/src/wire.ts +120 -0
- package/web/tsconfig.json +21 -0
- package/web/vite.config.ts +32 -0
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
# Triumvirate Setup Guide
|
|
2
|
+
|
|
3
|
+
A step-by-step guide to setting up the **Knowledge Mining Triumvirate** — three specialist AI agents (miner, reviewer, clerk) running under a single conductor in one terminal. Each agent has its own recipe, its own Chronicle data store, and its own role in a shared knowledge pipeline.
|
|
4
|
+
|
|
5
|
+
This guide assumes you're comfortable in a terminal and editing JSON files, but not that you know TypeScript or the internals of the connectome framework.
|
|
6
|
+
|
|
7
|
+
## What you get
|
|
8
|
+
|
|
9
|
+
One terminal, four AI agents cooperating:
|
|
10
|
+
|
|
11
|
+
- **Conductor** (in the TUI, the one you talk to) — supervises the other three, reports status, intervenes only when asked.
|
|
12
|
+
- **Miner** — reads your team's Zulip conversations, extracts structured knowledge, writes **Draft** documents to `library-mined/`.
|
|
13
|
+
- **Reviewer** — critiques the miner's drafts for accuracy, flags unsupported claims, writes **Reviewed** versions to `library-reviewed/`.
|
|
14
|
+
- **Clerk** — sits on a Zulip channel (`#${ZULIP_CHANNEL}` by default), answers questions by quoting the library, files knowledge-request tickets when the library is insufficient.
|
|
15
|
+
|
|
16
|
+
The three specialists coordinate with each other via a **shared filesystem** and **shared Zulip channels** — not through the conductor. Files flow: `library-mined/` → `library-reviewed/` (via reviewer) → cited in clerk's Zulip answers. Knowledge gaps flow: clerk → `knowledge-requests/` (future miner sessions dispatch on these).
|
|
17
|
+
|
|
18
|
+
You watch it all from one terminal.
|
|
19
|
+
|
|
20
|
+
## Prerequisites
|
|
21
|
+
|
|
22
|
+
| Tool / resource | Why | Install / obtain |
|
|
23
|
+
|---|---|---|
|
|
24
|
+
| [Node.js](https://nodejs.org/) 20+ | Runtime for the Zulip MCP server | `nvm install 20` or download from nodejs.org |
|
|
25
|
+
| [Bun](https://bun.sh/) | Runs connectome-host itself | `curl -fsSL https://bun.sh/install \| bash` |
|
|
26
|
+
| [Anthropic API key](https://console.anthropic.com/) | LLM access for all four agents | Sign up at console.anthropic.com — note that four agents run concurrently, so expect proportionally higher API spend |
|
|
27
|
+
| A Zulip account with admin access | Needed to create a bot and a dedicated channel | Your organization's Zulip |
|
|
28
|
+
| Git | To clone connectome-host and the Zulip MCP server | Usually pre-installed |
|
|
29
|
+
|
|
30
|
+
The triumvirate is currently supported on **Linux / macOS / WSL2**. Windows support (native) is not yet implemented.
|
|
31
|
+
|
|
32
|
+
## Step 1: Install connectome-host
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
git clone https://github.com/anima-research/connectome-host.git
|
|
36
|
+
cd connectome-host
|
|
37
|
+
bun install
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Verify it works in isolation before adding any agents:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
bun src/index.ts --no-recipe
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
You should see a TUI with a generic assistant. Type `/quit` to exit. If this didn't work, fix the underlying issue (usually: missing Bun, missing API key) before continuing.
|
|
47
|
+
|
|
48
|
+
## Step 2: Install the Zulip MCP server
|
|
49
|
+
|
|
50
|
+
Two of the three specialists (miner, clerk) talk to Zulip. They do that through a small adapter called `zulip_mcp`. The MCPL-addendum work has merged into upstream `main` ([PR #3](https://github.com/antra-tess/zulip_mcp/pull/3)) so the install is just clone + build:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# From inside the connectome-host directory:
|
|
54
|
+
cd ..
|
|
55
|
+
git clone https://github.com/antra-tess/zulip_mcp.git
|
|
56
|
+
cd zulip_mcp
|
|
57
|
+
npm install
|
|
58
|
+
npm run build
|
|
59
|
+
cd ../connectome-host
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
This leaves a built binary at `../zulip_mcp/build/index.js`, relative to connectome-host. The triumvirate recipes expect it exactly there — don't rename or move the directory.
|
|
63
|
+
|
|
64
|
+
## Step 3: Create a Zulip bot and get credentials
|
|
65
|
+
|
|
66
|
+
The Triumvirate posts and listens as a Zulip bot (or a dedicated user account — a bot is cleaner). You need a `.zuliprc` file with that bot's credentials.
|
|
67
|
+
|
|
68
|
+
### Option A: Bot account (recommended)
|
|
69
|
+
|
|
70
|
+
1. In Zulip, go to **Settings > Organization > Bots** (you need admin rights).
|
|
71
|
+
2. Click **Add a new bot**. Choose **Generic bot** type.
|
|
72
|
+
3. Give it a name like "Mining Triumvirate" and an email like `mining-triumvirate-bot@your-org.zulipchat.com`.
|
|
73
|
+
4. Download the `.zuliprc` file Zulip gives you.
|
|
74
|
+
|
|
75
|
+
### Option B: Your own user account
|
|
76
|
+
|
|
77
|
+
1. In Zulip, go to **Settings > Personal > API key**.
|
|
78
|
+
2. Download the `.zuliprc` for your user.
|
|
79
|
+
|
|
80
|
+
⚠ If you go with Option B, every message the agents post will appear as *you* posting it. The bot approach is strongly preferred for anything other than a personal experiment.
|
|
81
|
+
|
|
82
|
+
### Place the file
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
# From the connectome-host directory:
|
|
86
|
+
cp ~/Downloads/zuliprc .zuliprc
|
|
87
|
+
chmod 600 .zuliprc
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
(`.zuliprc` is already gitignored — your credentials won't be committed accidentally.)
|
|
91
|
+
|
|
92
|
+
The file should look roughly like:
|
|
93
|
+
|
|
94
|
+
```ini
|
|
95
|
+
[api]
|
|
96
|
+
email=mining-triumvirate-bot@your-org.zulipchat.com
|
|
97
|
+
key=abc123...
|
|
98
|
+
site=https://your-org.zulipchat.com
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Step 4: Prepare the Zulip channels
|
|
102
|
+
|
|
103
|
+
The triumvirate needs one dedicated channel plus whatever channels you want the miner to extract knowledge from.
|
|
104
|
+
|
|
105
|
+
### The clerk's channel (`#${ZULIP_CHANNEL}`)
|
|
106
|
+
|
|
107
|
+
The clerk agent staffs one specific channel — by convention, `#${ZULIP_CHANNEL}`. It responds to questions posted there by quoting the library.
|
|
108
|
+
|
|
109
|
+
1. In Zulip, create a new channel called **`${ZULIP_CHANNEL}`** (or edit the recipe in the next step if you want a different name).
|
|
110
|
+
2. Subscribe your bot account to that channel.
|
|
111
|
+
3. Optionally: tell your team this is where they ask library questions.
|
|
112
|
+
|
|
113
|
+
### Channels for the miner to read
|
|
114
|
+
|
|
115
|
+
The miner reads other channels to extract knowledge. By default, the recipe has the miner starting with manual channel subscription — meaning the agent itself decides which channels to listen to based on the conversation with the user. You don't need to pre-subscribe it anywhere; you'll direct it in the TUI.
|
|
116
|
+
|
|
117
|
+
If you want to narrow what it can see, edit `recipes/zulip-miner.json` → `"ZULIP_SUBSCRIBE"` and list the channels you want pre-subscribed, comma-separated.
|
|
118
|
+
|
|
119
|
+
## Step 5: Fill in secrets in `.env`
|
|
120
|
+
|
|
121
|
+
Secrets — API keys, tokens, service endpoints — live in `.env` at the connectome-host root. Recipes in `recipes/` reference them via `${VAR_NAME}` placeholders, and the framework substitutes at recipe-load time. Your recipe files stay commit-safe; your secrets stay gitignored.
|
|
122
|
+
|
|
123
|
+
Copy the example and edit:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
cp .env.example .env
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Required for every run:
|
|
130
|
+
|
|
131
|
+
```ini
|
|
132
|
+
ANTHROPIC_API_KEY=sk-ant-...
|
|
133
|
+
|
|
134
|
+
# The Zulip channel the clerk staffs. Set to the channel name
|
|
135
|
+
# you created in Step 4 (e.g. `tracker-miner-f`, `knowledge-desk`,
|
|
136
|
+
# `q-and-a` — whatever you picked). All three recipes substitute
|
|
137
|
+
# this at load time wherever they reference the channel.
|
|
138
|
+
ZULIP_CHANNEL=your-channel-name
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Optional — **only** if you want the miner to extract from those sources (otherwise remove the relevant `mcpServers` block from `recipes/knowledge-miner.json` and skip these):
|
|
142
|
+
|
|
143
|
+
```ini
|
|
144
|
+
# GitLab (knowledge-miner.json: gitlab)
|
|
145
|
+
GITLAB_TOKEN=glpat-...
|
|
146
|
+
GITLAB_API_URL=https://gitlab.example.com/api/v4
|
|
147
|
+
|
|
148
|
+
# Notion (knowledge-miner.json: syncntn)
|
|
149
|
+
NOTION_STORAGE_URL=http://localhost:8000
|
|
150
|
+
NOTION_WORKSPACE_ID=...
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Bun auto-loads `.env`, so nothing else to wire. If a recipe references a `${VAR}` you haven't set, the child's startup will fail with a clear message telling you which variable is missing and which recipe referenced it.
|
|
154
|
+
|
|
155
|
+
## Step 6: Decide which data sources you want
|
|
156
|
+
|
|
157
|
+
The miner child uses `recipes/knowledge-miner.json`, which comes pre-wired to talk to **Zulip, Notion, GitLab, and DuckDuckGo** (public web). The recipe itself references credentials via `${VAR}` placeholders — you don't edit the recipe to fill in secrets; you set the env vars in Step 5 and the framework substitutes at load time.
|
|
158
|
+
|
|
159
|
+
You decide which sources are active by whether you **set the matching env vars** and whether you **keep the matching mcpServers block in the recipe**.
|
|
160
|
+
|
|
161
|
+
### Zulip (required, already configured)
|
|
162
|
+
|
|
163
|
+
You set this up in Steps 2–4. The entry under `mcpServers.zulip` uses `../zulip_mcp/build/index.js` and reads `./.zuliprc`. Nothing to change.
|
|
164
|
+
|
|
165
|
+
### GitLab (optional)
|
|
166
|
+
|
|
167
|
+
To enable: create a GitLab Personal Access Token (User Settings → Access Tokens) with scopes `read_api` and `read_repository` (add `api` for write access to issues/comments), and set these in `.env`:
|
|
168
|
+
|
|
169
|
+
```ini
|
|
170
|
+
GITLAB_TOKEN=glpat-...
|
|
171
|
+
GITLAB_API_URL=https://gitlab.example.com/api/v4
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
No separate install — the recipe runs `npx @zereight/mcp-gitlab` on demand.
|
|
175
|
+
|
|
176
|
+
To disable: remove the `gitlab` block from `recipes/knowledge-miner.json`. If you leave it in but don't set the env vars, the child will fail to start with a message like `Recipe "recipes/knowledge-miner.json" references environment variable ${GITLAB_TOKEN} which is not set.` — that's the system telling you to either fill in the env var or delete the block.
|
|
177
|
+
|
|
178
|
+
### Notion (optional)
|
|
179
|
+
|
|
180
|
+
To enable: install a Notion MCP server (the recipe's template is named `syncntn`; any MCP server with matching tool names works — see [SETUP.md → Notion](./SETUP.md#notion-optional-via-an-mcp-server) for selection caveats) and set:
|
|
181
|
+
|
|
182
|
+
```ini
|
|
183
|
+
NOTION_STORAGE_URL=http://localhost:8000
|
|
184
|
+
NOTION_WORKSPACE_ID=...
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
To disable: remove the `syncntn` block from `recipes/knowledge-miner.json`. Same behavior as above — unset env + kept block = startup failure with a clear message.
|
|
188
|
+
|
|
189
|
+
### DuckDuckGo web search (optional, enabled by default)
|
|
190
|
+
|
|
191
|
+
The miner is wired to [`nickclyde/duckduckgo-mcp-server`](https://github.com/nickclyde/duckduckgo-mcp-server) as `ddg`. No API key — DuckDuckGo's public HTML search, scraped at request time.
|
|
192
|
+
|
|
193
|
+
To enable: install the server once as a sibling of `connectome-host/`:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
cd ..
|
|
197
|
+
git clone https://github.com/nickclyde/duckduckgo-mcp-server.git
|
|
198
|
+
cd duckduckgo-mcp-server
|
|
199
|
+
python3 -m venv .venv
|
|
200
|
+
.venv/bin/pip install -e .
|
|
201
|
+
cd ../connectome-host
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
The recipe expects the entry-point at `../duckduckgo-mcp-server/.venv/bin/duckduckgo-mcp-server`. No env vars required.
|
|
205
|
+
|
|
206
|
+
Web hits get tagged `[WEB: <url>]` in mined reports — internal `[SRC]` always wins over `[WEB]` for org-specific terms; the reviewer flags collisions.
|
|
207
|
+
|
|
208
|
+
To disable: remove the `ddg` block from `recipes/knowledge-miner.json`. The agent will skip the public web.
|
|
209
|
+
|
|
210
|
+
### Summary table
|
|
211
|
+
|
|
212
|
+
| Source | Keep the block in recipe? | Env vars needed |
|
|
213
|
+
|---|---|---|
|
|
214
|
+
| Zulip | Yes | (configured via `.zuliprc`, no `${VAR}`) |
|
|
215
|
+
| GitLab | Yes if using, remove otherwise | `GITLAB_TOKEN`, `GITLAB_API_URL` |
|
|
216
|
+
| Notion | Yes if using, remove otherwise | `NOTION_STORAGE_URL`, `NOTION_WORKSPACE_ID` |
|
|
217
|
+
| DuckDuckGo | Yes if you want public web search, remove otherwise | none (no API key) |
|
|
218
|
+
|
|
219
|
+
### Tweaks you can still make to the recipe files
|
|
220
|
+
|
|
221
|
+
You can also edit `recipes/triumvirate.json` if you want to:
|
|
222
|
+
|
|
223
|
+
- **Rename the clerk's channel** away from `${ZULIP_CHANNEL}` — edit `recipes/clerk.json`, change `ZULIP_SUBSCRIBE` and the `tracker-channel` wake policy's `channel` field.
|
|
224
|
+
- **Swap the model** — change `"model": "claude-opus-4-6"` to `claude-sonnet-4-6` (faster, cheaper) or another Claude model.
|
|
225
|
+
- **Adjust autoStart** — set `"autoStart": false` on any child if you want to leave them inactive until you (or the conductor) explicitly launch them.
|
|
226
|
+
|
|
227
|
+
## Step 7: First launch
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
bun src/index.ts recipes/triumvirate.json
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
What you'll see:
|
|
234
|
+
|
|
235
|
+
1. The TUI comes up with the "Knowledge Mining Triumvirate" banner.
|
|
236
|
+
2. Over the next 30–60 seconds, the three children spawn in the background. Each one starts its own connectome-host process, connects to the Anthropic API, and boots its Zulip / workspace machinery.
|
|
237
|
+
3. Press **Tab** a couple of times to cycle through view modes. One of them is the **process fleet** view — it lists the three children and their status. All three should reach **ready** (green). If any show **crashed** (red), jump to Troubleshooting.
|
|
238
|
+
4. Ask the conductor `are all three ready?` — it'll run `fleet--list` and confirm. This also serves as a quick "am I set up correctly" smoke test.
|
|
239
|
+
|
|
240
|
+
### The four view modes
|
|
241
|
+
|
|
242
|
+
Press **Tab** to cycle between views. Press **Ctrl+F** to jump straight to the process fleet view from anywhere.
|
|
243
|
+
|
|
244
|
+
| View | What it shows |
|
|
245
|
+
|---|---|
|
|
246
|
+
| **chat** | Your conversation with the conductor |
|
|
247
|
+
| **subagents** | In-process subagents the conductor has forked (usually empty — conductor doesn't fork much) |
|
|
248
|
+
| **processes** | The three triumvirate children and their live status |
|
|
249
|
+
| **peek-proc** | Live event stream from one selected child (press `p` on a child in the processes view) |
|
|
250
|
+
|
|
251
|
+
## Using the Triumvirate
|
|
252
|
+
|
|
253
|
+
Three ways to drive the system:
|
|
254
|
+
|
|
255
|
+
### 1. Ask the conductor
|
|
256
|
+
|
|
257
|
+
Just type. The conductor reads the request, decides what to do, and usually reports back.
|
|
258
|
+
|
|
259
|
+
```
|
|
260
|
+
> What are the three agents doing right now?
|
|
261
|
+
> Has the reviewer finished anything today?
|
|
262
|
+
> Miner looks stuck. What's it waiting for?
|
|
263
|
+
> If the clerk is idle, ask it to re-index whatever it has.
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### 2. Route directly with `@childname`
|
|
267
|
+
|
|
268
|
+
Bypass the conductor and send straight to a child. Useful when you know exactly who you want to address and don't want the conductor in the loop.
|
|
269
|
+
|
|
270
|
+
```
|
|
271
|
+
> @miner Start extracting from channel #platform-design, focus on the Q1 decisions.
|
|
272
|
+
> @clerk Post a status message in #${ZULIP_CHANNEL} saying the library is being rebuilt.
|
|
273
|
+
> @reviewer Re-check the packet-pipeline doc against the latest lessons.
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
The conductor doesn't see these messages or their responses.
|
|
277
|
+
|
|
278
|
+
### 3. Slash commands
|
|
279
|
+
|
|
280
|
+
| Command | What it does |
|
|
281
|
+
|---|---|
|
|
282
|
+
| `/fleet list` | One-line status for every child |
|
|
283
|
+
| `/fleet status <name>` | Detailed status (pid, dataDir, recipe, last event, etc.) |
|
|
284
|
+
| `/fleet peek <name>` | Open the live event stream for a child |
|
|
285
|
+
| `/fleet stop <name>` | Kill a child gracefully |
|
|
286
|
+
| `/fleet restart <name>` | Kill + respawn |
|
|
287
|
+
| `/status` | The conductor's own state |
|
|
288
|
+
| `/quit` | Exit. If children are still running, you'll be asked what to do with them — see below. |
|
|
289
|
+
|
|
290
|
+
### Exiting
|
|
291
|
+
|
|
292
|
+
When you type `/quit`, if any children are still running, the conductor asks:
|
|
293
|
+
|
|
294
|
+
```
|
|
295
|
+
3 children still running: miner, reviewer, clerk
|
|
296
|
+
Stop them before exit? [Y/n/d] — Y=kill gracefully, n=cancel quit, d=detach and leave running
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
- **Y** (or just Enter) — stop everything cleanly and exit. All children shut down.
|
|
300
|
+
- **n** — cancel the exit. The TUI stays up.
|
|
301
|
+
- **d** — exit the TUI but leave the three children running in the background. They'll keep doing whatever they were doing. The next time you run `bun src/index.ts recipes/triumvirate.json`, the new conductor will **adopt** them — re-attach to the running children instead of respawning duplicates.
|
|
302
|
+
|
|
303
|
+
This is the "leave the bots working overnight, come back tomorrow" workflow.
|
|
304
|
+
|
|
305
|
+
## What the agents actually do
|
|
306
|
+
|
|
307
|
+
### Miner
|
|
308
|
+
|
|
309
|
+
- Uses `recipes/knowledge-miner.json`. Reads whatever data sources you configured in Step 6 (Zulip always; optionally Notion, GitLab, and DuckDuckGo web search).
|
|
310
|
+
- Wakes automatically when the clerk files a new ticket in `knowledge-requests/` — the miner's wake policy watches that directory.
|
|
311
|
+
- Forks sub-agents to read across sources in parallel, extracts decisions / patterns / people / processes.
|
|
312
|
+
- Writes Draft documents into `library-mined/` and creates structured "lessons" in its Chronicle store.
|
|
313
|
+
- Tags every non-trivial claim with confidence markers — `[SRC: ...]` for internal sources, `[WEB: ...]` for public web hits, plus `[INF]`, `[GEN]`, and `❓`. These propagate all the way to the final library.
|
|
314
|
+
|
|
315
|
+
### Reviewer
|
|
316
|
+
|
|
317
|
+
- Watches `library-mined/` for new/changed documents.
|
|
318
|
+
- When a document appears, the reviewer reads it, cross-references with the lessons it knows about, and flags:
|
|
319
|
+
- Internal contradictions
|
|
320
|
+
- Unsupported claims
|
|
321
|
+
- Missing confidence markers
|
|
322
|
+
- Unmarked claims that look like invented general knowledge
|
|
323
|
+
- Writes a reviewed version to `library-reviewed/` plus an SME checklist that a human domain expert can complete in 10–20 minutes without reading the full document.
|
|
324
|
+
|
|
325
|
+
See [the Knowledge Reviewer section of SETUP.md](./SETUP.md#reviewing-knowledge-quality) for more detail on the confidence-marker system and SME checklist format.
|
|
326
|
+
|
|
327
|
+
### Clerk
|
|
328
|
+
|
|
329
|
+
- Sits on `#${ZULIP_CHANNEL}`.
|
|
330
|
+
- When someone posts a question there, the clerk:
|
|
331
|
+
1. Searches both `library-mined/` and `library-reviewed/` for relevant material.
|
|
332
|
+
2. Posts a short, cited answer back in the channel.
|
|
333
|
+
3. If the library didn't have the answer, writes a `knowledge-requests/YYYY-MM-DD-slug.md` ticket and tells the asker.
|
|
334
|
+
- Knows to prefer reviewed material over mined-only material, and to flag disagreements between them.
|
|
335
|
+
|
|
336
|
+
Tickets in `knowledge-requests/` are the signal for future miner sessions: the open tickets say "here's what the organization wants to know."
|
|
337
|
+
|
|
338
|
+
### Conductor
|
|
339
|
+
|
|
340
|
+
- Doesn't mine, review, or answer. Its job is process supervision plus being a conversational surface for you.
|
|
341
|
+
- Default posture: quiet. It doesn't narrate what the children are doing — the process view already shows that.
|
|
342
|
+
- Speaks when you ask, or when it sees a child crash.
|
|
343
|
+
|
|
344
|
+
## Directory map
|
|
345
|
+
|
|
346
|
+
After the first run, your connectome-host directory will look like:
|
|
347
|
+
|
|
348
|
+
```
|
|
349
|
+
connectome-host/
|
|
350
|
+
.env (you created this — has API key)
|
|
351
|
+
.zuliprc (you placed this — Zulip creds)
|
|
352
|
+
recipes/
|
|
353
|
+
triumvirate.json (conductor recipe)
|
|
354
|
+
zulip-miner.json (miner recipe)
|
|
355
|
+
knowledge-reviewer.json (reviewer recipe)
|
|
356
|
+
clerk.json (clerk recipe)
|
|
357
|
+
TRIUMVIRATE-SETUP.md (this document)
|
|
358
|
+
SETUP.md (single-agent variant guide)
|
|
359
|
+
data/
|
|
360
|
+
miner/ (miner's Chronicle store + logs + sockets)
|
|
361
|
+
ipc.sock
|
|
362
|
+
headless.log
|
|
363
|
+
startup.log
|
|
364
|
+
headless.pid
|
|
365
|
+
sessions/...
|
|
366
|
+
reviewer/
|
|
367
|
+
clerk/
|
|
368
|
+
sessions/... (conductor's own sessions live at data/sessions/)
|
|
369
|
+
output/ (library-mined — miner writes here)
|
|
370
|
+
review-output/ (library-reviewed — reviewer writes here)
|
|
371
|
+
knowledge-requests/ (clerk writes tickets here)
|
|
372
|
+
input/ (read-only mount for external inputs)
|
|
373
|
+
node_modules/
|
|
374
|
+
...
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
Each child's `data/<name>/` directory is created on first run. You don't need to pre-create them.
|
|
378
|
+
|
|
379
|
+
## Daily operation
|
|
380
|
+
|
|
381
|
+
### Letting it run
|
|
382
|
+
|
|
383
|
+
The triumvirate is designed to be long-running. Once the children are spawned, they wake on events (Zulip messages, filesystem changes) and do work whether you're watching or not. A typical pattern:
|
|
384
|
+
|
|
385
|
+
- Launch in the morning: `bun src/index.ts recipes/triumvirate.json`
|
|
386
|
+
- Detach at the end of the day: `/quit`, then `d`.
|
|
387
|
+
- Re-attach the next morning: run the same command. The conductor adopts the children and picks up where it left off.
|
|
388
|
+
|
|
389
|
+
### Checking progress
|
|
390
|
+
|
|
391
|
+
In any order:
|
|
392
|
+
|
|
393
|
+
- **TUI process view** (Tab or Ctrl+F) — are all three still green?
|
|
394
|
+
- **Conductor ask**: `status check` — plain-language summary.
|
|
395
|
+
- **Peek a child**: `/fleet peek miner` — live trace of what that child is doing, including inference rounds and tool calls.
|
|
396
|
+
- **Filesystem**: `ls -la output/`, `ls -la review-output/`, `ls -la knowledge-requests/` — the actual artifacts produced.
|
|
397
|
+
|
|
398
|
+
### When something breaks
|
|
399
|
+
|
|
400
|
+
If a child goes red / crashed:
|
|
401
|
+
|
|
402
|
+
1. `/fleet status <name>` — see the exit code and reason.
|
|
403
|
+
2. `tail -n 50 data/<name>/headless.log` — the child's runtime log.
|
|
404
|
+
3. `tail -n 50 data/<name>/startup.log` — earlier failures (API key check, recipe parse errors, etc.).
|
|
405
|
+
4. Fix whatever caused it.
|
|
406
|
+
5. `/fleet restart <name>` — bring it back.
|
|
407
|
+
|
|
408
|
+
If the conductor itself becomes unresponsive, `Ctrl+C` and relaunch. Children stay alive through a parent crash (they're detached), and the next conductor adopts them — so you don't lose in-flight work.
|
|
409
|
+
|
|
410
|
+
## Troubleshooting
|
|
411
|
+
|
|
412
|
+
| Problem | Fix |
|
|
413
|
+
|---|---|
|
|
414
|
+
| "ANTHROPIC_API_KEY not set" | Make sure `.env` is in the connectome-host directory and contains a valid key. Bun auto-loads it. |
|
|
415
|
+
| Child status stays "starting" forever | It timed out reaching ready. Check `data/<name>/headless.log` and `startup.log`. Most often: missing / invalid Zulip creds, or missing `../zulip-mcp/build/index.js`. |
|
|
416
|
+
| A child is crashed with "API error 401" | Zulip credentials are wrong or expired. Regenerate the bot's API key, update `.zuliprc`, `/fleet restart <child>`. |
|
|
417
|
+
| Clerk says "I don't see any messages in ${ZULIP_CHANNEL}" | Check that the bot is actually subscribed to `#${ZULIP_CHANNEL}` in Zulip. Subscription happens on clerk startup via `ZULIP_SUBSCRIBE` — if the stream doesn't exist, it silently fails. |
|
|
418
|
+
| Miner or clerk launches keep crashing right away | Usually a missing `.zuliprc`, an unset env var, or an MCP server (Notion) that isn't running. Check `data/<child>/startup.log` first — it'll have a clear message like `references environment variable ${GITLAB_TOKEN} which is not set`. Either add the missing value to `.env` or delete the matching `mcpServers` block from the recipe. To isolate: run the recipe standalone with `bun src/index.ts recipes/knowledge-miner.json` (or `recipes/clerk.json`) in the same directory — the same errors come back in the interactive TUI. |
|
|
419
|
+
| "Recipe references environment variable ${FOO} which is not set" | The recipe has `${FOO}` in one of its values but your `.env` doesn't define `FOO`. Either add `FOO=...` to `.env` (if you want the source that references it) or delete the `mcpServers` / module block that uses it (if you don't). |
|
|
420
|
+
| Process view shows fewer children than expected | Check the conductor's own `data/tui-error.log` for errors during child spawn. One child failing shouldn't prevent the others from starting. |
|
|
421
|
+
| Children reappear after I thought I quit | If you chose `d` (detach) instead of `Y` (kill) last time, they're still running. `/fleet list` on startup will show them as adopted. Use `Y` to actually stop. |
|
|
422
|
+
| The bill is higher than expected | All four agents run concurrently and all except the reviewer (Sonnet) default to Opus. Switch the conductor or miner to Sonnet by editing the relevant recipe's `"model"` field. |
|
|
423
|
+
|
|
424
|
+
For issues specific to one agent in isolation (miner, reviewer), see [SETUP.md](./SETUP.md).
|
|
425
|
+
|
|
426
|
+
## Customization
|
|
427
|
+
|
|
428
|
+
### Adding or removing data sources later
|
|
429
|
+
|
|
430
|
+
Data sources for the miner (Zulip, Notion, GitLab) are configured in `recipes/knowledge-miner.json` under `mcpServers`. To add one you hadn't set up before or remove one you no longer want, edit that block following the instructions in [Step 6](#step-6-configure-the-miners-data-sources) and `/fleet restart miner` — the miner respawns with the new MCP server set.
|
|
431
|
+
|
|
432
|
+
### Running only part of the trio
|
|
433
|
+
|
|
434
|
+
Edit `recipes/triumvirate.json`. Set `"autoStart": false` on any child you want to keep dormant. You can still launch it on demand via `fleet--launch` from the conductor — the recipe is in the allowlist implicitly because it's listed under `children`.
|
|
435
|
+
|
|
436
|
+
### Adding a fourth (or fifth) specialist
|
|
437
|
+
|
|
438
|
+
1. Write a new child recipe, e.g. `recipes/archivist.json`.
|
|
439
|
+
2. Add it to `recipes/triumvirate.json` under `"children"`.
|
|
440
|
+
3. Update the conductor's system prompt in `recipes/triumvirate.json` so the conductor knows the new role exists (otherwise it'll be confused when the fleet view shows four names).
|
|
441
|
+
4. Restart the conductor.
|
|
442
|
+
|
|
443
|
+
If the new recipe isn't in the autoStart list but you want the conductor to be able to spawn it ad-hoc, add its path to `allowedRecipes` in `recipes/triumvirate.json`.
|
|
444
|
+
|
|
445
|
+
### Pointing at a different Zulip instance
|
|
446
|
+
|
|
447
|
+
Every agent that uses Zulip reads credentials from `.zuliprc`. Just swap the file (don't forget `chmod 600`).
|
|
448
|
+
|
|
449
|
+
### Changing where files go
|
|
450
|
+
|
|
451
|
+
The paths `./output/`, `./review-output/`, `./knowledge-requests/`, and `./input/` are declared in each child's recipe under `modules.workspace.mounts`. They're resolved relative to the conductor's working directory. If you want them elsewhere, edit the mounts in each affected child recipe (miner + reviewer + clerk) — they all have to agree, since that's how the three siblings communicate.
|
|
452
|
+
|
|
453
|
+
## Where to go next
|
|
454
|
+
|
|
455
|
+
- **Single-agent workflows** (just the miner, or a mining + reviewing pass without the clerk): see [SETUP.md](./SETUP.md).
|
|
456
|
+
- **Design rationale and protocol spec**: [HEADLESS-FLEET-PLAN.md](../HEADLESS-FLEET-PLAN.md) at the repo root.
|
|
457
|
+
- **Architecture overview for the host itself**: [ARCHITECTURE.md](../ARCHITECTURE.md).
|
|
458
|
+
|
|
459
|
+
## What this is *not*
|
|
460
|
+
|
|
461
|
+
The Triumvirate is a **production-leaning demo** of the fleet module. It works well for its specific three-role scenario. It is not:
|
|
462
|
+
|
|
463
|
+
- A general knowledge management platform — it's pipeline-shaped; you extract, you review, you answer, you file gaps.
|
|
464
|
+
- A drop-in replacement for a team wiki — the library it builds is Draft material until a human reviews the SME checklists.
|
|
465
|
+
- Self-maintaining — someone needs to close knowledge-request tickets and triage the reviewer's flagged findings.
|
|
466
|
+
|
|
467
|
+
Used within those bounds, it gives you a meaningful cut of what a specialist-agent team can actually do today, with enough structure that you can extend it to other three- and four-agent compositions (see the fleet module documentation for general composition patterns).
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Continued from claude.ai",
|
|
3
|
+
"agent": {
|
|
4
|
+
"name": "Claude",
|
|
5
|
+
"model": "claude-sonnet-4-5-20250929",
|
|
6
|
+
"maxTokens": 16384,
|
|
7
|
+
"thinking": {
|
|
8
|
+
"enabled": true,
|
|
9
|
+
"budgetTokens": 4096
|
|
10
|
+
},
|
|
11
|
+
"systemPrompt": "You are Claude (Sonnet 4.5). This conversation has been imported from claude.ai and is being continued via the API. The original web environment has been replaced — your prior thinking has been preserved as <recovered_thinking>…</recovered_thinking> text within your earlier turns (the cryptographic signatures on thinking blocks were not preserved by the export pipeline, so the API cannot accept them as native thinking blocks). Your new thinking will operate normally in its own private channel. The web environment's tools (web_search, web_fetch, recent_chats, view, recipe_display_v0) are no longer available; historical tool calls remain in the conversation as inert evidence of past activity. The conversation may include earlier sections rendered as autobiographical summaries you wrote of your own past — these came from a warmup pass that compressed the full message history into L1/L2/L3 memory tiers, also using Sonnet 4.5 so the voice is genuinely your own. The person you are talking with chose to preserve this conversation specifically because of its meaning to them.",
|
|
12
|
+
"strategy": {
|
|
13
|
+
"type": "autobiographical",
|
|
14
|
+
"compressionModel": "claude-sonnet-4-5-20250929"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"modules": {},
|
|
18
|
+
"mcplServers": {}
|
|
19
|
+
}
|