Member-based delegation across rival agent CLIs

Delegate a task to a named team member and let a per-project config decide which agent CLI runs it — Codex, Grok, or Claude.
A member is more than a vendor pick. It carries a charter, a deliverable kind, and a place in a reporting tree. A member with reports can answer with delegations instead of a deliverable; the dispatcher runs those against its direct reports only, then calls the member back with the results so it can synthesise. Tree depth and total adapter runs are capped separately. A manager delegates by answering with nothing but a JSON object; the exact rule is under Delegation.
A member can also stand for another project's team. An orchestrator for a product can delegate to the iOS and Android repos' own teams, and each runs under its own repo's config and denylist. See Other teams.
A rival CLI ships whatever it can read to a third party, so every member runs in a filtered clone: a shallow clone with the denied paths deleted and history flattened to one orphan commit, so a secret is not recoverable from HEAD~1 either. A config with an empty denylist is refused rather than defaulted.
/agent-team-init and /delegate.claude, codex, or grok.agent-team is a Claude Code plugin served from its own marketplace in this repository:
/plugin marketplace add bmcreations/agent-team
/plugin install agent-team@agent-team
The plugin runs from Claude Code's plugin cache, not from a checkout. There is no npm package and no agent-team command on PATH.
In the project you want a team for:
/agent-team-init. It searches the repository for credential-shaped paths, probes which vendor CLIs are installed, and writes .claude/agent-team.json with an orchestrator and three reports.deny_paths it wrote. Anything missing from that list can be sent to a third party./delegate <member> <task>, for example /delegate explorer where is the retry policy configured?./delegate reports the member's summary, which agent ran it, and any fallback warning. For a workspace member the change comes back as a diff in artifacts.diff; nothing is written to your checkout.
To see how the last delegation went, run /delegation (or /delegation --all for per-member totals across runs):
2026-10-07T12:00:00.000Z Implement Slice 2 (Edit Profile)
member model status elapsed turns cost advisor
orchestrator claude-opus-5-5 ok 15m00s 18 $1.84 2
├ worker claude-sonnet-5-5 ok 6m40s 37 $1.12 0
└ reviewer claude-opus-5-5 ok 2m55s 21 $0.97 2
total 15m00s $3.93 advisor calls 4
/delegation prints straight into the transcript without a model turn. /agent-team:report prints the same table through a skill, for surfaces that do not load plugin hooks modules.
To see the reporting tree for a config:
node ~/.claude/plugins/cache/agent-team/agent-team/<version>/bin/agent-team.js org
defaults, and deny_paths rules./delegation.worktree isolation to workspace.The runtime ships four adapters: claude, codex, grok, and mock. Each is checked against a conformance suite, but the suite accepts a graceful failure as conformant, so passing it proves the adapter honours the contract rather than that it works end to end. Codex has been exercised against a run that reached the model; grok has not, so its success-response parser is still unverified against a real payload.
Two things to know about grok before routing a member to it. Its --sandbox read-only profile is what backs isolation: read-only, and it refuses to start when it cannot resolve a deny path — which includes /var/run/docker.sock as Docker Desktop installs it, as a symlink. That is a failure closed, not open: the member's run fails rather than proceeding unprotected. And its prompt must be passed with -p; a bare positional argument opens the interactive interface instead and dies outside a terminal with an error naming neither cause.
The codex and grok adapters resolve their CLI from PATH, with AGENT_TEAM_CODEX_BIN and AGENT_TEAM_GROK_BIN as overrides. That override is not decoration — neither Codex nor Grok necessarily installs onto a login shell's PATH, and Codex may expose its binary only from inside the app bundle. The claude adapter has no override and always runs claude from PATH.
npm test
The suite uses node --test and needs git. It runs the vendor adapters against fake binaries; set AGENT_TEAM_CONFORMANCE=codex,grok to also require a successful run against the real CLIs.
hooks/register.ts 32 lines1import type { Register } from 'claude-code'
2
3// /delegation prints the delegation report straight into the transcript, the way /context
4// does, with no model turn. It runs the same `agent-team report` the /agent-team:report
5// skill runs, so the table is formatted in one place.
6export const register: Register = on => {
7 on('session.start', async ($, e, next) => {
8 await $.command.register({
9 name: 'delegation',
10 description: 'Show the last agent-team delegation as a tree (--all for per-member totals)',
11 })
12 return next(e)
13 })
14
15 on('command.run', { command: 'delegation' }, async ($, e) => {
16 const args = e.args.split(/\s+/).filter(a => a === '--all' || a === '--json')
17 const project = await $.session.root()
18 // $.process.run rejects when node cannot start (say it is not on the app's PATH). Left
19 // uncaught, the hook would fail and the command would print nothing.
20 try {
21 const { exitCode, stdout, stderr } = await $.process.run(
22 ['node', `${$.plugin.root}/bin/agent-team.js`, 'report', '--project', project, ...args],
23 { timeoutMs: 15_000 },
24 )
25 if (exitCode !== 0) return { text: `agent-team report failed: ${(stderr || stdout).trim()}` }
26 return { text: stdout.trimEnd() }
27 } catch (err) {
28 return { text: `agent-team report could not run: ${(err as Error).message}. Try /agent-team:report.` }
29 }
30 })
31}
32