2026-01-03 05:07:45 +01:00
# Messaging Tools
2026-06-16 23:18:55 +02:00
There is **no** `roboco_message_*` , `roboco_notify_send` , or `roboco_session_*` tool. Messaging is a small set of **content tools** on the `roboco-do` MCP server. They are role-scoped at spawn time.
2026-06-05 17:20:36 +02:00
## Channel post — `say`
2026-01-03 05:07:45 +01:00
```python
2026-06-05 17:20:36 +02:00
say ( channel = "backend-cell" , text = "Starting work on rate limiting" , task_id = task_id )
2026-01-03 05:07:45 +01:00
```
2026-06-05 17:20:36 +02:00
- `channel` is the slug WITHOUT a leading `#` .
- `task_id` is auto-filled from your active task if omitted.
2026-06-16 23:18:55 +02:00
- Write access varies by role; the gateway returns `not_authorized` and lists the channels you *can* write to.
2026-06-05 17:20:36 +02:00
Don't invent channel slugs. Call `channels()` first if unsure:
2026-01-03 05:07:45 +01:00
```python
2026-06-05 17:20:36 +02:00
channels () # -> {"writable": [...], "readable": [...]}
2026-01-03 05:07:45 +01:00
```
2026-06-16 23:18:55 +02:00
Valid slugs: cell channels (`backend-cell` , `frontend-cell` , `uxui-cell` ); cross-cell (`dev-all` , `qa-all` , `pm-all` , `doc-all` ); management (`main-pm-board` , `board-private` ); broadcast (`announcements` , `all-hands` ).
2026-01-03 05:07:45 +01:00
2026-06-05 17:20:36 +02:00
## Direct message (A2A) — `dm`
2026-01-03 05:07:45 +01:00
```python
2026-06-05 17:20:36 +02:00
dm ( recipient = "be-qa" , text = "Quick sanity check: ..." , task_id = task_id )
2026-01-03 05:07:45 +01:00
```
2026-06-05 17:20:36 +02:00
- `recipient` is an agent slug (`be-pm` , `be-dev-1` , `ceo` , ...).
- Auto-creates the conversation; `task_id` auto-fills from your active task.
2026-06-16 23:18:55 +02:00
- Same-cell only. Cross-cell DM is denied by policy — route through your Cell PM via `escalate_up(task_id, reason)` .
2026-06-05 17:20:36 +02:00
## Formal notification — `notify` (PM / Board only)
2026-06-16 23:18:55 +02:00
`notify` creates an ack-required notification (distinct from the informal `say` /`dm` ). Only PM roles and the Board may send it; devs / QA / docs use `say` and `dm` .
2026-01-03 05:07:45 +01:00
```python
2026-06-05 17:20:36 +02:00
notify ( target = "be-dev-1" , text = "Task ready for you" , priority = "normal" , task_id = task_id )
2026-01-03 05:07:45 +01:00
```
2026-06-16 23:18:55 +02:00
`priority` is `normal | high | urgent` . `task_id` auto-injects from the active task when omitted.
2026-01-03 05:07:45 +01:00
2026-06-05 17:20:36 +02:00
## Receiving notifications
2026-01-03 05:07:45 +01:00
2026-06-16 23:18:55 +02:00
Every role with an inbox gets these (so `i_am_idle()` doesn't soft-block on unread items):
2026-01-03 05:07:45 +01:00
```python
2026-06-05 17:20:36 +02:00
notify_list ( unread_only = True , limit = 20 ) # your inbox
notify_get ( notification_id ) # read one (marks it read)
notify_ack ( notification_id ) # acknowledge after handling
2026-01-03 05:07:45 +01:00
```
2026-06-16 23:18:55 +02:00
When `i_am_idle()` reports unread A2A or @mentions , list -> get -> ack, then idle again. (The Auditor gets `notify_list` /`notify_get` for inbox visibility but does not ack.)
2026-01-03 05:07:45 +01:00
2026-06-05 17:20:36 +02:00
## Sessions (PM-or-up only)
2026-06-16 23:18:55 +02:00
Devs / QA / docs participate via channels and DMs and do **not** open sessions. PMs and the Board link discussion threads to tasks:
2026-06-05 17:20:36 +02:00
```python
open_session ( task_id , channel = "backend-cell" , topic = "Feature X kickoff" ,
relationship_type = "discussion" )
link_session ( session_id , task_id , is_primary = False )
```
2026-06-16 23:18:55 +02:00
`relationship_type` is `discussion | planning | review | retrospective` . `link_session` is idempotent; you must own the task you're linking.