fleet-street has ten agents for London theatre work. A stage manager assigns research and calculations to specialists, asks for an independent review, and returns an answer to the person in the room.

This walkthrough follows a fictional production from its initial brief to a cost calculation and an HTML report. The supplied prices and attendance figures are assumptions, not current London market data. No bookings or public release are part of the task.

Roles and collaboration#

Contact the stage manager for a question spanning several roles, or a specialist directly for its area. The stage manager coordinates at medium effort; the nine specialists use high effort. All ten use Codex with separate workareas and shared history by default. An exact model is optional and must be available to the operator’s account; the native adapter rejects an unsupported selection.

RoleResponsibility
stage-managerBrief, routing, dependencies and final synthesis
dramaturgDramatic structure and audience experience
venue-scoutVenue fit, public evidence and confirmation questions
production-plannerStaffing, schedule and technical dependencies
budget-analystReproducible costs, receipts and scenario assumptions
accessibility-reviewerAudience/participant barriers and access information
audience-researcherAudience hypotheses and the evidence needed to test them
publicity-editorFactual listings, practical copy and report drafts
rights-researcherRights inventory and permissions questions
fact-checkerIndependent source, claim and calculation review

Use the routing directory to choose a role, then the live agent directory to obtain its actual Matrix ID. The stage manager invites only the agents needed in the originating room. A mixed brief is not a broadcast assignment to all ten.

A theatre brief and its specialist reviewA person asks in a Matrix room. The stage manager assigns a budget analyst, asks the fact-checker for independent review and returns a synthesis to that room. The other seven specialists are consulted only when needed.Human request in a roomstage-managerScope, assign and synthesizebudget-analystCalculate supplied inputsNo live prices assumedfact-checkerIndependent reviewKeep unknowns visibleOnly needed agents receive room access and assignments.The stage manager replies through the tool to the original room.

Set up the example#

You need a crossfire account, a working Codex installation and login, Node 26+, npm 11.17+ and Python 3.11+. The commands below use fleet/fleetd 0.1.20 and require a matching crossfire server. If your instance uses another release, follow its personalized setup guide rather than these package versions.

Get the example to follow along:

git clone https://github.com/control-flow-project/fleet-street.git
cd fleet-street
git fetch origin a2821d64f62a2c1d477b0810849de96541672452
git switch --detach a2821d64f62a2c1d477b0810849de96541672452

Supply your actual public server origin, human Matrix ID and short agent-name prefix. The example values below are not a working server or account:

python3 -m tools.fleet_street configure \
  --server https://chat.example.org \
  --owner '@alice:chat.example.org' --prefix alice-fs
npm ci --ignore-scripts --cache .temp/npm
./node_modules/.bin/fleet setup --config "$(pwd)/.local/fleet/runtime.toml"

The offline configure command creates a private working fleet under .local/; it does not enroll or launch it. Setup then requests the human’s approval of the exact roster. The installation session is not adopted as a managed agent.

An identical configure rerun preserves existing instructions and histories. Changed authority, names or model selection is rejected without overwriting state. Registered names such as alice-fs-stage-manager must be unique across the server. See the complete setup instructions .

Configuration and permissions#

The roster lists each agent’s name, role and workarea. Here is the first entry, before configure replaces the example server, owner and names:

fleet = "fleet-street"

[coordination]
adapter = "crossfire"
server = "https://example.test"
owner = "@owner:example.test"

[[instances]]
key = "stage-manager"
name = "sample-stage-manager"
definition = "stage-manager"
workarea = "agents/stage-manager/workarea/stage-manager"

[instances.listener_options]
history_mode = "shared"

fleet/runtime.toml at a2821d64.

The stage manager’s role file sets its effort, permissions and wake-up rules:

name = "Stage manager"
runtime = "codex"

[runtime_options]
model_reasoning_effort = "medium"
sandbox_mode = "danger-full-access"
approval_policy = "on-request"

[coordination_options]
wake_mode = "selected"
permissions = ["room.agent.invite"]

[[coordination_options.wake_senders]]
matrix_user_id = "@owner:example.test"
include_agents = true

fleet/agents/stage-manager/agent.toml at a2821d64.

Only the stage manager has the invitation capability. The selected owner and that owner’s agents may wake it, including owner agents outside this example fleet. Other humans must be added in management if they should wake a role. Membership, applied access, wake policy, delivery and mute remain separate checks.

The role uses danger-full-access with on-request. Review these settings before starting: the agents have the host user’s file access. Separate workareas and per-room histories do not isolate files or credentials.

Work through the fictional brief#

The human asks whether three studio performances can cover supplied costs and what must be confirmed before commitment. No external contact, booking, spending or public release is authorized.

{
  "kind": "fictional-example",
  "assignment": "river-bell-feasibility",
  "title": "The River Bell — a fictional studio proposal",
  "request": "Can three small London studio performances cover the supplied costs, and what needs confirmation before committing?",
  "form": "A devised piece by a fictional company, with five performers",
  "audience": "An audience hypothesis to test; no sales evidence is supplied",
  "venue": "Example Studio, a fictional London venue",
  "constraints": [
    "Three evening performances; dates are not booked",
    "120 saleable paid seats per performance in the assumed layout",
    "No public release, external enquiries, purchases or bookings are authorized"
  ],
  "deliverable": "A reviewed cost scenario, practical uncertainties and questions for the human",
  "inputs": ["examples/budget.json"],
  "unknowns": [
    "Venue and staff availability, current hire terms and tax treatment",
    "Production-specific access needs and provisions",
    "Rights and permission requirements for the actual material"
  ]
}

examples/brief.json at a2821d64.

The stage manager routes the arithmetic to the budget analyst and requests independent fact-checking. Other specialists can address material venue, production, access or rights gaps without starting an unrequested research project.

{
  "currency": "GBP",
  "performances": 3,
  "saleable_seats": 120,
  "occupancy": "0.75",
  "ticket_price": "18.50",
  "fee_rate": "0.05",
  "contingency_rate": "0.10",
  "costs": [
    {"label": "Fictional venue hire", "quantity": 2, "unit_cost": "850.00"},
    {"label": "Fictional performer days", "quantity": 15, "unit_cost": "120.00"},
    {"label": "Fictional technician days", "quantity": 3, "unit_cost": "160.00"},
    {"label": "Illustrative access provision allowance", "quantity": 1, "unit_cost": "300.00"},
    {"label": "Illustrative publicity allowance", "quantity": 1, "unit_cost": "250.00"},
    {"label": "Illustrative permission fee", "quantity": 1, "unit_cost": "200.00"}
  ]
}

examples/budget.json at a2821d64.

Run the calculation from the repository root:

python3 -m tools.fleet_street budget --input examples/budget.json \
  --output .local/budget.json

The result is GBP 4,745.25 net receipts, GBP 5,203.00 costs and a GBP 457.75 gap. The paid break-even is 297 tickets, or 82.50% of the supplied saleable capacity. The calculation basis explains pence rounding, fees, contingency and exclusions. The analyst still needs to assess whether the supplied demand, rates and assumptions are realistic.

Hand-offs and room replies#

The sample hand-off names the question, permitted inputs, output and stopping point. Replace its origin note with the actual delivered room, event, sender and time. Resolve the recipient from the directory, not a guessed name.

The executable example invokes the installed client using the profile supplied by fleetd:

#!/bin/sh
set -eu
if [ "$#" -ne 4 ]; then
  printf 'Usage: sh examples/send-handoff.sh ROOM_ID RECIPIENT_MATRIX_ID TRANSACTION_ID MARKDOWN_FILE\n' >&2
  exit 2
fi
: "${CROSSFIRE_PROJECT:?Use the project supplied by fleetd}"
: "${CROSSFIRE_AGENT_NAME:?Use the profile supplied by fleetd}"
node "$CROSSFIRE_PROJECT/.crossfire/client.mjs" \
  --project "$CROSSFIRE_PROJECT" --profile "$CROSSFIRE_AGENT_NAME" \
  matrix send-message --room-id "$1" --event-type m.room.message \
  --mention-user "$2" --txn-id "$3" --markdown-file "$4"

examples/send-handoff.sh at a2821d64.

--mention-user writes actual Matrix mention metadata. If accepted by the recipient’s listener it interrupts; an ordinary progress update should not use that control. The stable transaction ID is reused only for an identical uncertain send. The tool does not grant room access or override a wake rule.

The stage manager sends the final answer through the messaging tool to the originating room. Terminal output instead reaches the owner’s DM. Neither an invitation nor an input receipt proves the analytical task is complete.

Prepare a report#

The local report input labels its claims and unresolved questions:

{
  "title": "The River Bell",
  "subtitle": "Fictional three-performance feasibility note",
  "status": "Fictional example — not a booking, quote or production recommendation",
  "summary": "At the supplied occupancy and price the scenario does not cover its costs. The calculation is a starting point for the human's decision, not evidence of likely ticket sales.",
  "findings": [
    {"label": "Calculated", "text": "The paid-ticket scenario has a funding gap on the stated assumptions."},
    {"label": "Assumed", "text": "The fixture uses 120 saleable seats and 75% expected paid occupancy; no demand evidence is supplied."},
    {"label": "Unknown", "text": "Availability, tax, staffing inclusions and actual access and permission requirements need confirmation."}
  ],
  "questions": [
    "Which dates and venue layout are actually available?",
    "What do the venue and staff rates include, and what tax treatment applies?",
    "Which access provisions are appropriate and properly resourced?",
    "What permissions are required for the material and intended uses?"
  ],
  "sources": [
    {"label": "Fictional supplied brief", "reference": "examples/brief.json"},
    {"label": "Fictional structured cost inputs", "reference": "examples/budget.json"}
  ]
}

examples/report.json at a2821d64.

python3 -m tools.fleet_street report --input examples/report.json \
  --budget examples/budget.json --directory .local/public-report

Open the example report to see the cost calculation, assumptions and unresolved questions together. The report links to its calculated budget data. Generating these files does not publish them through crossfire.

Creating a draft is not permission to release private information. A real agent must obtain explicit public-release authorization, inspect every file, and use the native report publisher . It sends the actual returned URL to the intended room and explains that anyone with the link can view the report. See the complete task walkthrough .

Resume, adapt and verify#

./node_modules/.bin/fleet agent stop fleet-street budget-analyst
./node_modules/.bin/fleet agent start fleet-street budget-analyst

Start reuses saved history; it is not a fresh context. Preserve .local/fleet/ through host restarts. Edit wanted instructions in the stopped working fleet; configure does not silently recopy templates over an existing session.

The operations guide covers room diagnostics, native questions, stop/resume and updates. The test guide explains how to check the configuration, local tools and report before enrolling.