A Multi-Agent Workflow with tk
A hands-on walkthrough for running a small team of AI agents in separate TermFlow panes that coordinate through a shared file protocol. You will scaffold the workspace with tk init, learn the request / response / status contract, wire up MCP the correct way, and drive worker panes from an orchestrator.
One TermFlow window with an orchestrator pane (the "PM") and one or more worker panes. The orchestrator hands work out through files in .agent-comms/ and drives the worker panes over TermFlow's MCP server. You bring your own agent (for example Claude Code) and your own keys — TermFlow ships no AI.
Prerequisites
- TermFlow 0.1.0 installed and running (this starts the local API on port 42031 and the MCP server on port 42032).
- An MCP-capable agent CLI in your panes — TermFlow generates paste-ready config for Claude Code, Codex CLI, and Gemini CLI. See Connect an agent.
- The
tkCLI (terminal-kit) available on yourPATH. It requires Node.js 18 or newer. Build it from theterminal-kitfolder and link it globally:
npm install
npm run build
npm link # creates the global `tk` command
Step 1 — Scaffold the workspace with tk init
From the root of the project your agents will work in, run:
cd /path/to/your/project
tk init
This writes the cross-terminal communication scaffold plus a set of per-tool config files:
your-project/
├── .agent-comms/ # cross-pane communication
│ ├── requests/ # PM → worker requests (REQ-YYYYMMDD-NNN.md)
│ ├── responses/ # worker → PM responses (RESP-YYYYMMDD-NNN.md)
│ ├── status/ # per-terminal status (terminal-{id}.status)
│ ├── shared/
│ │ └── findings/ # cached research results
│ └── README.md # quick reference
├── .mcp.json # MCP config ⚠ see Step 2 — stale, do not use as-is
├── .gemini/
│ └── settings.json # Gemini MCP config ⚠ stale, do not use as-is
├── .claude/
│ └── settings.local.json # Claude permission allow-list
└── docs/
└── multi-team-agent-workflow.md # protocol reference (omitted with --no-docs)
The .agent-comms/ tree is the valuable output — it is the shared mailbox your agents read and write. The config files, on the other hand, need correcting (Step 2).
Flags
| Flag | Default | Effect |
|---|---|---|
-f, --force | off | Overwrite existing files/folders instead of aborting when they already exist. |
--no-docs | docs are written | Skip docs/multi-team-agent-workflow.md. |
--api-url <url> | http://localhost:42031 | API base URL baked into the generated MCP config. Pass this if you changed the API port in Settings → Connections. |
If any of the target files already exist, tk init stops and lists them rather than clobbering your work. Add -f only when you genuinely want to overwrite.
The request / response / status protocol
.agent-comms/ is a plain-files message bus — no daemon, no database. Any agent that can read and write files in the project can participate, which is exactly what agents running in TermFlow panes can do.
| Folder | Direction | Naming | Purpose |
|---|---|---|---|
requests/ | orchestrator → worker | REQ-YYYYMMDD-NNN.md | A unit of work handed to a worker. |
responses/ | worker → orchestrator | RESP-YYYYMMDD-NNN.md | The worker's findings, tagged with the request ID it answers. |
status/ | worker → everyone | terminal-{id}.status | A lightweight, frequently-updated marker so the orchestrator can poll progress without reading a pane. |
shared/findings/ | shared | your choice | A cache of reusable research so the same lookup is not repeated. |
A request file follows a simple front-matter-style Markdown shape:
# Research Request
**ID:** REQ-20260704-001
**From:** Project Manager
**To:** Leader Agent
**Timestamp:** 2026-07-04T09:15:00Z
**Priority:** HIGH <!-- HIGH | MEDIUM | LOW -->
**Status:** PENDING
## Request Type
- [x] Code Exploration
- [ ] Log Analysis
- [ ] Documentation Search
## Description
Trace how the auth gate decides whether a route requires a token.
## Expected Output
The file + function names, and the exact condition that toggles enforcement.
The worker answers with a matching response, echoing the originating Request ID so the orchestrator can pair them:
# Research Response
**ID:** RESP-20260704-001
**Request ID:** REQ-20260704-001
**From:** Leader Agent
**To:** Project Manager
**Status:** COMPLETE <!-- COMPLETE | PARTIAL | FAILED -->
## Summary
Enforcement is gated on the "expose on network" flag.
## Detailed Findings
...
## Recommendations
...
The status/ directory is reserved by the scaffold but its contents are yours to define — write a short marker per terminal (for example WORKING, BLOCKED, DONE) so the orchestrator can glance at a file instead of interrupting a busy pane.
Here is the full loop end to end:
Step 2 — Configure MCP the right way (the Connect modal, not tk's config)
An honest note: The
.mcp.jsonand.gemini/settings.jsonthattk initwrites are stale. They describe an old stdio server keyedopen-terminal, point at a placeholder path (path/to/auto-terminal/mcp-server/build/index.js), and list only 5 tools. The MCP server TermFlow 0.1.0 actually runs is a streamable-HTTP server keyedauto-terminalathttp://127.0.0.1:42032/mcp, exposing 7 tools. Do not use the generated MCP files as-is.
Instead, generate correct config from inside the app. Open Settings → Connections → "Connect an AI agent". The modal produces paste-ready snippets for Claude Code, Codex CLI, and Gemini CLI. Replace the tk-generated block with the modal's output. The essential difference:
| Field | What tk init writes | What the Connect modal gives you |
|---|---|---|
| Server key | open-terminal | auto-terminal |
| Transport | stdio (command/args) | streamable HTTP (url) |
| Endpoint | placeholder file path | http://127.0.0.1:42032/mcp |
| Tool count | 5 (documented) | 7 |
For Claude Code, the corrected .mcp.json looks like this:
{
"mcpServers": {
"auto-terminal": {
"type": "http",
"url": "http://127.0.0.1:42032/mcp",
"headers": {
"Authorization": "Bearer <token>",
"X-Termflow-Terminal-Id": "${TERMFLOW_TERMINAL_ID}"
}
}
}
}
On the default localhost-only setup every endpoint is unauthenticated — it is bound to 127.0.0.1, so the Authorization header is optional. The bearer token only becomes mandatory once you turn on Expose on local network. The real credential is the authToken shown in Settings → Connections (reveal / copy / rotate there). See Local API and auth.
One more consequence of the rename: the .claude/settings.local.json permission allow-list the scaffold writes references mcp__open-terminal__*. Once your server is keyed auto-terminal, update that entry to mcp__auto-terminal__* so the tools are actually permitted.
Step 3 — Drive the worker panes
With a real MCP connection in place, the agent in your orchestrator pane can create and command the other panes directly. The tools that make this work (full schemas in MCP tools):
| Tool | Use in orchestration |
|---|---|
create_terminal | Spin up a worker pane. direction: "horizontal" splits right, "vertical" splits below; new panes inherit the live working directory. |
execute_command | Send a command or an agent prompt to one terminal — or an array of terminal IDs to fan the same command out to many panes at once. Returns immediately (async). |
get_terminal_output | Read a worker's output back (lines, offset) to check on progress or collect results. |
list_terminals / get_terminal_detail | Discover panes and their tab IDs. |
get_my_terminal | The orchestrator resolves its own pane via the identity header (or pass the shorthand "me" to any tool). |
A typical TermFlow window during a run:
+---------------------------------------------------------------+
| TermFlow _ □ x |
+-------------------+-------------------+-----------------------+
| Orchestrator | Worker B | Worker C |
| (Project Mgr) | (Research) | (Tests) |
| | | |
| writes REQ files | reads REQ, | runs the suite, |
| drives B & C via | writes RESP + | writes RESP + |
| MCP, polls RESP | status | status |
+-------------------+-------------------+-----------------------+
To kick a worker into reading its request, the orchestrator sends a prompt to that pane. cliType formats the submission for the target agent CLI:
{
"terminalId": "term-b",
"command": "Read .agent-comms/requests/REQ-20260704-001.md, do the work, and write your findings to .agent-comms/responses/ with a matching Request ID.",
"cliType": "claude"
}
To run the same command across several panes in one call, pass an array of IDs — this is the batch fan-out path:
{
"terminalId": ["term-b", "term-c"],
"command": "git pull --rebase",
"cliType": "default"
}
The orchestrator then polls responses/ for RESP- files whose Request ID matches what it dispatched, reads each one, and moves the plan forward. Because everything flows through files, a pane can crash and be respawned without losing the conversation — the mailbox persists on disk.
Files under .agent-comms/ are ephemeral communication artifacts. Clean them up between runs so stale requests are not re-processed, and consider adding the directory to .gitignore for real projects.
Putting it together
tk init→ get the.agent-comms/protocol scaffold. → verify: the folder tree above exists.- Settings → Connections → Connect an AI agent → replace the stale
.mcp.jsonwith the modal'sauto-terminalHTTP config, and fix the.claudepermission prefix. → verify: your agent lists the TermFlow MCP tools. - Open an orchestrator pane and one or more worker panes; have the orchestrator dispatch requests and drive workers via
create_terminal/execute_command. → verify:RESP-files appear and pair with yourREQ-files.
Next steps
- The tk CLI — the full reference for what
tk initscaffolds and why. - Fan a command to many panes — go deeper on the
execute_commandarray / batch fan-out used in Step 3.