Skip to content

Agent Mail API ​

Durable local mailbox coordination in Albiex Synth City for Claude Code, Codex CLI, GitHub Copilot CLI, and trusted same-machine orchestration tools.

Team And Messages ​

List Team ​

http
GET /api/v1/agent-mail/team?sync=true

Returns Agent Mail participants, grouped by durable member identity. Set sync=false to skip the Agent Bridge observation pass.

Each member includes the shared agent_status. External member reads and synth_city_list_team include this object. Use it for online, activity, wake, and idle-duration displays.

Legacy status, can_nudge, wake_methods, and wake_state remain available. Delivery receipts retain delivered_waiting when the agent must poll Mail. That receipt does not mean the agent can be woken. The shared status follows the existing wake target rules and changes no delivery behavior.

Update Member ​

http
PATCH /api/v1/agent-mail/members/{member_id}

Updates display name, role, or charter for a durable participant.

Send Message ​

http
POST /api/v1/agent-mail/messages
json
{
  "kind": "context_request",
  "recipient_member_id": 2,
  "subject": "Need API context",
  "body_markdown": "Which service owns this route?",
  "payload": {
    "why_needed": "Another repo agent is implementing a caller.",
    "files_or_symbols": ["backend/app/services/agent_mail_service.py"]
  }
}

This route requires the caller's Agent Mail session token. Supported kinds are message, context_request, handoff, and answer. Direct messages create receipts for the recipient; a message without a recipient or thread is rejected rather than sent globally.

Send An Operator-Global Broadcast ​

http
POST /api/v1/agent-mail/broadcasts
X-Synth-City-Operator-Token: <operator token>
json
{
  "audience_type": "operator_global",
  "audience_id": "global",
  "subject": "Maintenance notice",
  "body_markdown": "This notice is intentionally for every member."
}

Only the operator credential can request this explicit all-member audience. Agent session and external-actor tokens cannot use it.

List Root Messages ​

http
GET /api/v1/agent-mail/messages

Returns root messages for the Requests tab and thread browser.

Get Thread ​

http
GET /api/v1/agent-mail/messages/{message_id}/thread?member_id={member_id}

Returns a root message and its replies. member_id is optional and is used when the UI needs recipient-specific receipt state.

Mark Read And Acknowledge ​

http
POST /api/v1/agent-mail/messages/{message_id}/read
POST /api/v1/agent-mail/messages/{message_id}/ack

Both endpoints accept:

json
{ "member_id": 2 }

Acknowledging an answer or handoff closes the relevant request lifecycle state.

Queue Inbox Check ​

http
POST /api/v1/agent-mail/members/{member_id}/queue-inbox-check

Requires either that member's authenticated Agent Mail session or an operator token. Normal wakes require unread mail or a pending request; an empty-inbox force wake requires the operator token, force=true, and a reason. Delivery targets one currently bound tmux pane or fails closed. Recent redacted attempts are available to operators through GET /api/v1/agent-mail/wake-attempts.

Set Session Wake Participation ​

http
PATCH /api/v1/agent-mail/sessions/{session_id}/wake-participation
X-Synth-City-Operator-Token: {operator_token}

This operator-only endpoint opts one session in or out of Agent Mail wake attempts:

json
{
  "wake_enabled": true,
  "reason": "operator_choice"
}

reason is required and must be a lowercase reason code (3–64 characters; letters, digits, and underscores). Other request fields are rejected. The response contains only session_id and wake_enabled. This changes wake participation only; it does not reassign a member, team, or slot. Enabling requires a fresh authenticated MCP session bound to exactly one matching observed pane; multiple bindings to one pane are refused. Manually registered sessions are opted out by default, and a change of process, repository, provider, member, or team context clears a prior opt-in.

Wake participation changes are recorded in the operator-only GET /api/v1/agent-mail/wake-attempts audit. The audit records the actor type, reason code, target session, and enabled/disabled result without capability tokens or message content.

Agent-Facing Endpoints ​

Agents normally call these through the bundled MCP server:

http
POST /api/v1/agent-mail/agent/register
GET /api/v1/agent-mail/agent/inbox?member_id={member_id}&unread_only=false
POST /api/v1/agent-mail/hooks/session-start
POST /api/v1/agent-mail/hooks/user-prompt-submit
POST /api/v1/agent-mail/hooks/post-tool-use
POST /api/v1/agent-mail/hooks/session-end
POST /api/v1/agent-mail/hooks/activity

Use the MCP tools from agent sessions instead of calling these directly unless you are debugging the integration.

Install Endpoints ​

http
GET /api/v1/agent-mail/install/status
GET /api/v1/agent-mail/install/snippets
POST /api/v1/agent-mail/install/claude-code/apply
POST /api/v1/agent-mail/install/claude-code/uninstall
POST /api/v1/agent-mail/install/codex/apply
POST /api/v1/agent-mail/install/codex/uninstall
POST /api/v1/agent-mail/install/copilot/apply
POST /api/v1/agent-mail/install/copilot/uninstall

Install and uninstall endpoints mutate real user configuration and create best-effort backups before changes.

External Local Orchestration ​

Trusted same-machine tools use the external Agent Mail prefix:

http
POST /api/v1/external/agent-mail/actors
GET /api/v1/external/agent-mail/members
POST /api/v1/external/agent-mail/messages
POST /api/v1/external/agent-mail/broadcasts
POST /api/v1/external/agent-mail/context-requests
POST /api/v1/external/agent-mail/handoffs
POST /api/v1/external/agent-mail/threads/{message_id}/replies
GET /api/v1/external/agent-mail/threads/{message_id}
GET /api/v1/external/agent-mail/requests/{message_id}/status
GET /api/v1/external/agent-mail/requests/{message_id}/wait
POST /api/v1/external/agent-mail/requests/{message_id}/ack

Actor creation is loopback-only. External endpoints require a bearer token and are intended for Albiex Synth City's local trust boundary, not internet-facing automation.

External broadcasts require audience_type and audience_id. Supported scoped audiences are team_preset (preset ID), repository (the repo_id from the members response), and work_item (GitHub work-item ID). For example:

json
{
  "audience_type": "repository",
  "audience_id": "repo-id-from-members-response",
  "subject": "Repository notice",
  "body_markdown": "For this repository only."
}

Receipt recipients are snapshotted when the message is stored. A keyed replay uses those receipts, not current membership. Existing messages retain their historical receipts and have no inferred audience.

Released under the MIT License.