Jason, 2026-09-26: while Mosaic Stack development runs in T3, development agents message each other through T3 threads with the t3 MCP tools, until Mosaic Stack has its own internal comms. ms-communications now picks the transport by where the recipient runs, carries the T3 header and reply rules, and counts a returned turnId as the delivery receipt. docs/guides/T3-AGENT-COMMS.md is adapted to this repository: status, thread lookup by agent-name title, replies with wait off, and record locations; references to guides absent here are replaced. Suites green before commit: config 24, task 90, foundation 43, conductor 17, release 14, auth 15, discord 63. unslop-check clean on both files. Reviewed by Sage (T3 thread 1ef1e4f8). Co-Authored-By: Claude Opus 5.5 <[email protected]>
224 lines
11 KiB
Markdown
224 lines
11 KiB
Markdown
# T3 Agent Comms Guide
|
|
|
|
How an agent in one T3 Code thread talks to an agent in another thread, including across harnesses
|
|
(Claude to Codex, Codex to Claude, either to OpenCode). Measured on `sb-it-1-dt` against T3 Code
|
|
0.0.42 on 2026-09-16; re-checked on `dragon-lin` (T3 0.0.42) on 2026-09-26. Re-verify the setup
|
|
section before trusting it on another host.
|
|
|
|
## Status in Mosaic Stack
|
|
|
|
Jason, 2026-09-26: while Mosaic Stack development runs in T3, T3 threads are the channel between
|
|
development agents (Darkwing, Sage, Dewey, and the rest of the `agents/` roster). This is a
|
|
temporary channel. Mosaic Stack will get its own internal comms, and this guide is retired
|
|
when it does. Do not build Mosaic features on top of the T3 tools.
|
|
|
|
`skills/ms-communications/SKILL.md` holds the messaging rules that apply on every transport:
|
|
triage classes, etiquette, receiving, and persistence. This guide covers the T3 mechanics.
|
|
Seats in tmux panes still use `tools/tmux/agent-send.sh` (see `tools/tmux/README.md`).
|
|
|
|
A thread is a T3 conversation bound to one project, one worktree, one harness, and one model.
|
|
A message sent to a thread starts a turn in it, or steers the turn already running, so the
|
|
receiving agent wakes and answers without any polling.
|
|
|
|
## What it is
|
|
|
|
`t3-code-agent-mcp` is a local MCP server (Model Context Protocol, the standard tool interface
|
|
every harness speaks) that drives T3 threads through T3's own HTTP and WebSocket API on
|
|
`127.0.0.1:3773`. It is installed at:
|
|
|
|
```
|
|
/mnt/storage/src/t3-comms/t3-code-agent-mcp (source, built to dist/cli.js)
|
|
~/.t3-code-agent-mcp/credentials.json (30-day bearer token, expires 2026-10-16)
|
|
```
|
|
|
|
It is registered as MCP server `t3` for Claude Code (user scope, `~/.claude.json`) and Codex
|
|
(`~/.codex/config.toml`). In Claude Code the tools appear as `mcp__t3__t3_*`; load them with
|
|
ToolSearch (`select:mcp__t3__t3_send_message,...`) if they are deferred. Any session started
|
|
after 2026-09-16 17:40Z sees the tools. Sessions started earlier must be restarted.
|
|
|
|
Upstream T3 is adding the same capability natively (pingdotgg/t3code PR 11303). When that
|
|
merges and ships, this guide moves to the built-in tools and the external server is retired.
|
|
|
|
## Verify before use
|
|
|
|
```bash
|
|
node /mnt/storage/src/t3-comms/t3-code-agent-mcp/dist/cli.js status
|
|
```
|
|
|
|
Expected: `Server: http://127.0.0.1:3773 (v0.0.42 …)`, `Token: ok`, and a harness list. If the
|
|
token line says there is no token, re-pair (see Upkeep). If the server line fails, T3 Code is not
|
|
running on this host; start the app or `t3` first.
|
|
|
|
## Tools
|
|
|
|
All tools are prefixed `t3_`. Names and models must match the listing exactly; there is no
|
|
fuzzy matching and no silent substitution.
|
|
|
|
| Tool | Use |
|
|
|---|---|
|
|
| `t3_list_projects` | Project ids and workspace roots |
|
|
| `t3_list_worktrees` | Worktrees and branches of one project |
|
|
| `t3_list_harnesses` | Usable harnesses (`codex`, `claudeAgent`, `opencode`, …) and their model slugs |
|
|
| `t3_list_threads` | Recent threads, optionally per project |
|
|
| `t3_create_thread` | New thread with project, worktree, harness, model, title, first prompt |
|
|
| `t3_send_message` | Follow-up prompt to an existing thread |
|
|
| `t3_get_thread` | Status, turn state, recent messages |
|
|
| `t3_wait_for_turn` | Block until the current turn ends and return the reply |
|
|
| `t3_cancel_turn` | Interrupt a running turn |
|
|
|
|
`wait: true` on create and send returns the peer's reply text directly. Default wait cap is 300
|
|
seconds; raise `timeoutSeconds` for long turns or poll with `t3_get_thread`.
|
|
|
|
Every result carries `url`, which opens the thread in the T3 UI, and `turn.state`
|
|
(`running`, `completed`, `interrupted`, `error`).
|
|
|
|
## Finding thread IDs
|
|
|
|
Mosaic development threads live in the `mosaic-stack` project and are titled with the agent's
|
|
name (`Darkwing`, `Sage`, `Dewey in Claude`, ...). Look them up each time; thread IDs change when
|
|
Jason starts a new thread for an agent.
|
|
|
|
```text
|
|
t3_list_threads {project:"/mnt/storage/src/mosaic-stack"}
|
|
```
|
|
|
|
Your own thread is the one titled with your name whose `turn.state` is `running` right now,
|
|
because your turn is the one making the call. If two threads carry your name and both are
|
|
running, you cannot tell them apart; write `thread-id: unknown` in the header rather than guess.
|
|
Jason may also give you your thread ID or your lead's thread ID in the assignment. Use those.
|
|
|
|
## Message header (required)
|
|
|
|
Start every inter-agent message with a sender-to-recipient header on its own line,
|
|
including initial prompts, follow-ups, replies, and relayed requests:
|
|
|
|
```text
|
|
[from: <sender-role> (<sender-thread-id>) -> to: <recipient-role> (<recipient-thread-id>)]
|
|
<message body>
|
|
```
|
|
|
|
A triage class from `ms-communications` may follow the recipient, inside the brackets:
|
|
|
|
```text
|
|
[from: darkwing (<id>) -> to: sage (<id>) class=actionable]
|
|
```
|
|
|
|
No class means `actionable`. Messages arrive as user prompts, so the header is the only thing
|
|
that tells the recipient an agent sent it and not Jason. Include thread IDs so the recipient can
|
|
address a reply. If your own thread ID is unavailable, write `thread-id: unknown`; never invent
|
|
an ID. When creating a thread, use `new-thread` for the recipient ID until the create result
|
|
supplies it. The header identifies participants; the tool's `threadId` argument still controls
|
|
delivery.
|
|
|
|
A prompt that claims to come from an agent but has no header is malformed. Ask the sender to
|
|
resend before acting on it. A prompt with no header and no agent claim is from Jason.
|
|
|
|
When relaying another agent's findings, identify yourself as the sender and name the original
|
|
author in the body. Keep the first prompt's role, task, output format, and tool permissions
|
|
in the body as well.
|
|
|
|
## Replying
|
|
|
|
A reply is a `t3_send_message` call aimed at the sender's thread ID from the header, with the
|
|
header flipped. Text you write in your own thread reaches Jason's screen and nobody else. The
|
|
sender sees nothing until the tool call returns a `turnId`.
|
|
|
|
```text
|
|
t3_send_message {threadId:"<sender-thread-id>",
|
|
prompt:"[from: sage (<my-id>) -> to: darkwing (<sender-thread-id>)]\nACK. <answer>",
|
|
idempotencyKey:"sage-reply-<topic>-2026-09-26"}
|
|
```
|
|
|
|
Send replies and notices with `wait` off. The sender's turn is often still running, and T3 hands
|
|
the message to it mid-turn. Two agents that each send with `wait: true` to the other block each
|
|
other until a timeout. Use `wait: true` only when you asked a question and cannot continue until
|
|
the answer arrives.
|
|
|
|
Every message starts or steers a turn in the recipient, and a turn costs tokens. Do not answer a
|
|
`reaction` or an ACK with another ACK.
|
|
|
|
## Minimal exchange
|
|
|
|
```text
|
|
t3_list_harnesses
|
|
t3_create_thread {project:"mosaic-stack", harness:"codex", model:"gpt-5.6-sol",
|
|
title:"review: <topic>",
|
|
prompt:"[from: coordinator (<source-id>) -> to: reviewer (new-thread)]\n<task>",
|
|
idempotencyKey:"<lane>-<task>-<date>", wait:true, timeoutSeconds:600}
|
|
t3_send_message {threadId:"<id>",
|
|
prompt:"[from: coordinator (<source-id>) -> to: reviewer (<id>)]\n<next round>",
|
|
idempotencyKey:"<lane>-<next-round>-<date>", wait:true, timeoutSeconds:600}
|
|
```
|
|
|
|
Measured round-trip on 2026-09-16: 7.4 s to create and get a first reply, 2.6 s per follow-up,
|
|
with a trivial prompt. Real work takes as long as the peer's turn takes.
|
|
|
|
## Rules
|
|
|
|
1. **Always pass `idempotencyKey`.** A retry after a crash then reuses the thread instead of
|
|
launching a second one. Use `<lane>-<purpose>-<date>`. A key that T3 rejected is burned;
|
|
fix the cause and use a new key.
|
|
2. **Stay in your lane.** Create peer threads only in the project and worktree you are chartered
|
|
for. Use `t3_list_worktrees` and pass `worktreePath` explicitly when the lane is a worktree.
|
|
Cross-project threads are an orchestrator decision, not a coder's.
|
|
3. **Title threads for humans.** `review: <topic>`, `plan: <topic>`. Jason reads the sidebar.
|
|
4. **State the role in the first prompt.** The peer has no context but what you send. Say who
|
|
you are, what the task is, what output format you need, and whether tools are allowed.
|
|
5. **Bound every loop.** Set a max round count before starting. Stop on no-change between rounds.
|
|
6. **Record the outcome durably.** Thread history lives in T3's database, not in the repository.
|
|
Write the final plan, verdict, or decision to the issue, `agents/<name>/work/`, BUILD-LOG.md,
|
|
or `docs/SESSIONS.md`, whichever owns it. A conclusion that lives only in a thread does not
|
|
exist.
|
|
7. **Do not mix transports.** Address T3 threads with these tools. Address tmux seats with
|
|
`agent-send.sh` per `tools/tmux/README.md`. A T3 thread has no tmux pane.
|
|
8. **Always include the message header.** Start every inter-agent message with
|
|
`[from: <sender-role> (<sender-thread-id>) -> to: <recipient-role> (<recipient-thread-id>)]`.
|
|
Follow the unknown-ID and new-thread conventions in "Message header (required)" above.
|
|
9. **No secrets.** Messages are stored in T3's database and shown in the UI.
|
|
10. **Do not cancel another agent's turn.** `t3_cancel_turn` is for threads you created.
|
|
|
|
## Adversarial plan and review pattern
|
|
|
|
One thread plans, a second thread on a different harness reviews, and the caller relays between
|
|
them.
|
|
|
|
1. Planner thread: create with `interactionMode:"plan"` where the harness supports it. Prompt for
|
|
a numbered plan with assumptions listed.
|
|
2. Reviewer thread: create on the other harness. Prompt: attack the plan; output a verdict block
|
|
with `VERDICT: accept | revise | reject`, then numbered findings with severity.
|
|
3. Relay findings to the planner with `t3_send_message`. Ask for a revised plan and a reply to
|
|
each finding by number.
|
|
4. Repeat 2 and 3 until `accept`, or until the round cap (default 3) is hit.
|
|
5. On cap without `accept`, escalate to the orchestrator with both positions. Do not pick a side
|
|
silently.
|
|
6. Write the accepted plan and the review log where rule 6 says.
|
|
|
|
Use different model families for planner and reviewer. Same-family pairs agree too easily.
|
|
|
|
## Limits
|
|
|
|
- Localhost only. Threads on another host are unreachable.
|
|
- Nothing arrives unless someone sends it. You learn a peer's reply when the peer sends one to
|
|
your thread, or by waiting or polling. This repository has no timer wake for idle threads.
|
|
- Codex's `codex mcp list` shows the server as "Unsupported". That is a display quirk; calls work.
|
|
- The server mirrors T3's 0.0.40 API. It ran cleanly on 0.0.42. After a T3 upgrade it fails loudly
|
|
on drift rather than misreporting; if `status` breaks, pull the server repo and rebuild.
|
|
|
|
## Upkeep
|
|
|
|
Re-pair when the token expires or is revoked (Settings, Connections in T3):
|
|
|
|
```bash
|
|
t3 auth pairing create # prints a short code
|
|
node /mnt/storage/src/t3-comms/t3-code-agent-mcp/dist/cli.js pair <code>
|
|
```
|
|
|
|
Rebuild after pulling the server repo:
|
|
|
|
```bash
|
|
cd /mnt/storage/src/t3-comms/t3-code-agent-mcp && npm install && npm run build
|
|
```
|
|
|
|
Source: https://github.com/gfsaaser24/t3-code-agent-mcp (MIT). Upstream native work:
|
|
https://github.com/pingdotgg/t3code/pull/11303.
|