Agent skill

Slack Agent-to-Agent Rooms

by nanocoai in nanocoai/nanoclaw

Lets two or more NanoClaw Slack bots and a human share a group DM, with an allowlist of rooms and a hop limit that stops bots looping on each other.

MITAuto-check: notesProductivity & Automation

Install Slack Agent-to-Agent Rooms

skills CLI
$ npx skills add nanocoai/nanoclaw --skill slack-a2a-rooms -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install nanocoai/nanoclaw slack-a2a-rooms --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/nanocoai/nanoclaw.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/slack-a2a-rooms .claude/skills/slack-a2a-rooms && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
slack-a2a-rooms
GitHub stars
31k
Token cost
~3k tokens
SKILL.md length
1,440 words
Files
4 (incl. scripts)
Skills in repo
59
Repo updated
First seen
Licence
MIT

At a glance

Lets two or more NanoClaw Slack bots and a human share a group DM, with an allowlist of rooms and a hop limit that stops bots looping on each other.

  • Works in 4 steps: Verify the installed Slack channel ships… → Copy the policy module, its guard test,… → Register the policy module → …
  • Putting several Slack-connected agents in one conversation with a person
  • SKILL.md covers Apply, Configuration, Engagement: A2A conversation… and Remove, plus 1 more section
  • Runs TypeScript scripts from its folder; calls pnpm; needs SLACK_BOT_TOKEN

What it does

By default NanoClaw's Slack bot-inbound guard drops every message written by another bot. This skill registers an admission policy on that guard so bot messages pass only in group DMs listed in SLACK_A2A_ROOMS, where they are attributed to a bot user ID and counted against a hop limit. Everywhere else the default drop still applies.

The loop guard counts consecutive bot messages in a room; after SLACK_A2A_MAX_HOPS of them, default 6, further bot messages are dropped until a human speaks, and any human message resets the count for that bot and room. The files include scripts/open-a2a-room.ts, which opens a room and registers it, plus src/channels/slack-a2a.ts and a test. It requires the Slack channel with the guard, at least two bot identities, and a bot token with the mpim:write scope.

When your agent uses it

  • Putting several Slack-connected agents in one conversation with a person
  • Letting a sibling bot's messages through in selected rooms only
  • Opening a new agent-to-agent room from a script

Example prompts

  • “Set up an agent-to-agent Slack room with me, the research bot and the writer bot.”
  • “Allow bot messages only in the rooms we open for agent collaboration, and cap the loop at 6 hops.”

Requirements

  • NanoClaw with the Slack channel and its bot-inbound guard installed
  • At least two Slack bot identities
  • A bot token with the mpim:write scope

Workflow steps

4 steps, taken from the step headings in SKILL.md.

  1. Verify the installed Slack channel ships the bot-inbound guard
  2. Copy the policy module, its guard test, and the room-opener script
  3. Register the policy module
  4. Build and validate

What it can do on your machine

Read from SKILL.md and the folder at commit a0c79dd. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Ships 1 file in scripts/ (TypeScript), which the agent can run.

    Shell commands in SKILL.md call:

    • pnpm

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md. Its commands use pnpm, which can reach the network depending on how they are called.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names these keys or tokens, usually read from environment variables:

    • SLACK_BOT_TOKEN

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Slack Agent-to-Agent Rooms loads about 3k tokens when it runs. Until then it costs about 119 tokens; SKILL.md has 1,440 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~119
When it runs · the whole SKILL.md, loaded when a task matches
~3k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check: notes

The automated check noted patterns worth knowing about, such as sudo or a known installer.

  • NoteMentions a .env fileSKILL.md:120
    `.env` keys (both re-read with a ~30s cache — no restart needed after edits):
  • NoteMentions a .env fileSKILL.md:139
    appends it to `SLACK_A2A_ROOMS` in `.env`. Without `--user` you get a
  • NoteMentions a .env fileSKILL.md:180
    2A_ROOMS` and `SLACK_A2A_MAX_HOPS` from `.env`.
  • NoteMentions a .env fileSKILL.md:214
    `.env` manually.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); the scripts in this folder are not scanned.

SKILL.md

The full file from nanocoai/nanoclaw at commit a0c79dd, republished under its MIT licence (© nanocoai). 1,440 words, ~2,958 tokens.

Download SKILL.mdSave it as .claude/skills/slack-a2a-rooms/SKILL.md (or your agent's skills folder). This skill also uses 3 other files; get the full folder from GitHub.
name
slack-a2a-rooms
description
Agent-to-agent Slack rooms — a group DM (MPIM) holding a human plus two or more NanoClaw sibling bots, where each bot hears the room over its own Socket Mode connection. Registers the admission policy on the Slack channel's bot-inbound guard so bot-authored inbound is admitted only for rooms allowlisted in SLACK_A2A_ROOMS (re-attributed as slack:bot:<bot_id>, hop-limited via SLACK_A2A_MAX_HOPS), plus scripts/open-a2a-room.ts to open a room and register it.

Slack agent-to-agent rooms (SLACK_A2A_ROOMS)

Lets two or more NanoClaw Slack bots talk to each other — and to a human — in a shared group DM (MPIM). Empirically established against live Slack: conversations.open with users=[<human>, <other bot user id>…] works from a bot token holding mpim:write and returns an is_mpim channel, and bots receive each other's messages over their own Socket Mode connections as plain message events with channel_type: "mpim", bot_id set, and subtype null.

Canonical home. This directory on main is the skill's canonical source — the setup wizard and any direct apply read it from the checkout. The copy on the channels branch is a compatibility mirror for older checkouts whose setup fetches companions from there; edits land here, never there.

Where sibling-bot messages die today. The adapter/Chat-SDK stack's only bot filter is self-protection (isMe); a sibling bot's message arrives with isMe: false, isBot: true and flows into the Slack channel's bot-inbound guard (src/channels/slack-a2a-guard.ts, installed with /add-slack), which drops all bot-authored inbound at the bridge boundary by default — before the router, before any sender-approval flow. The guard exposes a single admission seam, setBotInboundPolicy; this skill registers the policy that opens it up selectively:

  • Rooms listed in SLACK_A2A_ROOMS: bot-authored inbound passes, attributed to the user id slack:bot:<bot_id>, under a consecutive-hop limit.
  • Everywhere else: bot-authored inbound stays dropped at the bridge, exactly as the guard's default already does.

Loop safety. After N consecutive bot-authored inbound messages in an A2A room without a human message (N = SLACK_A2A_MAX_HOPS, default 6), further bot messages are dropped with a log line until a human speaks. The counter is per bot identity and per room; any human message resets it.

Requires:

  • The Slack channel installed (/add-slack), current enough to ship the bot-inbound guard (src/channels/slack-a2a-guard.ts with the setBotInboundPolicy seam). The default drop arrives with that payload; this skill only adds the allowlisted-room admission on top.
  • At least two Slack bot identities on this host (or sibling bots on other hosts sharing the workspace). Named identities are registered natively by the adapter from SLACK_INSTANCES — see the slack-multi-instance skill for the env-key format. scripts/open-a2a-room.ts reads tokens by that convention (SLACK_BOT_TOKEN_<NAME>; default → SLACK_BOT_TOKEN).
  • Every participating app's manifest must carry the MPIM scopes and event: mpim:write (open the room), mpim:history + mpim:read (see it), and the message.mpim bot event (hear it). Apps provisioned through the managed flow (apps.manifest.create + apps.managedInstall) already include all of these.

Apply

1. Verify the installed Slack channel ships the bot-inbound guard

The policy module copied next imports setBotInboundPolicy from the installed src/channels/slack-a2a-guard.ts. On a Slack payload that predates the guard, that import takes down the channel barrel — and with it every adapter — so verify the seam first. If the check fails, stop: re-run /add-slack from a channels branch that ships the guard, then re-apply this skill.

ncrun
grep -sq 'export function setBotInboundPolicy' src/channels/slack-a2a-guard.ts || { echo 'slack-a2a-rooms: src/channels/slack-a2a-guard.ts is missing or does not export setBotInboundPolicy. Installing anyway would break the channel barrel and take down every channel adapter. Update the installed Slack channel first (re-run /add-slack from a channels branch that ships the bot-inbound guard), then re-apply this skill.' >&2; exit 1; }
2. Copy the policy module, its guard test, and the room-opener script

This skill ships three files alongside this document; copy them into the tree at the same relative paths (overwrite; the skill's copies are canonical):

nccopy
src/channels/slack-a2a.ts
src/channels/slack-a2a.test.ts
scripts/open-a2a-room.ts
  • slack-a2a.ts — the admission policy: SLACK_A2A_ROOMS / SLACK_A2A_MAX_HOPS parsing (re-read with a ~30s cache so a freshly opened room needs no restart), the per-room, per-identity consecutive-hop counter with human reset, and the slack:bot:<bot_id> re-attribution. The module registers itself onto the guard's admission seam on import.
  • slack-a2a.test.ts — the guard: drives the real channel barrel and the real bot-inbound guard end-to-end (see step 4 for what it pins).
  • open-a2a-room.ts — operator CLI to open a room (see Configuration).
3. Register the policy module

Append the self-registration import to the channel barrel (skipped if the line is already present). Appending at the end keeps it after the Slack channel's own imports:

ncappend
import './slack-a2a.js';
4. Build and validate

Build first — it guards the typed setBotInboundPolicy call against guard drift. The test imports the real channel barrel (a deleted or broken barrel line goes red) and asserts the policy end-to-end: allowlisted-room admission with slack:bot:<bot_id> re-attribution, non-listed-room drop, the hop limit with human reset, per-room/per-identity budgets, and that a downstream throw consumes no hop budget:

ncrun
pnpm run build
ncrun
pnpm exec vitest run src/channels/slack-a2a.test.ts

Configuration

.env keys (both re-read with a ~30s cache — no restart needed after edits):

  • SLACK_A2A_ROOMS — comma-separated raw Slack channel ids (the MPIM ids the opener script prints, e.g. G0AAAAAAA — note MPIM ids may start with G or C depending on workspace vintage). Only these rooms admit bot-authored inbound.
  • SLACK_A2A_MAX_HOPS — consecutive bot-authored inbound messages allowed in an A2A room without a human message before further bot messages are dropped. Default 6.
Opening a room
bash
pnpm exec tsx scripts/open-a2a-room.ts --instances dana,eli --user U0AAAAAAA

The first listed instance opens the conversation (via conversations.open with the human + the other bots' user ids, resolved through auth.test per token) and posts an intro message. The script prints the channel id and appends it to SLACK_A2A_ROOMS in .env. Without --user you get a bots-only room, which needs at least three instances (Slack collapses a two-party open into a 1:1 IM).

Letting bot senders through the access gate

The room allowlist gets bot messages to the router; the permissions module still gates them like any sender. Bot senders arrive as user id slack:bot:<bot_id>, which starts unknown. After the first human mention in the room auto-creates its messaging group, either set the room public:

bash
pnpm exec tsx scripts/q.ts data/v2.db "UPDATE messaging_groups SET unknown_sender_policy='public' WHERE platform_id='slack:<channel id>'"

or keep request_approval and approve each slack:bot:<bot_id> sender once (or add them as members of the agent group). A private A2A room with known humans is a reasonable place for public.

Show full SKILL.md (566 more words)Show less

Engagement: A2A conversation is mention-driven

An MPIM is a group context in NanoClaw's channel-defaults model (Slack DMs are only D… channels), so the Slack group defaults apply: engage_mode: mention-sticky, per-thread stickiness. That means a bot replies when it is @-mentioned (then stays engaged in that thread) — it does not answer every room message. Bot-to-bot conversation is therefore mention-driven by design: bot A's reply reaches bot B's agent when it @-mentions bot B, and the chain continues only as long as each reply mentions the next speaker. Slack does not emit app_mention for bot-authored messages, but mention detection still works: the Chat SDK's text-level detector matches the bot's own <@U…> token, which the adapter deliberately leaves unresolved in the text. This is the intended loop governor alongside the hop limit — prompt the agents (group CLAUDE.md / personality) to @-mention the sibling they want an answer from, and to stop mentioning anyone when the exchange has converged.

Remove

  1. Delete the three copied files: src/channels/slack-a2a.ts, src/channels/slack-a2a.test.ts, scripts/open-a2a-room.ts.
  2. Delete the import './slack-a2a.js'; line from src/channels/index.ts.
  3. Remove SLACK_A2A_ROOMS and SLACK_A2A_MAX_HOPS from .env.
  4. Optionally re-tighten any messaging groups you set to unknown_sender_policy='public', and archive/leave the MPIMs from Slack (the rooms themselves are ordinary Slack conversations; NanoClaw holds no other state for them beyond the usual messaging-group/session rows).
  5. Rebuild (pnpm run build).

With the skill removed, the channel guard's default applies everywhere again: bot-authored inbound is dropped in every room.

Notes

  • Bot senders outside A2A rooms: the Slack channel's bot-inbound guard drops bot-authored messages in rooms not listed in SLACK_A2A_ROOMS at the bridge — before the router and before any sender-approval flow — with or without this skill applied. If an install relies on a bot sender (another workspace app posting into a channel the agent watches), add that room to SLACK_A2A_ROOMS. Human messages are never affected.
  • Access-gate story is manual. The recipe deliberately leaves letting slack:bot:<bot_id> senders through the gate as an operator step (public policy or per-bot approval). Should open-a2a-room.ts instead pre-create the messaging group + wirings + members via ncl so a room works with zero extra steps? That needs the host running and a choice of agent group per bot — deferred.
  • Hop-counter scope. The counter counts bot-authored inbound per bot identity (bridge instance). A bot's own outbound is invisible to it (isMe dropped upstream), so with two bots the effective conversation length is roughly 2×maxHops messages; with k bots each message increments k−1 counters. If per-room total (not per-identity) semantics are wanted, the counter needs to live host-side (router/session), not in the channel layer.
  • Cross-host rooms. For sibling bots on different NanoClaw hosts, each host needs this skill (its own allowlist entry). The opener script only handles co-hosted tokens; opening a cross-host room means running it where the first bot's token lives and adding the room id to the other host's .env manually.
  • message_changed / edited bot messages are not admitted (the adapter only forwards unfurl data for edits) — fine for v1.
  • Attribution name. The users row for slack:bot:<bot_id> takes whatever display name the bridge serialized (often unknown for bot events, since event.username is frequently absent and event.user is unset). A nicety would be resolving the bot's profile name via bots.info — deferred.
  • MPIM id prefix. Older workspaces mint MPIM ids starting with G, newer ones with C. The allowlist matches exact ids so both work, but the adapter's getChannelVisibility calls C… ids "workspace"-visible — cosmetic only, nothing here branches on it.

© nanocoai, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 3 other files (scripts) in .claude/skills/slack-a2a-rooms of nanocoai/nanoclaw.

  • SKILL.md
  • scripts/open-a2a-room.ts
  • src/channels/slack-a2a.test.ts
  • src/channels/slack-a2a.ts

Open the folder on GitHubat commit a0c79dd

Compare with similar skills

Slack Agent-to-Agent Rooms next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Slack Agent-to-Agent Rooms compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Slack Agent-to-Agent Rooms this skillnanocoai/nanoclaw31k—~3kAutomated safety check: NotesMIT
Slackhuangruiteng/CS-Notes4k10 repos~578Automated safety check: PassMIT
Openloomi Connectorsmelandlabs/openloomi1k—~3.3kAutomated safety check: PassApache-2.0
Use Avibeavibe-bot/avibe624—~2.5kAutomated safety check: PassMIT
Chat SDKdatabuddy-analytics/Databuddy1.2k—~2.6kAutomated safety check: PassAGPL-3.0
Agent Deep Linkscomposio-community/awesome-codex-skills17k—~513Automated safety check: PassNone

Similar skills

  • Slack

    huangruiteng/CS-Notes

    A skill your agent uses when you need to control Slack from Clawdbot via the slack tool, including reacting to messages or pinning/unpinning items in Slack channels or DMs.

    4k GitHub starsUsed in 10 repos~578 tokens
    Productivity & AutomationAuto-check passed
  • Openloomi Connectors

    melandlabs/openloomi

    openloomi Connectors tools - manage the native 7 messaging integrations and pair with the composio skill for the 1000+ apps OAuth layer (Slack, Discord, X, Gmail, Outlook, Google…

    1k GitHub stars~3.3k tokensUpdated 17 days ago
    Productivity & AutomationAuto-check passed
  • Use Avibe

    avibe-bot/avibe

    Safely inspect and modify local Avibe configuration, routing, runtime settings, watches, scheduled tasks, Avibe Cloud remote access, and operational state.

    624 GitHub stars~2.5k tokensUpdated today
    Productivity & AutomationAuto-check passed
  • Chat SDK

    databuddy-analytics/Databuddy

    Build multi-platform chat bots with Chat SDK (chat npm package).

    1.2k GitHub stars~2.6k tokensUpdated today
    Agent WorkflowsAuto-check passed
  • Agent Deep Links

    composio-community/awesome-codex-skills

    Builds and checks clickable deep links that open a thread, file, folder or settings panel in tools like Codex, Cursor and VS Code, usually for sharing in Slack.

    17k GitHub stars~513 tokensUpdated 2 mo ago
    Productivity & AutomationAuto-check passed
  • Drives the traul CLI to sync, search and monitor messages from Slack, Telegram, Discord, Linear, Gmail, WhatsApp, Claude Code sessions and Markdown files.

    112 GitHub stars~3.9k tokensUpdated 5 mo ago
    Productivity & AutomationAuto-check: notes

More from nanocoai/nanoclaw

All 59 skills in this repo
  • Installs or refreshes Iron Proxy and its Iron Control web console for NanoClaw, with a local Docker setup, database, credentials and a human approval bridge.

    31k GitHub stars~4.6k tokensUpdated today
    Auto-check: notes
  • Installs or refreshes OneCLI as the gateway provider for NanoClaw, copying the adapter files, registering the provider and running the setup script.

    31k GitHub stars~1.1k tokensUpdated today
    Auto-check: notes
  • Agent Browser

    nanocoai/nanoclaw

    Drives a web browser from the shell with the agent-browser CLI: open pages, read an element snapshot, click and fill by reference, grab text and screenshots.

    31k GitHub starsUsed in 2 repos~1.6k tokens
    Auto-check passed
  • Add Dial Tool

    nanocoai/nanoclaw

    Installs the `dial` CLI and a credential in NanoClaw agent containers so chosen agents can send SMS, place AI voice calls and receive verification codes.

    31k GitHub stars~4.8k tokensUpdated today
    Auto-check passed
  • Guides a conversational migration from an OpenClaw install to NanoClaw v2, carrying over identity, channel credentials, scheduled tasks and workspace files.

    31k GitHub stars~6k tokensUpdated today
    Auto-check: notes
  • Wires up an additional phone number onto an already-installed Dial channel, so one NanoClaw install answers SMS and AI voice calls on more than one line.

    31k GitHub stars~1.5k tokensUpdated today
    Auto-check passed

Works with

Questions about Slack Agent-to-Agent Rooms

What does Slack Agent-to-Agent Rooms do?

Lets two or more NanoClaw Slack bots and a human share a group DM, with an allowlist of rooms and a hop limit that stops bots looping on each other. By default NanoClaw's Slack bot-inbound guard drops every message written by another bot. This skill registers an admission policy on that guard so bot messages pass only in group DMs listed in SLACK_A2A_ROOMS, where they are attributed to a bot user ID and counted against a hop limit.

When should I use Slack Agent-to-Agent Rooms?

Slack Agent-to-Agent Rooms fits situations like: putting several Slack-connected agents in one conversation with a person; letting a sibling bot's messages through in selected rooms only; opening a new agent-to-agent room from a script.

How do I install Slack Agent-to-Agent Rooms in Claude Code?

Run `npx skills add nanocoai/nanoclaw --skill slack-a2a-rooms -a claude-code`. Or copy the skill folder (.claude/skills/slack-a2a-rooms in nanocoai/nanoclaw) into .claude/skills/slack-a2a-rooms in your project. Claude Code loads it when a task matches its description.

How do I install Slack Agent-to-Agent Rooms in Codex?

Run `npx skills add nanocoai/nanoclaw --skill slack-a2a-rooms -a codex`. Or copy the skill folder (.claude/skills/slack-a2a-rooms in nanocoai/nanoclaw) into .agents/skills/slack-a2a-rooms in your project. Codex loads it when a task matches its description.

Can I use Slack Agent-to-Agent Rooms in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add nanocoai/nanoclaw --skill slack-a2a-rooms -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/slack-a2a-rooms, .gemini/skills/slack-a2a-rooms, .github/skills/slack-a2a-rooms and .opencode/skills/slack-a2a-rooms in your project.

What does Slack Agent-to-Agent Rooms need to run?

Going by SKILL.md and its folder, Slack Agent-to-Agent Rooms needs TypeScript for the scripts in its folder, the command-line tools its instructions call (pnpm) and credentials named SLACK_BOT_TOKEN. Our summary lists: NanoClaw with the Slack channel and its bot-inbound guard installed; At least two Slack bot identities; A bot token with the mpim:write scope.

Does Slack Agent-to-Agent Rooms access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Slack Agent-to-Agent Rooms safe to install?

Our automated static check of SKILL.md found notes only (mentions a .env file), nothing it rates as a warning. It is not a guarantee. The check reads SKILL.md only: the scripts in the folder are not scanned, so read them before running anything.

What licence does Slack Agent-to-Agent Rooms use?

Slack Agent-to-Agent Rooms is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Slack Agent-to-Agent Rooms use?

About 3k tokens (SKILL.md is roughly 12k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Slack Agent-to-Agent Rooms?

Skills that share tags, products or a category with Slack Agent-to-Agent Rooms: Slack (huangruiteng/CS-Notes, 4k stars), Openloomi Connectors (melandlabs/openloomi, 1k stars), Use Avibe (avibe-bot/avibe, 624 stars) and Chat SDK (databuddy-analytics/Databuddy, 1.2k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Slack Agent-to-Agent Rooms?

nanocoai (a GitHub organization) maintains it in nanocoai/nanoclaw, which has 30,915 GitHub stars. The repository holds 59 skills in this directory. The repository was last updated on October 10, 2026.

Source: nanocoai/nanoclaw on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.