Architecture

agent-team has four layers. Each one can grow without changes to the others.

 .team.toml ──► config.Team ──► workflows (discuss, build, market, setup, ship)
                   │                    │ find members by role
                   ▼                    ▼
               AgentConfig ──────► agent.Agent ──► providers.Provider ──► a model somewhere
               (name, role,        (prompt +       anthropic | ollama | openai | agent-http
                owns, model)        history)        | any kind you register

1. Configuration (config.py)

A project’s .team.toml lists providers (how to reach a model) and agents (team members). Agents have a free-form role; the built-in workflows look for lead, builder, devops, marketing, and optionally factcheck, qa, security and docs. [limits] sets spend caps and [project].context how much of the project a prompt includes. Any other role can still join discussions and own files. Unknown keys are rejected with a clear message, so typos don’t silently change behaviour.

2. Providers (providers/)

A provider turns (system prompt, conversation) into a reply. Built in:

Kind Reaches Notes
anthropic Claude via the Anthropic API Streams, shows summarised reasoning, retries dropped connections, cancels and retries a stalled reply, sees images.
ollama Ollama, on this machine or another Retries while the server restarts.
openai Any OpenAI-compatible /v1/chat/completions server vLLM, LM Studio, llama.cpp, gateways.
agent-http Another machine running agent-team serve That machine keeps its model and credentials; see remote-agents.md.

Providers register themselves by kind (@register("kind")), and configuration is validated against the registry, so a new kind needs no change anywhere else. Every built-in kind also implements complete_tools, one step of a tool-using conversation, so any of them can be the devops member.

3. Agents (agent.py, prompts/)

An agent joins its config, its provider and an append-only conversation (append-only keeps provider-side reasoning valid between turns). Its system prompt comes from a Markdown template for its role, filled with project facts: the roster, the guarantees, the test command and the paths it owns. A project can replace any member’s prompt with its own file (prompt = "..."), or add to it with skills (skills.py): Markdown files or skill folders appended after the role prompt, so the workflow’s reply formats still hold.

4. Workflows (workflows/)

Each workflow is a plain function over a Team. Agents exchange files through <file path="..."> blocks, written by files.write_files, which refuses paths outside the project or the step’s allowed prefixes. Every run is logged to .team/logs/<workflow>.md in the project.

ship is different: the devops member drives it with tool use, and the tools are the only way it can act. With Claude it runs on the Anthropic SDK’s tool runner; with any other provider it runs on tool_loop.py, which uses that provider’s complete_tools. The rules that matter (merge_blockers, is_changelog_rename) are small pure functions with their own tests.

Review rules: the lead’s approval of a commit is also its sign-off on paths it owns, and a re-review gets the reviewer’s earlier review with the rule to block only on unresolved points or problems the new commit introduces (RE_REVIEW in ship.py).

fix closes the review loop: when a shift’s lead review requests changes on a team PR, a builder applies that review (read from the team’s own ship log; PR comments arrive as untrusted) on the PR’s branch, the lead confirms the blocking points, and only then is it pushed. Approvals stay tied to commits, so the next shift reviews the new head before anything merges.

build brings in the optional members when the team has them: a qa member writes tests for the plan first, a security member reviews the result once the lead approves (a NO sends it back), and a docs member updates the documentation afterwards. With several builders and --parallel, the lead splits the plan into parts with separate paths.

Records

Each workflow appends to .team/logs/<workflow>.md; every run and entry heading carries a timestamp marker, so logs.py can rebuild the timeline (older logs without markers still parse). Every model call appends a line to .team/usage.jsonl (member, model, tokens, run), which usage.py turns into cost estimates. agent-team ui (dashboard/) serves both on 127.0.0.1 with a strict Content-Security-Policy and a Host check, and never returns secret values. It can also edit .team.toml through config_io.py, which renders the file, validates it by reading it back as the CLI does, shows the diff, and saves atomically with a .team.toml.bak backup. Writes need the page’s session token and a same-origin request, and are refused if the file changed on disk. agent-team status --json gives the same summary to the Claude Code side panel (plugin/hooks/).

Trust model

Cost, context and running unattended

Edits, tool reviews, memory and autopilot (0.3)

To-do list, routing, gates and notifications (0.4)

Safety, proof and reach (0.5)