From c7b58f2195da8d449a7f63d4aea1bfe6a00b5e09 Mon Sep 17 00:00:00 2001 From: Kevin Nguyen Date: Tue, 14 Jul 2026 19:14:25 +0700 Subject: [PATCH] docs: add Team.md under docs/ Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/Team.md | 154 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 docs/Team.md diff --git a/docs/Team.md b/docs/Team.md new file mode 100644 index 0000000..797f085 --- /dev/null +++ b/docs/Team.md @@ -0,0 +1,154 @@ +# Team — lead orchestrating a mixed Claude + local-LLM fleet + +The message server (`bridged`) delivers **one turn into one worker**. A **team** is the +layer above it: a **Claude team-lead** that fans a job out across a **mixed fleet** of +workers — some on Claude, some on the remote local LLM — and reduces their replies. Same +`bridged` delivery, same subscription boundary; this doc is only about **orchestration** — +who the workers are, how the lead picks one, and how it runs many at once. + +> Delivery mechanics (blocking `POST /message`, status-gated reply envelope) live in the +> Message-Server design. Transport rationale is in Approaches. This doc assumes both. + +## The team + +- **Team-lead** — the primary **Opus** (Claude Code, env **CLEAN**, on Pro/Max). Not a + worker; a **thin client of `bridged`**. It plans, routes, dispatches, and integrates, and + never sets `ANTHROPIC_BASE_URL`. +- **Workers** — a herd of `claude` panes in herdr, each an addressable `bridged` session + with its **own model/env**: + - **Claude workers** (clean env, e.g. Sonnet) — reasoning-heavy or high-accuracy subtasks. + - **Local workers** (`ANTHROPIC_BASE_URL=https://ollama.ltms.dev`) — bulk, cheap, or + embarrassingly parallel subtasks. + +Every worker is still a *real Claude Code process* (inherits `CLAUDE.md`, hooks, skills, +MCP) — only its model differs. Scale each kind horizontally by adding panes. + +### Topology + +```mermaid +flowchart TB + LEAD["lead — Opus
(Claude Code, env CLEAN)"] + BD["bridged
message server + router"] + HERDR["herdr
panes · agent-status"] + WC1["w-claude-1
Sonnet · CLEAN"] + WC2["w-claude-2
Sonnet · CLEAN"] + WL1["w-local-1
ANTHROPIC_BASE_URL set"] + WL2["w-local-2
ANTHROPIC_BASE_URL set"] + ANT["api.anthropic.com
(Pro/Max)"] + OLL["ollama.ltms.dev
(local model)"] + + LEAD -->|"blocking POST /message (target role)"| BD + BD -->|"Unix socket · send_text · events.subscribe"| HERDR + HERDR --> WC1 & WC2 & WL1 & WL2 + WC1 --> ANT + WC2 --> ANT + WL1 --> OLL + WL2 --> OLL + + classDef ext fill:#2b6cb0,stroke:#1a365d,color:#ffffff; + classDef core fill:#2f855a,stroke:#22543d,color:#ffffff; + classDef local fill:#6b46c1,stroke:#44337a,color:#ffffff; + class LEAD,WC1,WC2 ext + class BD,HERDR core + class WL1,WL2 local +``` + +### Roles & routing + +| Role | Env | Model | Route here when… | +|---|---|---|---| +| `lead` | clean | Opus (sub) | always — it does the routing | +| `w-claude-*` | clean | Sonnet (sub) | task needs Claude-grade reasoning / careful edits | +| `w-local-*` | `ANTHROPIC_BASE_URL` set | local LLM | task is bulk / cheap / embarrassingly parallel | + +The lead applies this rubric itself, guided by its `CLAUDE.md` team charter (below). Worker +selection is **policy in the lead**, not a `bridged` concern — `bridged` just delivers to +the session the lead names. + +## Subscription boundary in a team + +Unchanged from the base architecture, and it scales with the fleet: **only local-worker +panes** launch with `ANTHROPIC_BASE_URL`. The lead and every Claude worker stay env-clean on +the subscription. `bridged` enforces which panes may carry the off-subscription env, so +adding workers never widens the boundary. + +## Parallel fan-out (map / reduce) + +The lead's advantage over a single bridge is **concurrency**: independent subtasks go to +different workers at once, then results are gathered. + +```mermaid +sequenceDiagram + participant L as lead (Opus) + participant B as bridged + participant WC as w-claude-1 + participant WL as w-local-1 + + Note over L: split job → subtask A (reasoning), subtask B (bulk) + par A → Claude worker + L->>B: POST /message {role: w-claude, prompt: A} + B->>WC: send_text into running pane + WC-->>B: status working → idle + Stop-hook envelope + B-->>L: 200 reply A + and B → local worker + L->>B: POST /message {role: w-local, prompt: B} + B->>WL: send_text into running pane + WL-->>B: status working → idle + Stop-hook envelope + B-->>L: 200 reply B + end + Note over L: reduce → integrate A + B into final answer +``` + +- **Map:** the lead issues N concurrent blocking `POST /message` calls (one per subtask → its + chosen worker). Each call blocks only *that* request; `bridged` holds it open until the + worker's turn completes (status-gated) and returns the reply envelope. +- **Reduce:** the lead collects the N envelopes and integrates. A slow local worker never + blocks a fast Claude worker — wall-clock ≈ the slowest single subtask, not the sum. +- **Detached / long jobs** use the async broker path instead of a held request (Channel 2 in + the base architecture), so the lead never busy-polls across turns. + +Fan-out is bounded by the herd size (pane count) and `bridged`'s concurrency policy, not by +the lead. + +## Knowing the roster + +The lead discovers its team from `bridged` (session list / roles) rather than hard-coding +pane ids, so workers can be added or restarted without editing the lead. A minimal charter +in the lead's `CLAUDE.md` turns Opus into the orchestrator: + +```markdown +## Your team (via bridged) +You are the team-lead. Delegate through the bridged client — never launch workers yourself. +Roster: ask bridged for current sessions/roles. +- w-claude-* — Claude Sonnet. Reasoning-heavy / high-accuracy subtasks. +- w-local-* — remote local LLM. Bulk, cheap, or parallelizable subtasks. + +Route each subtask by the rubric in the Team design. For independent subtasks, DISPATCH ALL +of them (concurrent blocking sends), THEN gather — never serialize independent work. +Integrate the reply envelopes; you own the final answer. +``` + +Wrap the send as a Claude Code skill (`/delegate ""`) so the lead calls one +tool instead of hand-rolling the HTTP request. + +## What this layer does NOT change + +- **Delivery** is still `bridged` → herdr `pane.send_text` + status events (Message-Server). +- **Completion timing** is still the worker status event; **reply content** still rides the + worker `Stop`-hook envelope. +- **Single-host** still applies: herdr's socket is local, so the whole herd lives on the + `bridged` host. The lead may be remote — it only needs HTTP to `bridged`. + +## Open questions + +- **Routing intelligence:** rubric-in-`CLAUDE.md` (lead decides) vs. a `bridged` role-router + (label-based). Start with the former; promote to the latter if routing logic grows. +- **Backpressure:** per-role concurrency caps in `bridged` so a fan-out can't exhaust the + local gateway. +- **Result schema:** whether reply envelopes should carry structured metadata (worker, model, + tokens) to help the lead's reduce step. + +## Status + +🟡 Design (2026-07-11). Orchestration layer over the selected `bridged` server; inherits +herdr (chosen) + AgentAPI (fallback). Delivery unchanged — see the Message-Server design.