Skip to content

Crews Reference

Authoritative reference for the agents-fleet crew system (v2): file format, bundled crews, authoring custom crews, activator lifecycle, per-command workflow overrides, topology, and the role+skills composition contract. Source of truth: src/skills/types.ts at HEAD (v0.36.3). For skills + role+skills composition mechanics, see docs/composition.md.

What a crew is

A crew is a named bundle of agents — each declared as a role (persona) plus zero or more atomic skills (composable knowledge packs) — together with a coordinator role, a default workflow, a topology that governs inter-worker messaging, and an optional MCP allowlist. Crews live as *.crew.md files at one of three tiers: bundled, user, or project.

Activating a crew (/crew activate <name>) is the single mechanism by which an operator swaps the orchestration context of a session: the coordinator's system prompt is rewritten to embed <active-crew> and <active-workflow> XML blocks describing the new roster, spawn_worker calls match against crew members instead of defaults, MCP servers declared by the crew are toggled on for the coordinator session, and slash commands that consult the crew's optional workflows: map (/feature, /code-review, /init, /research) switch to the workflow the crew prescribes for that command.

Exactly one crew is active per session at a time; deactivation reverts the coordinator to its bundled default role and clears the crew-injected MCP servers. The active crew name is persisted in the session JSON and re-applied on --resume.


Crew file format (v2)

Frontmatter schema (YAML)

Authoritative shape: CrewV2 in src/skills/types.ts:157-178.

FieldTypeRequiredDescription
namestringUnique crew name. Used for /crew activate <name> and on-disk filename.
descriptionstringHuman-readable summary (one line). Falls back to the first body heading if omitted (parser.ts:762).
topology'hub' | 'mesh' | 'silent'Inter-worker messaging discipline. Defaults to 'hub' if missing (parser.ts:763).
workflowstring✅ (logically)Workflow name to inject as <active-workflow>. Defaults to 'freeform' when omitted (parser.ts:764, types.ts:160-161).
workflowsRecord<string, string>Per-command override map (T-148). Keys are slash-command names matching /^[a-z][a-z0-9-]*$/; values are workflow names. See Per-command workflow overrides.
coordinator{ role: string; model?: string }Coordinator role and optional model override.
agentsCrewAgent[]Worker roster (one entry per spawnable role). Must contain at least one agent.
synthesisCrewAgentOptional final agent run after the rest complete. Same shape as CrewAgent.
mcpServersstring[]Names of MCP servers from the fleet registry to enable on the coordinator session while this crew is active (CrewActivator.toggleCrewMcp).
versionstring | numberAuto-managed on save (parser.ts:773).

CrewAgent schema

Authoritative shape: CrewAgent in src/skills/types.ts:145-154.

FieldTypeRequiredDescription
rolestringRole artifact name (e.g. fleet-coder). Resolved against SkillRegistry.getRole.
skillsstring[]Atomic skills composed into this agent's system prompt (joined under ## Capabilities by composeAgentPrompt, SkillRegistry.ts:1118-1148).
parallelbooleanOrchestration hint — workflow/runner may launch parallel members concurrently.
after'all' | string[]Orchestration hint — wait for 'all' other agents or a named list before starting.
modelstringPer-agent model override. Wins over the role's model: at spawn (fleetTools.ts:169).
mcpServersstring[]Per-agent MCP allowlist (subset of the crew-level mcpServers).
namestringDisplay name distinct from the role identifier (rendered into the <member> element).

The parallel/after hints are advisory — they're surfaced to the coordinator via the <active-workflow>/<active-crew> blocks and consumed by workflow-driven runners (e.g. /feature); the crew loader itself does not enforce them.

Tier precedence

SkillRegistry.loadAll() calls loadTier in fixed order (SkillRegistry.ts:176-178):

  1. bundledsrc/skills/bundled/crews/
  2. user~/.fleet/crews/ (USERPROFILE on Windows, HOME on Unix)
  3. project<cwd>/.fleet/crews/

Later tiers win by kind:name key (upsertArtifact). A project crew named my-crew overrides a bundled or user crew named my-crew; a user crew of the same name only overrides bundled.

SEC-4: project-tier role artifacts cannot escalate agent_type

Even though project-tier crews can override bundled crews, the roles they reference are subject to a privilege clamp in src/fleet/permissions.ts:

ts
canRoleOverrideAgentType(requestedType, roleType, roleTier)
  • bundled and user role tiers are trusted — any agent_type override is allowed.
  • project role tiers may only narrow privileges (or stay at the same level): if the role declares an agent_type whose privilegeLevel (agentPermissionProfiles.ts) is higher than the requested type, the spawn fails with Security policy violation: Project role cannot escalate privileges… (permissions.ts:22-52, enforced in fleetTools.ts:118-140).
  • coordinator is never spawnable as a worker (permissions.ts:28-33).

In practice: a project-tier role file cannot silently turn a reviewer (read-only) worker into a coder (write/exec).

Topology semantics

ValueBehaviorWhen to pick
hubCoordinator is the central messaging hub; workers do not message each other.Default for most crews. Structured pipelines, sequential or fan-out/fan-in patterns.
meshWorkers can address each other directly via send_message.Collaborative tasks needing peer-to-peer coordination (e.g. paired review + revise loops).
silentWorkers run independently with no inter-worker messaging.Pure parallel work where outputs are merged by a synthesis step or by the coordinator (e.g. independent reviewers).

The topology field is stored in FleetStateStore.activeTopology on activation (CrewActivator.ts:114-118 for v1, CrewActivator.ts:190-194 for v2) and surfaces as the topology= attribute of the injected <active-crew> block. Workers ultimately consult this value when deciding which destinations are valid for send_message.

Limitation: the exact routing semantics for mesh are governed by MessageBus; if your crew depends on strict peer-only delivery semantics, verify against src/messaging/MessageBus.ts before relying on it. The activator itself only records the topology and exposes it to the coordinator.


Bundled crews

All five bundled crews live at src/skills/bundled/crews/ and ship inside the package. They are loaded into the bundled tier on every session start (cached for process lifetime; SkillRegistry.ts:235-255).

agents-fleet-crew

File: src/skills/bundled/crews/agents-fleet-crew.crew.md

The default development crew for working on the agents-fleet repository itself. All agents share the agents-fleet-conventions atomic skill (TypeScript strict + ESM + branded types + named exports + no enums); specialists layer domain-specific skills on top.

Coordinator role: default-coordinatorTopology: hubDefault workflow: planningMCP servers: bluebird, workiq

Agents:

RoleSkillsParallel
fleet-coderagents-fleet-conventions
fleet-testeragents-fleet-conventions, vitest-patterns
fleet-architectagents-fleet-conventions, coordinator-worker-architecture
fleet-security-revieweragents-fleet-conventions, security-audit-checklist
fleet-correctness-revieweragents-fleet-conventions, prepared-statements-pattern
fleet-exploreragents-fleet-conventions, coordinator-worker-architecture
fleet-researcheragents-fleet-conventions
test-reviewervitest-patterns

Sample invocation:

text
/crew activate agents-fleet-crew
Implement a new "/diagnose" command that prints SessionSendQueue state.

code-review-crew

File: src/skills/bundled/crews/code-review-crew.crew.md

Multi-perspective code review crew. Four specialist reviewers run in parallel against the current diff, each producing findings from a single perspective.

Coordinator role: default-coordinatorTopology: hubDefault workflow: code-reviewMCP servers: none

Agents:

RoleSkillsParallel
architecture-reviewer
correctness-reviewer
performance-reviewer
security-reviewer

Sample invocation:

text
/crew activate code-review-crew
/code-review

init-crew

File: src/skills/bundled/crews/init-crew.crew.md

Codebase investigation crew used by /init. Seven domain explorers run in parallel (read-only explorer agents) and an init-critic verifies findings afterward.

Coordinator role: research-coordinatorTopology: hubDefault workflow: init-investigationMCP servers: none

Agents:

RoleSkills
init-arch-explorer
init-build-explorer
init-pattern-explorer
init-decision-explorer
init-dep-explorer
init-api-explorer
init-security-explorer
init-critic

Sample invocation:

text
/crew activate init-crew
/init

research-crew

File: src/skills/bundled/crews/research-crew.crew.md

Adversarial deep-research crew. Four research angles run in parallel, then a critic agent runs after all four to verify and triangulate findings.

Coordinator role: research-coordinatorTopology: hubDefault workflow: adversarial-researchMCP servers: none

Agents:

RoleSkillsParallelAfter
primary-researcher
counter-researcher
context-researcher
edge-case-researcher
research-critic[primary-researcher, counter-researcher, context-researcher, edge-case-researcher]

Sample invocation:

text
/crew activate research-crew
/research "Tradeoffs of pgvector vs Qdrant for our embedding workload"

minimal-dev-crew

File: src/skills/bundled/crews/minimal-dev-crew.crew.md

A two-agent, minimal-footprint development crew: the ponytail-coder implements with YAGNI discipline, then a reviewer composing the ponytail-review skill audits the result for over-engineering.

Coordinator role: default-coordinatorTopology: hubDefault workflow: none MCP servers: none

Agents:

RoleSkillsParallelAfter
ponytail-coder
default-reviewerponytail-review

Sample invocation:

text
/crew activate minimal-dev-crew
/do "Add a --json flag to the status command"

Authoring custom crews

Where to put the file

TierDirectoryWhen to use
user~/.fleet/crews/<name>.crew.mdPersonal crews you want available across every project.
project<cwd>/.fleet/crews/<name>.crew.mdCrew tailored to the current repository. Wins over user/bundled crews of the same name.

Create the directory if it doesn't exist; SkillRegistry ignores missing tier roots silently.

Worked example — minimal custom crew

.fleet/crews/docs-crew.crew.md:

markdown
---
name: docs-crew
description: Documentation-focused crew for prose + markdown work
topology: silent
workflow: freeform
coordinator:
  role: default-coordinator
agents:
  - role: doc-writer
    skills: [docs-conventions]
  - role: doc-reviewer
    skills: [docs-conventions]
    after: [doc-writer]
---

# docs-crew

A two-agent crew that writes then reviews documentation.

Activate with:

text
/crew activate docs-crew

Tip: the fastest way to start is to copy a bundled crew from src/skills/bundled/crews/ into .fleet/crews/ and edit it. The bundled crews are guaranteed to parse cleanly under parseCrewV2 and give you a working baseline.

Per-command workflow overrides (T-148)

A crew's top-level workflow: field names the default workflow injected into the coordinator's <active-workflow> block. The optional workflows: map lets you swap which workflow a specific slash command runs while this crew is active, without forking the command handler:

yaml
---
name: strict-team-crew
description: Strict pipelines for /feature and /code-review under this crew
topology: hub
workflow: freeform
workflows:
  feature: my-detailed-pipeline
  code-review: strict-review
coordinator:
  role: default-coordinator
agents:
  - role: coder
---

Resolution rules (src/skills/workflowResolver.ts:34-77):

  1. If an active crew has workflows[commandName] set and the named workflow resolves to a workflow with at least one stage → use it (source: 'crew').
  2. Otherwise fall back to the command's bundled default workflow (source: 'default').
  3. If a crew maps a command to a workflow name that doesn't exist or has no stages, the command surfaces a loud error rather than silently falling back. Misconfigurations must not masquerade as default behavior.

Validation guardrails (src/skills/parser.ts:791-813):

  • Keys must match /^[a-z][a-z0-9-]*$/ (kebab-case slash-command names). Malformed keys are dropped with a console.warn and skipped.
  • Values must be non-empty strings. Non-strings or empty strings are dropped.
  • A wholly malformed workflows: (e.g. a string or array) is dropped silently (treated as absent).
  • The referenced workflow is not validated at parse time — resolution happens at command-invocation time so workflows added later by another tier still resolve.

Which commands consult the map today:

CommandBundled default workflow
/featurefeature-pipeline
/code-reviewcode-review
/initinit-investigation
/researchadversarial-research

Any other slash command ignores the workflows: map. See workflows reference §Per-command override mechanism for the runtime details.

/init placement caveat: workflow resolution runs after the status / scopes / load subcommand router, so those read-only paths over .fleet/context/ don't surface workflow errors that have nothing to do with their job (src/commands/initCommand.ts:140).

Variations

Silent topology (independent parallel work):

yaml
---
name: triage-crew
description: Three independent triagers, no inter-worker chat
topology: silent
workflow: freeform
coordinator:
  role: default-coordinator
agents:
  - role: triager
    name: triager-a
    parallel: true
  - role: triager
    name: triager-b
    parallel: true
  - role: triager
    name: triager-c
    parallel: true
---

MCP-restricted crew (coordinator gets two extra MCP servers; one worker is locked down to a subset):

yaml
---
name: research-with-mcp
description: Research crew with curated MCP access
topology: hub
workflow: adversarial-research
mcpServers: [bluebird, workiq]
coordinator:
  role: research-coordinator
agents:
  - role: primary-researcher
    parallel: true
    mcpServers: [bluebird]   # only bluebird, not workiq
  - role: counter-researcher
    parallel: true
---

Crew-level mcpServers: enables those servers on the coordinator session via CrewActivator.toggleCrewMcp (resolved against the fleet's registered MCP servers; unknown names are skipped). Per-agent mcpServers: narrows what an individual worker sees.


Activator lifecycle

The activator is src/skills/CrewActivator.ts. It owns the swap between crews and is the only path that mutates activeCrew / activeTopology on the fleet state store.

/crew activate <name> flow

  1. Resolution. SkillRegistry.getCrewV2(name) is consulted first. If a real v2 crew exists (and isn't a v1 shim), the v2 path runs. Otherwise the legacy v1 path runs via SkillRegistry.getCrew(name) (which itself may project a v2 crew down to the v1 shape — SkillRegistry.ts:544-554). (CrewActivator.ts:78-105)
  2. Validation (v2). Every agent.role is resolved via registry.getRole, every agent.skills[] entry via registry.getAtomicSkill, the coordinator.role, and the workflow (always — defaults to freeform). Any miss throws a CrewActivationError before the store is mutated, so a failed activation never leaves a half-configured crew name behind. (CrewActivator.ts:152-186)
  3. State transition. store.activeCrew and store.activeTopology are updated (invalidates: ['meta']). The UI re-renders. (CrewActivator.ts:190-194)
  4. System prompt rewrite. The coordinator's system prompt becomes:
    <coordinator role.systemPrompt>
    
    <active-crew name="…" topology="…" workflow="…">
      <member role="…" skills="…" agentType="…" whenToUse="…" name="…" />
    
    </active-crew>
    
    <active-workflow name="…">
      <description>…</description>
      <stages> <stage … /> … </stages>
      <body> … (escaped) … </body>
    </active-workflow>
    (CrewActivator.ts:196-207, builders at :303-342)
  5. Model swap. If crew.coordinator.model (or the coordinator role's model) is set, the coordinator session model is changed. (CrewActivator.ts:203-206)
  6. MCP toggle. Previously enabled crew MCP servers are disabled, then the new crew's mcpServers[] are resolved against the fleet registry and enabled on the coordinator session. (CrewActivator.ts:276-293)

The legacy v1 path (activateV1) does the same in spirit but operates on the v1 Crew / Skill shapes and emits a v1-flavored <active-crew> block whose members are keyed by skill= (not role=) and which lacks an <active-workflow> sibling.

/crew deactivate (or /crew stop)

  1. store.activeCrew cleared to null; activeTopology reset to 'hub'.
  2. Any crew-enabled MCP servers are disabled on the coordinator session.
  3. The coordinator system prompt is reset (setSystemPrompt(undefined)), reverting to the default coordinator role and removing both the <active-crew> and <active-workflow> blocks.

(CrewActivator.ts:213-238)

Resume behavior

The active crew name is persisted in the session JSON (the session store serializes state.activeCrew and state.activeTopology). On --resume, the activator is re-invoked so the coordinator prompt, model, and MCP scope are all restored to match the snapshot.

Note: active loops/goals (/loop "<goal>" <interval>) are not part of the session schema and do not persist across --resume. Re-issue them after resume.

crew_match / skill_applied (worker spawn semantics)

Every spawn_worker tool response (src/coordinator/tools/fleetTools.ts) includes both v1 back-compat fields and v2 fields:

Response fieldMeaning
role_appliedThe role artifact that was actually used to compose the worker prompt (v2).
skills_appliedThe atomic skills composed into the worker prompt (v2).
skill_appliedv1 back-compat — equals role_applied on the v2 path.
crew_match"crew" when a crew member matched (priority 1 or 2 resolution); "default" when it fell through to default-${agent_type}.
crew_warningPresent when a crew is active but no member matched the requested agent_type — the coordinator used default-${agent_type} instead.

The resolution chain (src/coordinator/toolHandlers.ts:75-114, resolveCrewWorker):

  1. Explicit role (or legacy skill) argument on spawn_worker → used verbatim. crew_match: "crew". Skills from the explicit skills argument (if any) are composed in.
  2. Crew member match. If a crew is active, first try member.role === args.name (exact-name match), then fall back to the first member whose role's agentType equals the requested agent_type. On match: use that member's role + skills; crew_match: "crew".
  3. Default fallback. default-${agent_type} (e.g. default-coder). crew_match: "default". Surfaces crew_warning if a crew was active but no member matched.

Coordinator-side guidance: when a crew is active, prefer passing an explicit role: (and optional skills:) to spawn_worker rather than relying on the agentType-only fallback. The fallback picks the first crew member whose role's agentType matches; if your crew has multiple workers of the same agent_type, you'll get a silent first-match, not a deliberate pick.

v1 crew quirk: if an active crew is loaded from the v1 path (getCrew returns a v1 Crew), FleetManager.resolveCrewMember (src/fleet/FleetManager.ts:1364-1380) and the v1 branch of resolveActiveCrewWorker (toolHandlers.ts:181-191) match on member.skill (the v1 skill name), not role. The behavior is otherwise equivalent.


Limitations (be honest)

  • v1 Crew interface still exists alongside v2 CrewV2. The SkillRegistry.getCrew() fallback projects a v2 crew down to the v1 shape so legacy v1-era callers and tests keep working. New code should prefer the v2 path (getCrewV2).
  • workflows: map only consulted by 4 commands today (/feature, /code-review, /init, /research). Other commands ignore it. Adding a command to that set requires wiring resolveCommandWorkflow(...) into the command's handler.
  • No multi-crew sessions. Exactly one crew is active at a time; activating a new crew implicitly replaces the previous one (MCP servers and the coordinator prompt are swapped, not merged).
  • mesh topology routing is recorded but not strictly enforced at the activator layer. The activator stores activeTopology on the state store; whether workers can address each other is ultimately a function of MessageBus plus the send_message validation. Verify against src/messaging/MessageBus.ts if you need strict peer-only or hub-mandatory delivery semantics.
  • parallel / after are advisory hints. The crew loader does not enforce them; only workflow-driven runners (e.g. /feature) consume them as stage-scheduling input. A coordinator running in freeform mode may ignore them.
  • SEC-4 clamp applies to role artifacts, not to the crew file itself. A project-tier crew can name any role; the clamp is enforced when spawn_worker resolves and validates that role's agentType against the requested agent_type (fleetTools.ts:118-140).

Cross-references