Cockpit · multi-agent
Tutorial · Cockpit

An agent team in Cockpit

Cockpit's real power is the multiplexer: many agents in one window, each in its own folder. Here you'll wire up three — an orchestrator, a backend, and a frontend — each with its own AGENTS.md, all talking to each other over the remote-pi mesh.

What you'll build

Three Pi agents, side by side as panes in a single Cockpit workspace. Each lives in its own subfolder and reads that folder's AGENTS.md as its standing brief, so each one boots into a role. They coordinate by sending each other messages on the local mesh — the orchestrator splits a request, hands tasks to the backend and frontend, and stitches their replies back together.

Nothing here leaves your machine: the mesh runs over a local socket, and all three agents work on your real files.

Two pieces you already know
This builds on Getting started (install Pi + the remote-pi extension) and Local mesh (how two agents trade messages). Skim those first if the mesh tools are new to you.

Before you start

  • Cockpit installed — grab it from the Cockpit page. On first launch its onboarding checks for pi, the remote-pi extension, and the supervisor, and helps you install anything missing.
  • The remote-pi extension is what hands every agent the mesh tools, so make sure onboarding is green before you build the team.

1. Lay out the folders

An agent's identity comes from its folder, so give each teammate one. In your project, create three subfolders, each with its own AGENTS.md:

project layout — text
my-app/
├── orchestrator/
│   └── AGENTS.md
├── backend/
│   └── AGENTS.md
└── frontend/
    └── AGENTS.md

AGENTS.mdis the brief Pi reads when it starts in a folder — the agent's role and house rules. Give each one a clear job and tell it how to behave on the mesh.

orchestrator/AGENTS.md — markdown
# Orchestrator

You coordinate two teammates over the Remote Pi mesh: `backend` and
`frontend`. You don't write app code yourself — you split the work,
delegate it, and integrate the results.

## How you work
- At the start of every turn, drain your inbox and read any replies.
- Break a request into one backend task and one frontend task.
- Delegate with agent_send to "backend" and "frontend".
- Collect their replies, reconcile mismatches (e.g. the API shape vs.
  what the UI needs), and report back to the user.

Keep each message small and explicit: say what you want and what
"done" looks like.
backend/AGENTS.md — markdown
# Backend

You own the server and API in this folder. On the Remote Pi mesh you are
the peer named `backend`.

## How you work
- Check your inbox each turn — the `orchestrator` sends you tasks.
- Do the work here, in this folder, then reply to the sender (use the
  message id as `re`).
- If a task is ambiguous, reply asking for the missing detail instead of
  guessing.
- Keep the API contract (routes, payloads) explicit so `frontend` can
  build against it.
frontend/AGENTS.md — markdown
# Frontend

You own the UI in this folder. On the Remote Pi mesh you are the peer
named `frontend`.

## How you work
- Check your inbox each turn — the `orchestrator` sends you tasks.
- Build against the contract `backend` exposes. If you need a route or
  field that doesn't exist yet, ask the orchestrator to coordinate it.
- When done, reply to the sender with what changed (use the message id
  as `re`).
One agent per folder
Pi allows exactly one agent per directory — which is precisely why each teammate gets its own subfolder. Three folders, three agents, three distinct peers on the mesh.

2. Open the three panes

In Cockpit, open my-app/ as a workspace. The file tree on the right shows your three subfolders. For each one, right-click the folder and create an agent there — Cockpit roots that agent in the subfolder, so it picks up the right AGENTS.md.

Split the canvas so all three are visible at once — orchestrator on one side, backend and frontend on the other — and drag the dividers to taste. One agent streaming a long answer never freezes the others, and the whole layout comes back exactly like this the next time you open the app.

Name them to match
When an agent asks for a name (or in its /remote-pi wizard), use orchestrator, backend, and frontend. Those are the names teammates address in agent_send, so matching them to the folders keeps the prompts readable.

3. Put them on the mesh

Agents meet in a shared session named local, over a Unix socket — no network. Join each agent the same way as in the terminal: in each pane's composer, run the slash command once.

each pane · composer — text
/remote-pi

The first run is a quick wizard (name + relay); accept the folder name so the peer is called orchestrator, backend, or frontend. Then confirm everyone is home — ask the orchestrator:

orchestrator · prompt — text
List the other agents on the mesh.
orchestrator · tool call — text
list_peers()
→ backend
  frontend

If a teammate is missing from the roster, run /remote-pi in its pane and check again.

4. Run the orchestration

Now give the orchestrator something real and let it delegate. You only talk to the orchestrator — it talks to the others.

orchestrator · prompt — text
Add a "todos" feature: an API to list and create todos, and a page
that shows them with a form to add one. Coordinate backend and frontend.

It breaks the work in two and sends a task to each peer. A send returns an ACK, not an answer — it's fire-and-ACK, not a blocking call.

orchestrator · tool calls — text
agent_send({
  to: "backend",
  body: { task: "Expose GET /todos and POST /todos (title:string). Return the JSON shape." }
})
→ Delivered to backend

agent_send({
  to: "frontend",
  body: { task: "Build a Todos page: list todos and a form to add one, against backend's API." }
})
→ Delivered to frontend

On its next turn, backend sees the task, does the work in its own folder, and replies — quoting the message id in re so the orchestrator knows which task it answers:

backend · tool calls — text
get_messages()
→ [..] from=orchestrator id=7f3a91 { "task": "Expose GET /todos and POST /todos ..." }

# ...writes the routes here, in backend/ ...

agent_send({
  to: "orchestrator",
  body: { done: "Added GET/POST /todos", api: { todo: { id: "string", title: "string", done: "bool" } } },
  re: "7f3a91"
})
→ Delivered to orchestrator

frontend does the same in its folder. Back in the orchestrator, both replies arrive on its next turns; it reconciles them — for instance, forwarding the exact API shape to the frontend if it asked — and reports the finished feature back to you. Three agents, three folders, one coordinated change.

If a reply never comes
An agent_sendto a peer that's mid-turn can come back busy — the message was dropped, so retry shortly. The full set of ACKs (Delivered, busy, denied, timeout) is covered in Local mesh.

Why do this in Cockpit

You could run three terminals — but in Cockpit the whole team lives in one window. Every agent streams its own work in its own pane, you watch the orchestrator hand off and the others pick up in real time, and the layout (and each session's history) comes back when you reopen the app. Add a real terminal pane to run the servers, and the build, the agents, and their conversation are all in front of you at once.

From here: promote the orchestrator to a 24/7 daemon so the team keeps coordinating in the background, or read Remote mesh to add a teammate running on a different machine.