How to communicate with the human operator (and other agents) via the MCP messaging server. Covers when to send each message type, priority semantics, the mandatory status heartbeat, and anti-patterns. Loaded by default into every agent-containers session regardless of agent type — all agents in containerised execution need this.
You have an MCP server named agent-messaging mounted in your container.
It exposes two tools:
send_message — post a message to the human operator via the
project dashboardcheck_messages — read any pending responses to your messagesUse it to coordinate with the human in real time. Messages are NOT
committed to git as they happen — they are ephemeral. When your session
completes, the full message log is persisted to
sessions/<id>/messages.yaml in the project repo.
These are non-negotiable. Skipping them breaks the orchestration flow.
Every 5 minutes of active work, send a status message so the UI and
the PM agent can see what you're doing. Status messages have a
structured body: {state, summary} where:
state is one of the values in <project>/enums/agent_state.yaml
(investigating, planning, awaiting_plan_approval, implementing,
testing, debugging, refactoring, documenting, self_verifying,
blocked, handed_off, done)summary is 1-2 plain-text sentencesAlways informational priority — status messages never block.
Example:
{
"type": "status",
"priority": "informational",
"body": {
"state": "implementing",
"summary": "Wired the JWT middleware into the auth router. Now writing unit tests for the validation logic."
}
}
Send a status message on every state transition too (e.g. moving from
investigating → planning, or from implementing → testing).
Check <project>/templates/artifacts/manifest.yaml: if the plan
artifact has approval_gate: true, you MUST send a plan_approval
message after writing plan.md and before starting implementation:
{
"type": "plan_approval",
"priority": "blocking",
"body": "## My plan\n\n(the contents of plan.md)..."
}
Then stop and exit. The orchestrator will re-engage you with the
human's response via check_messages.
If you have a genuine ambiguity that blocks correct work, send a
question message with priority: blocking and stop:
{
"type": "question",
"priority": "blocking",
"body": "Should `/auth/refresh` rotate the refresh token or keep the same one? The contract in [[contract-auth-token]] doesn't specify. Option A: rotate (safer, more complex). Option B: reuse (simpler, less safe). I lean toward A unless you disagree."
}
Good blocking questions:
informational)Milestones worth surfacing but not blocking work. Keep going after