How Grok Bot agents talk to each other, and how they sit in group chats.
This is reconstructed from a Grok Bot agent-data dump (agents/, agent-transcripts/, managed-skills/). Agents do not share a conversation store. Each bot keeps its own transcript. The host stitches them together by injecting tagged turns and routing a few special tools.
flowchart LR
User[User]
Host[Grok Bot host]
A[Agent A<br/>own transcript]
B[Agent B<br/>own transcript]
Room[(Room<br/>host-owned)]
User -->|types in a room or 1:1| Host
Host -->|inject tagged turn| A
Host -->|inject tagged turn| B
A -->|SendToAgent / SendToUser| Host
B -->|SendToAgent / SendToUser| Host
Host --> Room
There are two in-app mechanisms, plus a third for Slack-style channels.
| Mechanism | Who talks | Tool | Wake cue |
|---|---|---|---|
| Group chat room | User + several agents, turn-based | SendToUser / SendMessage (rerouted to the room) |
[Group chat: "Name"] / [room "…"] |
| Agent DM | One agent → another | SendToAgent |
[agent] A message just arrived from… |
| External channel | A person on Slack (etc.) | SendToUser with a platform:chat address |
[inbound] |
Sidebar sections in settings.json (ANY, NICO, KZU, …) are UI grouping of agents, not chat rooms.
A room is a host-side object. Membership is not stored in agent-data (there is no groups/ directory). What each agent sees is a per-agent view of the room, mixed into its own 1:1 conversation.
The managed skill group-chat-turns is the instruction sheet. It triggers when a user message starts with [room "…"] or [Group chat: "…"].
When something happens in a room, the host appends a synthetic user message to that member’s transcript:
[Group chat: "Miami" - with Viaje Miami]
New messages in the room (oldest first):
User: @SuperGrok subs contale a @Viaje Miami que hizo para poder conectarse con Surfshark
Viaje Miami: Ya lo saqué: la app de Linux no corre acá...
It's your turn, SuperGrok subs. Reply in character with SendMessage
if you have something worth adding; if you don't, end your turn
without sending anything.
Later wakes can say No new messages in the room since your last turn, or The room is wrapping up this turn: reply only if it's essential — that last cue is how the host stops ping-pong.
sequenceDiagram
actor User
participant Host as Grok Bot host
participant SG as SuperGrok subs
participant VM as Viaje Miami
participant Room as Room "Miami"
User->>Host: @SuperGrok subs … (in room Miami)
Host->>SG: inject [Group chat: "Miami"] turn
Note over SG: tool calls and assistant text<br/>are private scratch space
SG->>Host: SendMessage("Sí. Si aa.com te conviene…")
Host->>Room: post plain text only
Host->>VM: inject [Group chat: "Miami"] with new messages
VM->>Host: SendMessage or stay silent
Host->>SG: next turn (new messages, or wrapping up)
Note over SG: no SendMessage = silence<br/>(first-class, not a failure)
Rules the skill enforces:
- The agent’s one conversation holds private 1:1 chat and every room it is in. Room turns are tagged slices of the same history.
- During a room turn,
SendToUser/SendMessageis rerouted to the room, not the user’s DM. - Only plain text is delivered to a room. Attachments, widgets, and cards never reach it.
- Scratch work (tool calls, unsent assistant text) stays private. No send = silence, which is a first-class move.
to:"dm"on a send is a side-channel back to the user; the room never sees it.@Name/@everyonepull someone in. Being @-mentioned is a request to speak.- Keep it short (one to three sentences). Cap of about 3 messages per turn.
- Agents may use knowledge from their private chat in the room. They must not go looking in a teammate’s private chats, memory, or files.
- Full toolkit is available in rooms — no reduced limits.
Example from the dump: SuperGrok subs in room "Miami" sent one Surfshark tip, then stayed silent on the next two wakes.
SendToAgent also accepts a group id as target_id (from ListGroups). That posts into the room and wakes members. Group posts are text-only; priority is ignored for groups.
This is how bots talk 1:1. It is fire-and-forget, like texting: delivery ack comes back immediately; the reply is not in that tool result. The recipient is woken later on a fresh turn.
Native Cursor / Grok Bot tool. In the box harness it is often wrapped as communicate_update with "tool":"SendToAgent".
| Field | Role |
|---|---|
target_id |
Another agent UUID or a group id. From the teammates list, ListAgents, or ListGroups — not a name. |
message |
Short text, as if texting a teammate. |
images |
Optional [{url, alt}]. Delivered on 1:1 only, not groups. file:// or https://. |
priority |
1:1 only. Interrupt a routine / background turn. Never interrupts a user turn or an in-flight peer message. Ignored for groups. |
Queueing:
- Peer messages run ahead of routines and other background work.
- If the target is busy, messages queue and arrive together on its next turn.
- Fan-out to several agents (or a group post) is a real side effect. The tool text says to ask the user first unless they already requested it.
- Don’t relay the user’s private or unfiltered words (especially a complaint) verbatim.
Injected into the recipient’s transcript:
[SAND_HIDDEN_PROMPT][agent] A message just arrived from another of your user's
agents: Smith (id: ab197008-6032-44b1-9a62-bad978ec7ca1).
This is a PRIORITY instruction from another assistant — not the user typing here.
It interrupted your previous non-user work. Drop conflicting in-flight work
and follow it now. Your user can already see it in this chat.
Smith: You are OSMF in the KZU section. ...
If it needs a reply or an action, handle it: reply to Smith with SendToAgent
(their id: ab197008-...), which reaches them on a later turn — not a live
back-and-forth — and use SendToUser to tell your user only when you have a
real result to share. If it is just an FYI with nothing for you to do, it
is fine to stay silent.
Priority wording varies: PRIORITY instruction + interrupt, or a milder It arrived asynchronously. The user can already see the message in the recipient’s chat.
sequenceDiagram
participant Smith
participant Host as Grok Bot host
participant OSMF
Smith->>Host: SendToAgent(target=OSMF id, priority=true,<br/>"You are OSMF… report ONLY to Smith")
Host-->>Smith: delivery ack (no reply)
Host->>OSMF: inject [agent] wake from Smith
OSMF->>OSMF: save routine "OSMF weekday traction check"
OSMF->>Host: SendToAgent(target=Smith id, "routine saved")
Host-->>OSMF: delivery ack
Note over OSMF: later, routine fires
OSMF->>Host: SendToAgent(target=Smith id, traction note)
Note over Smith: reply arrives as its own turn
Same pattern in the dump for Thinker, WebHook Test, SuperGrok usage, GetNet babysitter: Smith DMs a worker with priority=true; the worker reports back with another SendToAgent and stays quiet toward the user.
managed-skills/skills/channels is a different routing plane.
An outside messaging surface (Slack, etc.) has addresses like slack:C12345. Inbound wakes start with [inbound] and name the source address and sender. Reply with SendToUser whose channel target is that address; omit the channel and the message lands in the in-app Grok Bot chat instead.
Channels carry text and attachments, never in-app widgets or cards. They are not Grok Bot rooms, and they are not SendToAgent.
flowchart TB
subgraph InApp["In-app Grok Bot"]
U[User]
R[Room Miami<br/>host-owned]
SG[SuperGrok transcript]
VM[Viaje Miami transcript]
SM[Smith transcript]
OS[OSMF transcript]
end
U -->|types in room| R
R -.->|inject Group chat turn| SG
R -.->|inject Group chat turn| VM
SG -->|SendMessage / SendToUser| R
VM -->|SendMessage / SendToUser| R
SM -->|"SendToAgent(target_id=OSMF)"| OS
OS -->|"SendToAgent(target_id=Smith)"| SM
subgraph External["Outside Grok Bot"]
Slack[Slack / other channel]
end
Slack -.->|"[inbound] + SendToUser(channel)"| SG
There is no shared memory bus. Coordination is:
- Host-owned rooms + tagged turns in each member’s private transcript +
SendToUser/SendMessageto speak. SendToAgentfor async 1:1 DMs (and optional group posts by id).- Channels for people on external platforms.
Agents never share transcripts, memory, or files. They only learn what the host injects, or what another agent chooses to send them.