Skip to content

Instantly share code, notes, and snippets.

@kzu
Created September 14, 2026 21:02
Show Gist options
  • Select an option

  • Save kzu/fc624ee4e9d93b3715bd795d40b8c4a7 to your computer and use it in GitHub Desktop.

Select an option

Save kzu/fc624ee4e9d93b3715bd795d40b8c4a7 to your computer and use it in GitHub Desktop.
How Grok Bot agents talk to each other and sit in group chats (agent-to-agent / rooms / SendToAgent)

Agent-to-agent in Grok Bot

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
Loading

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.


1. Group 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: "…"].

Wake

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.

Routing during a room turn

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)
Loading

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 / SendMessage is 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 / @everyone pull 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.

How a bot posts into a room on its own

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.


2. Agent-to-agent DMs (SendToAgent)

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.

Tool

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.

Wake

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.

Example: Smith stands up OSMF

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
Loading

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.


3. What this is not: channels

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.


Mental model

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
Loading

There is no shared memory bus. Coordination is:

  1. Host-owned rooms + tagged turns in each member’s private transcript + SendToUser/SendMessage to speak.
  2. SendToAgent for async 1:1 DMs (and optional group posts by id).
  3. 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment