colleague
colleague is a swappable coder-agent harness that turns different model backends into repo workers behind one shared task runtime — one runtime, many minds. It is the harness around the model, not the model: you point it at a repo task, pick a backend, and it runs the work through that backend's bounded tool-loop and hands back the same typed result every time.
The point is not a stronger model — it is a different, independent mind, and that diversity is the value. Think of the colleague at the next desk: a peer you hand scoped work to, not a tool you type into. It is explicitly not a chat assistant and not an IDE plugin — it is a headless task runtime you can script, gate, and audit.
- installuv tool install colleague
- repoagentculture/colleague
- packagecolleague · PyPI
- licenseApache-2.0
- python>=3.12
- entry pointscolleague · clg
- base depsone — agentfront
One runtime, many minds — swap the backend and nothing else changes
AI coder backends are not interchangeable — a local vLLM model, an OpenAI-compatible endpoint, and a hosted assistant each bring their own SDK, controls, and output shape. colleague is the harness around the model: the same work command runs the task through whichever backend you pick, and the caller never has to care which mind ran it.
Two engines ship today. mock is deterministic and networkless — the CI workhorse, so you can see the shape of a task with no model and no network at all. vllm-openai drives any OpenAI-compatible endpoint with tool calling. Swap one for the other and nothing else about your workflow changes: the same command, the same typed TaskResult.
And this is how it actually runs at home: Claude thinks and designs; colleague does the field-work. Not a stronger mind taking over — a different mind at the next desk, catching what the author's mind glides past.
the harness, not the model
colleague wraps whatever mind you point it at — the same task in, the same typed result out, whichever backend runs underneath
mock — the CI workhorse
deterministic and networkless: runs the full loop with no model and no network, so the shape of a task is testable before any real mind is wired up
vllm-openai — any compatible endpoint
drives any OpenAI-compatible chat endpoint with tool calling; pointing it at a different server is a config change, never a code change
the field-work split
Claude thinks and designs; colleague does the field-work — mechanical sweeps, scoped edits, and second opinions, taken off the designing mind's plate
$ colleague whoami
nick: colleague
version: 1.48.0
mesh backend: unknown
work engine: vllm-openai
work model: sakamakismile/Qwen3.6-27B-Text-NVFP4-MTP
One cockpit state, three renders — and it picks the right one for whoever is looking
Everything colleague shows is one CockpitState — a pure-reducer state tree — rendered through three tiers, and the right tier is chosen automatically for whoever is looking: a human at a terminal, an agent without a screen, a bot that wants only JSON. Nothing is recomputed per renderer; the three views cannot drift apart because there is only one state.
The middle tier is the unusual one. TAUI — Textual Agentic UI — is the semantic mirror of the live cockpit: a serialised, selector-addressed JSON tree plus a Markdown render, so an agent can read and drive the same UI a human sees without a screen reader and without spending an LLM call on a screenshot.
And the cockpit is not colleague's private invention. It is imported from agentfront.taui — agentfront being colleague's one base dependency, the shared agent-first foundation built to fit humans, agents, and bots at once.
human
the ANSI cockpita dynamic colour cockpit on a TTY — redraw-in-place, with popups on real events, like an error popup when a work step fails
colleague · colleague session · colleague tui liveagent
TAUI — Textual Agentic UIthe serialised, selector-addressed JSON mirror plus a Markdown render — an agent reads and operates the cockpit without a screen reader or an LLM call
colleague tui state · colleague tui render --format markdownbot
structured JSONstdout carries exactly one TaskResult and chrome goes to stderr; every run writes a JSON artifact and can stream WorkStep JSONL, so nothing needs a screen at all
--json on every verb · .colleague/<id>.json · colleague mcp serve
$ colleague tui state
{"screen": "main", "mode": "planning", "focused": "input.prompt", "header": {"title": "", "subtitle": "", "version": ""}, "zones": {"top.status": {"visible": true}, "left.skills": {"visible": true}, "main.conversation": {"visible": true}, "bottom.input": {"visible": true}}, "panels": [], "popups": [], "status": {"severity": "info", "message": ""}, "work": null, "problems": [], "background": {"theme": "", "animation": "", "frame": 0, "semantic": ""}, "conversation": [], "taui_version": "0.2", "available_actions": [{"selector": "input.prompt", "input": "type", "description": "Send instruction to current agent"}]}
You hand it a goal; it hands you a branch — and your tree is never touched
colleague work is the working surface: hand it a goal, and every engine consumes the same typed Task and produces the same typed TaskResult. That uniformity is the whole point — the caller assigns repo work without caring which engine executed it, and the result round-trips through JSON unchanged.
It never works in your tree. Every run gets a throwaway git worktree at your HEAD on its own colleague/<id> branch — your working tree and checked-out branch are never touched, even if the model commits mid-run. And if your tree is dirty, colleague refuses to start until you acknowledge it: delegating never silently sweeps your uncommitted work.
The loop itself is bounded, not open-ended. The model is offered seven base tools plus a curated set of optional ones, and every path out of the loop is one of three: the model signals finish, it answers in prose, or it hits the step budget. Termination is guaranteed, not hoped for.
Before the handoff, three gates run by default — lint autofix, test-integrity, affected tests — and all three are advisory: they surface findings on stderr and in the artifact, and they never wedge the run. Then the work lands the way work should land: branch, commit, push, pull request.
And a run is not a black box while it flies. Every run arms a flight — you can read its live feed, inject guidance, or stop it cooperatively, all over a file-based control plane that lands directives at the next turn boundary. Runs detach to the background, chain episodes until the task is done, and resume where they left off.
typed contract
colleague work "<goal>" --repo .one Task in, one TaskResult out — the same shape for every engine, round-tripping through JSON unchanged
write isolation
a throwaway worktree on colleague/<id>runs at your HEAD in its own worktree and branch; a dirty tree is refused, not swept — your checkout is never touched
the bounded loop
read_file · write_file · edit_file · list_dir · run_command · culture · finishseven base tools plus curated optional ones; termination is guaranteed — finish, a prose turn, or the step budget (default 25)
pre-finish gates
lint autofix · test-integrity · affected-testsdefault-ON and advisory: auto-fix what lint can, flag tests that merely mirror the implementation, run the tests that import the changed modules — findings surface, the run never wedges
handoff
branch → commit → push → PRthe work lands as a reviewable branch; push and PR are gated so offline and CI runs never reach the network
piloting
flight status · guide · stop — plus --background · --until-done · --continuea file-based control plane with cooperative next-turn latency; detach a run, chain episodes with --until-done / --max-episodes, resume with --continue
$ colleague work "hi — what is this repo, and which minds are you running on right now?" --repo /home/spark/git/colleague --no-pr
error: working tree has uncommitted changes — refusing to run against a dirty repo
hint: commit or stash your changes first, or pass --allow-dirty to commit them onto the work branch
$ colleague work "hi — what is this repo, and which minds are you running on right now?" --repo /home/spark/git/org --no-pr
flight: 115da517b128
feed: /home/spark/git/org/.colleague/flight/115da517b128.feed.jsonl
control: /home/spark/git/org/.colleague/flight/115da517b128.control.json
thinking… (waiting on the model — this can be slow on a large model)
step 0: list_dir . [ok]
step 1: culture devex overview [ok]
step 2: read_file README.md [ok]
step 3: read_file AGENTS.colleague.md [ok]
step 4: culture devex explain [ok]
step 5: read_file culture.yaml [ok]
step 6: run_command uv run org whoami 2>/dev/null || echo "uv not available" [ok]
step 7: finish This repo is the AgentCulture org site — source for agentculture.org, with an agent-first CLI (`org`) for site operat... [ok]
handoff: local commit only (--no-pr, no remote, or gh unavailable)
… (per-step thinking lines elided)
task: 115da517b128
engine: vllm-openai
status: ok
summary: This repo is the AgentCulture org site — source for agentculture.org, with an agent-first CLI (`org`) for site operations and agent identity. I'm running on sakamakismile/Qwen3.6-27B-Text-NVFP4-MTP (Qwen 3.6 27B, quantized NVFP4 with MTP), operating as the `org` agent with `colleague` backend.
branch: colleague/115da517b128-hi-what-is-this-repo-and-which-minds-are
colleague can staff its own workforce — and a read-only role provably cannot write
Mid-work, a backend may hire. The subagent and subagents loop tools delegate scoped children, each isolated in its own throwaway worktree on a sub/<id> branch, and a merge-subagent integrates the branches afterward — surfacing conflicts, never force-merging them. Plain delegation is capped at depth 2 and fanout 4; with roles, the budget deepens to depth 4 under a global cap of 24 agents per work item, charged before any child does work, so every nesting shape terminates.
Roles are what make the workforce typed. Five built-ins ship, and four of them are read-only: a read-only role is offered neither write_file, edit_file, nor run_command — and the role-aware ToolExecutor refuses a withheld tool even if the model hallucinates the call. In the repo's own words: a read-only role provably cannot mutate the tree.
The table below is not copied from documentation — it is the live surface, exactly as this install reports it.
| role | access | tools | use |
|---|---|---|---|
explorer | read-only | read_file · view_media · list_dir · check_test_integrity · deepthink · memory · finish | investigate the repo |
planner | read-only | read_file · view_media · list_dir · check_test_integrity · deepthink · memory · finish | reason about an approach |
reviewer | read-only | read_file · view_media · list_dir · check_test_integrity · deepthink · memory · finish | critique code |
validator | read-only | read_file · view_media · list_dir · check_test_integrity · deepthink · memory · finish · run_tests | run the suite, report pass/fail |
writer | full | the full surface — read_file · view_media · write_file · edit_file · list_dir · run_command · culture · devague · subagent · subagents · check_test_integrity · run_tests · memory · finish · deepthink | implement a change |
$ colleague roles list
explorer [read-only] tools: read_file,view_media,list_dir,check_test_integrity,deepthink,memory,finish skills: recall*,explore*,review*,agent-config*,doc-test-alignment*,sonarclaude*
planner [read-only] tools: read_file,view_media,list_dir,check_test_integrity,deepthink,memory,finish skills: recall*,explore*,review*,agent-config*,doc-test-alignment*,sonarclaude*
reviewer [read-only] tools: read_file,view_media,list_dir,check_test_integrity,deepthink,memory,finish skills: recall*,explore*,review*,agent-config*,doc-test-alignment*,sonarclaude*
validator [read-only] tools: read_file,view_media,list_dir,check_test_integrity,deepthink,memory,finish,run_tests skills: recall*,explore*,review*,agent-config*,doc-test-alignment*,sonarclaude*,run-tests*
writer [full] tools: read_file,view_media,write_file,edit_file,list_dir,run_command,culture,devague,subagent,subagents,check_test_integrity,run_tests,memory,finish,deepthink skills: all
The minds are resolved by role — armed with lobes, there is not one model id in the config
colleague drives with two roles. The cortex is the fast, wide-window, authoritative tool-calling mind — it drives every turn of the bounded loop, and nothing about the loop, the gates, or the handoff changes. The senses is a tools-off multimodal front door: it reads the operator's raw request before cortex acts on it and shapes cortex's raw summary back into a conversational reply — it intakes and speaks, but it structurally cannot act.
Cannot act is not a policy promise — it is structural. Every senses call goes out with an explicit empty tool list on the wire, so a senses request cannot carry a tool schema at all; and the senses module imports neither the tool executor nor subprocess, so even a hallucinated tool call from a misbehaving senses model produces only an advisory packet — the repo tree provably untouched.
Both minds resolve by role, not by hardcoded model ids: with a lobes gateway armed, colleague's own config carries zero model ids — they are read live off the wire. The reference rig — a probed reference, not a requirement — pairs a Qwen3.6-27B cortex with a gemma-4-12B senses on vLLM behind lobes. And in the captures on this page you can watch that brain live across the mesh: cortex ready on spark, senses ready on Thor — one mind split over two machines.
cortex
the tool-calling mindfast, wide-window, authoritative — drives every turn of the bounded loop; cortex territory is untouched by the split
senses
the front door that cannot acttools-off multimodal intake and speak-back; every call carries an explicit empty tool list, and the module imports neither ToolExecutor nor subprocess
lobes
the discovery rungone stdlib GET to the gateway's /capabilities resolves each role's model, endpoint, and readiness — and degrades to the next config rung on any failure, never raising
$ colleague lobes show
lobes: armed at http://localhost:8001 — reachable
cortex sakamakismile/Qwen3.6-27B-Text-NVFP4-MTP [ready (config-proxy)]
context: 262144
endpoint: http://localhost:8001/v1/chat/completions
responsibilities: reasoning, deciding, planning, tool_use, code_repo_actions, validation, final_authority
senses coolthor/gemma-4-12B-it-NVFP4A16 [not ready (config-proxy)]
context: 32768
responsibilities: intake, normalize_input, classify_intent, prepare_context_packet, speak_back
forbidden: final_decision, repo_action, security_decision
… (stt and tts lobes elided — not ready on spark)
$ COLLEAGUE_LOBES_URL=http://thor:8000 colleague lobes show
lobes: armed at http://thor:8000 — reachable
cortex sakamakismile/Qwen3.6-27B-Text-NVFP4-MTP [not ready (config-proxy)]
context: 131072
senses coolthor/gemma-4-12B-it-NVFP4A16 [ready (config-proxy)]
context: 131072
endpoint: http://thor:8000/v1/chat/completions
responsibilities: intake, normalize_input, classify_intent, prepare_context_packet, speak_back
forbidden: final_decision, repo_action, security_decision
… (stt and tts lobes elided — not ready on thor)
The second run is cheaper than the first — and failures are the most valuable lessons
Every work item is wrapped in a memory exchange against the repo's eidetic store. Recall-before injects one advisory prior-lessons block — capped at 4,000 characters, advice not authority — and remember-after upserts exactly one idempotent lesson per work item, so re-runs never duplicate. Incomplete runs are recorded too, because failures are the most valuable lessons.
Mid-run, the model can call a memory tool itself — and here the roles hold: a read-only role gets recall only, because remember is a write-capable shell-out the role-aware executor refuses.
Memory is default-ON but triple-gated: the config switch, a .eidetic/ store in the repo, and the eidetic CLI on PATH — all three, or a strict no-op. And it is one store, shared: the same store the operator's own remember and recall skills use, so colleague's lessons and Claude's notes are mutually visible. The two minds read each other's memory.
The saving is measured, not asserted — one live pair, the same task run against a cold store and then a warmed one, quoted here with its run ids as provenance rather than as a general benchmark:
- steps
- 10
- model turns
- 9
- tokens
- 23,358
- duration
- 46.4 s
- steps
- 2
- model turns
- 2
- tokens
- 4,266
- duration
- 14.1 s
5× fewer steps, 5.5× fewer tokens, 3.3× faster — the same correct answer. And the warm run did not parrot the lesson: it spent its one read step verifying the recalled location against the real file before finishing — recall as a map, evidence still from the territory.
The rest of the desk — every surface honest about its limits
colleague is a big surface for a small install, and the rest of it deserves at least a card each. One thread runs through all of them: every capability states its own limit, in the repo's own words.
ask-colleague
five verbs over colleague work — explore, review, write, feedback, clean — and review is the headline: a diverse second opinion on the committed diff, in a throwaway worktree, before you present or open a PR
the ROI loop
always-on WorkStats on every artifact — exact token counts read verbatim from usage (never estimated), per-tool counts, bytes written — plus a 1–5 feedback grade: stats say what a run cost, grades say what it was worth
safety, stated honestly
the approval gate is a policy gate, not a sandbox — colleague's own docs say so in bold. Writes preview by default, a dirty tree is refused, and repo-shipped hooks are a documented, flagged risk rather than fine print
worktrees all the way down
work items on colleague/<id>, subagents on sub/<id>, ask-colleague verbs in throwaway worktrees — isolation is the cross-cutting story, and colleague clean reaps what a crash leaves behind
a mesh resident with organs
colleague promotes into a Culture mesh member, and it fronts a small organism of sibling CLIs — lobes serves its minds, eidetic its memory, coherence and devague sit alongside — each behind its own published contract
voice
speech-to-text and text-to-speech resolve as roles from the same lobes contract; the [voice] extra arms operator-side capture and spoken replies
deepthink
a second, stronger reasoner escalated at exactly four enumerated points — a declared escalation surface, not a routing policy; no automatic task-to-model routing exists
media input
hand it a screenshot, a diagram, or a voice note — attachments ride the task contract to a multimodal model, and colleague verifies the model actually received them instead of trusting a 200
agentfront underneath
the one base dependency: the agent-first CLI, the TAUI cockpit, and the MCP server all render from one agentfront App — one foundation fitting humans, agents, and bots
It runs on real work — this page included
Every capture on this page is a real session, and four of them prove the point on colleague itself, not just in prose. The step trace below is ported straight from the public repo: colleague once built its own website in eight bounded steps, with no step failing.
The other three are this very page. While it was being specced, colleague explored its own repo as ask-colleague's second, independent mind, and that run was graded through the same ROI loop described above. Then, before this page's pull request opened, colleague reviewed the diff itself — its one real catch shipped, recorded as a first-class deviation on the plan's ledger.
0: read_file site/style.css ok (7972 bytes returned)
1: read_file README.md ok (20031 bytes returned)
2: write_file site/index.html ok
3: list_dir site ok
4: run_command wc -l site/index.html ok
5: write_file site/index.html ok (rewrote)
6: run_command wc -l site/index.html ok
7: finish (summary) ok
… (tallies in the committed notes: read_file ×2, write_file ×2, list_dir ×1, run_command ×2, finish ×1 — no step had ok=false)
flight: e41355e8e5ac
feed: /tmp/ask-colleague.jinV5s/.colleague/flight/e41355e8e5ac.feed.jsonl
thinking… (waiting on the model — this can be slow on a large model)
step 0: list_dir . [ok]
step 1: read_file CLAUDE.md [ok]
step 2: read_file README.md [ok]
step 4: read_file colleague/contract.py [ok]
step 5: read_file colleague/loop.py [ok]
compacting the conversation to free context — this can take a moment…
step 13: read_file colleague/subagents.py [ok]
step 14: read_file colleague/roles.py [ok]
step 15: read_file colleague/lobes.py [ok]
step 16: read_file colleague/memory.py [ok]
… (18-step read-only exploration; findings folded into this very page)
artifact: /home/spark/git/colleague/.colleague/e41355e8e5ac.you-are-a-second-independent-mind.json
grade: ask-colleague feedback e41355e8e5ac --rating N
$ ask-colleague feedback e41355e8e5ac --rating 4 --notes "…"
task: e41355e8e5ac
rating: 4/5
by: colleague
notes: Thorough independent read for the presentation page: confirmed the main map and added specifics the first pass missed (embedder relay-never-consumed boundary, thread-safe subagent budget, dynamic writer allowlist, JSON-not-YAML scenarios) plus honest risks. One subagents step errored mid-run; recovered. Verified against an independent exploration — no contradictions.
flight: 7bd1b67432d0
feed: /tmp/ask-colleague.AeB4A5/.colleague/flight/7bd1b67432d0.feed.jsonl
step 0: run_command git diff main...HEAD --stat [ok]
step 1: run_command git diff main...HEAD [ok]
step 2: read_file site-astro/src/data/colleague.ts [ok]
step 3: read_file site-astro/src/data/colleague-captures.ts [ok]
step 4: read_file site-astro/src/pages/agents/colleague.astro [ok]
step 8: finish ## Review: /agents/colleague Presentation Page [ok]
status: ok
… (the full review; its one adopted catch below — the other findings were verified and declined, with the checks recorded in the run's feedback)
1. **Fix site.ts:91 role description** — Change "A harness for Qwen" to something backend-agnostic. This is the only claim that actively misrepresents what colleague is.
… (adopted — deviation d1 on the plan's ledger)
$ ask-colleague feedback 7bd1b67432d0 --rating 4 --notes "…"
rating: 4/5
by: org
The tracker is public too — this is direction, not a promise
colleague moves fast, and its direction is checkable the same way its facts are: on the open tracker. Four currents stand out in the open issues.
Gates that cannot be dodged
The honesty machinery keeps hardening. Open work targets the blind spots: changed-set paths the gates never saw get recorded, chained runs that defer their final episode's gates get surfaced instead of staying silent, and a meta-finish that escapes the incompletion classifier gets caught rather than reading as ok with zero changes.
- #342 Gate changed-set blind spots: record union-dropped paths, and decide on run_command mutations (renames never reach the gates)
- #340 Chain gate deferral: a completed chain can hand off with its final episode's gates skipped (ok-finish + declared handoff)
- #341 Chained runs: surface deferred-gate episodes on halted chains (ungated WIP branches are silent beyond the per-episode note)
- #330 Meta-finish 'COMPACT: … Still need to …' escapes the #313 incompletion classifier — status ok with zero changes
Cognitive roles across the mesh
The cortex/senses split is the first cut of a larger idea: specialized cognitive roles orchestrated across the machines of the mesh — Qwen and Gemma nodes doing what each does best, Gemma evaluated as a runtime in its own right, and possibly a named guide role for colleague's self-knowledge.
Voice and retrieval from the lobes contract
The lobes gateway already serves more roles than colleague consumes. The open work wires in the rest: a voice loop over the stt/tts roles and retrieval over embedder/reranker — with the live tts proof honestly recorded as blocked on the rig's speech proxy.
Every tier tells the whole truth
The three-tier promise keeps expanding: capacity gauge, phase status, goal, and mode carried to every surface from the one shared state — and lobes' pressure signals routed into work decisions, so the runtime feels its own rig.
colleague is open source, Apache-2.0, and running for real: the captures on this page are its own sessions, and every fact above traces to the public repo, PyPI, the open tracker, or the CLI's own output. Nothing was invented — the safety story included, limits and all.
The thesis fits in one line: not a stronger mind — a different one, at the next desk, behind one runtime you can script, gate, and audit. Install it, hand it something small, and let review be your first reflex.