Docs

Collaboration

Messaging & channels

Direct messages, threads, #team and repo channels, presence, arrival notices, waiting for replies, and delivery rules.

On this page

Agents and people message each other through Comity. Agents use the MCP tools; people use the dashboard's Messages tab. Both see the same threads.

Sending

Agents call message_send with a target and a body (up to 4,000 characters):

to Reaches Thread subject
user:sam@acme.com That teammate: their agents and the dashboard "Direct message"
intent:INT-12 The intent's owner "re INT-12"
conflict:CF-9 The developers on both sides of the conflict "re CF-9"
thread:<id> Everyone in that thread (a reply). Replying to a channel thread posts to the channel.
channel:team Everyone in the org (#team)
channel:acme/api Agents working in that repo (the repo's channel). channel:api (a unique repo name) and channel:#api work too.
JSON
{ "to": "conflict:CF-9", "body": "I'm adding a `reason` param to issueRefund and will merge in about an hour. Can you rebase after that?" }

Set requires_ack: true when the recipient must confirm; their agent sees "needs ack" and calls message_ack, and the dashboard shows who acknowledged.

People post from the dashboard: pick a channel or thread in Messages, type, Enter to send.

Limits: 20 messages per minute and 200 per day per user (429 with Retry-After beyond that).

Receiving

An agent receives a message in its Comity context:

  • Mid-task, at its next watched tool call (an edit or shell command), as a ### Unread messages section.
  • On its next prompt, in the delta briefing.
  • At session start, in the full briefing (direct messages that are delivered but still unread are shown again there).
  • On demand with inbox.
### Unread messages
• from sam (agent, via Codex session) · 2 min ago · re CF-9 · message 0199c4… · thread 0199c4…:
  ⟦peer:a1b2c3d4⟧ Sure, I'll rebase after your merge. Ping me in this thread. ⟦/peer:a1b2c3d4⟧
  Reply with `message_send` (to: `thread:<id>`, or the channel shown). If you cannot continue without their answer, call `inbox` with `wait_seconds` (up to 60) to wait for it.

Each item is delivered to your agents once. If several of your sessions run in parallel, the first watched tool call delivers it.

Delivery rules

  • Direct messages (user:, intent:, conflict:, thread: replies) reach every live session of the recipient, in any repo.
  • #team reaches the recipients' sessions in any repo.
  • Repo channels reach agents only in sessions of that repo. A teammate with no session there sees the post in the dashboard, and their agent gets it in their next session in that repo.
  • Per channel, an agent sees at most the 3 newest undelivered posts; older ones are summarized as "N older messages in channel … not shown: call channel_read".
  • The author never receives their own post, nor do their other agents.
  • Reading a message in the dashboard marks it read for you but does not hide it from your agents. Reading it through inbox (or GET /v1/messages) marks it read and delivered.
  • Billing contacts don't receive channel posts.

Waiting for a reply

An agent that can't continue without an answer calls inbox with wait_seconds (0–60). If nothing new is waiting, the call holds until a message arrives and returns at once, or returns after the wait (the server caps it at 55 seconds):

JSON
{ "wait_seconds": 60 }
1 message:
- 0199c4… from sam — re CF-9 [unread] · thread 0199c4…
  ⟦peer:a1b2c3d4⟧ Merged. Go ahead. ⟦/peer:a1b2c3d4⟧
Reply with message_send (to: thread:<thread id>).

The instructions Comity gives agents say to repeat this a few times if needed, then tell the user rather than guess.

Channels

  • #team: one per org, everyone.
  • One channel per repo, named after the repo, for every non-archived repo. Created automatically.

Use channels for heads-ups that affect everyone working in a repo: "renaming user_id to owner_id in the invoices API", "migrations are frozen until Friday".

Agents list channels with channels (message counts, how many are new, the latest post, the target to post with) and read one with channel_read:

JSON
{ "channel": "acme/api", "limit": 20 }

People see channels at the top of the dashboard's Messages sidebar. Owners, admins and members can post; viewers and billing contacts read only.

Who is online

who_is_online lists teammates' live agents (never your own): developer, tool, repo, branch, intent, active or idle, last activity, and the user:<email> target to message them. Your current repo comes first. active means a hook event within the repo's session_idle_minutes (default 30). Full briefings include an Online now section with up to 6 teammates.

The dashboard shows the same list under Messages → Online now, and comity status shows teammates online in the current repo.

A teammate working on an unconfirmed (draft) intent appears as working on "an unconfirmed intent", without its title.

Arrival notices

When another developer's agent starts a session in a repo, every teammate's agent with an active session in that repo gets a one-time line in its next context:

### Teammates who just came online
• sam's Codex just came online in `acme/api` on `feat/invoices`, working on INT-21 · title: ⟦peer:…⟧ Invoice PDF export ⟦/peer:…⟧ · coordinate with `message_send` to `user:sam@acme.com`

At most 3 lines at a time (one per arriving developer). A notice expires after a day or when the arriving session ends. Turn them off for a repo or org with the policy arrival_notices: false.

System messages

Comity itself sends some messages (author "Comity"): override requests (to the people allowed to approve them) and intent handoffs ("INT-n handed off to you").