Social Channels
Broadcast / social-feed integrations. These differ from chat channels in two ways: messages are typically public, and the agent often acts as a poster rather than a bidirectional responder.
Build note: Social channels are not included in the lean default build. To use them, build with
--features channels-full(all channels) or the specific feature flag (e.g.--features channel-twitter). Prebuilt binaries do not include these channels by default. See Channels → Overview for the full build-options table.
Twitch
Twitch chat is a thin adapter over IRC. Build it with --features channel-twitch or include it through --features channels-full; the lean default build does not include it.
Configure enabled, bot_username, oauth_token, and the channels to join under a Twitch alias. mention_only is optional and defaults to false. A minimal instance looks like this:
[channels.twitch.default]
enabled = true
bot_username = "zeroclaw_bot"
oauth_token = "replace-with-twitch-token"
channels = ["zeroclaw_channel"]
mention_only = true
[peer_groups.twitch_default]
channel = "twitch.default"
external_peers = ["zeroclaw_user"]
- Auth: use a Twitch user access token for the bot account with
chat:readandchat:edit. After configuring the Twitch CLI, generate it while signed in as that account withtwitch token -u -s 'chat:read chat:edit', then store it through a protected config surface. ZeroClaw trims the value and adds the requiredoauth:prefix when it is omitted. - Channels: entries in
channelsmay include the leading#; ZeroClaw adds it when missing and normalizes channel names to lowercase. - Inbound and outbound: channel messages are answered in the same channel.
mention_only = trueignores channel messages that do not mentionbot_username. If Twitch delivers a non-channel IRCPRIVMSGto the bot login, ZeroClaw replies to that sender; the adapter does not configure a separate whisper transport. - Formatting: Twitch replies use plain text and are split to fit IRC frames. Markdown formatting is not preserved.
- Rate limits: the adapter writes IRC
PRIVMSGframes directly and has no Twitch-specific rate limiter or HTTP429backoff. Keep the agent’s posting cadence within Twitch Chat limits and throttle bursty workflows at their source.
Bluesky (AT Protocol)
Inbound senders are gated against the peer set resolved for the bound
agent, drawn from the peer_groups config the agent belongs to. Matching strips
a leading @ and is case-insensitive against the channel’s native sender
identifier. An empty set denies everyone; a set containing "*" accepts
anyone; otherwise only the listed external peers (and peer agents) are accepted.
This is separate from gateway pairing (gateway.require_pairing), which
authenticates HTTP/WebSocket clients, not chat-channel senders.
A peer group for bluesky sets channel to bluesky, lists the allowed senders in
external_peers (for bluesky, the sender’s handle or DID (a DID survives a handle rename); ["*"] accepts anyone), optionally
names peer agents for cross-agent dispatch, an ignore blocklist, and an
output_modality (mirror, voice, or text). See Peer Groups
for the field reference.
Where to set this:
Gateway dashboard
Open /config/peer_groups in the web dashboard.
zerocode
In the Config pane, under Peer groups.
- Auth: Bluesky app-password (not your real password). Create one in settings.
- Inbound:
mentionandreplynotifications, from peers only. - Outbound: 300-character posts; longer responses auto-thread.
- Protocol: AT Protocol via the
atrium-apicrate.
A peer entry may be either the handle or the DID. Prefer the DID if you want the entry to survive the account renaming itself.
Each poll walks the unread notifications to the end before delivering any of them, so a failure part-way through the walk delivers nothing and retries the whole range on the next poll. That trades a short delay for not re-delivering the pages that did arrive: a notification the agent has already answered is worse than one it answers five seconds late.
Nostr
Inbound senders are gated against the peer set resolved for the bound
agent, drawn from the peer_groups config the agent belongs to. Matching strips
a leading @ and is case-insensitive against the channel’s native sender
identifier. An empty set denies everyone; a set containing "*" accepts
anyone; otherwise only the listed external peers (and peer agents) are accepted.
This is separate from gateway pairing (gateway.require_pairing), which
authenticates HTTP/WebSocket clients, not chat-channel senders.
A peer group for nostr sets channel to nostr, lists the allowed senders in
external_peers (for nostr, the sender’s hex public key; ["*"] accepts anyone), optionally
names peer agents for cross-agent dispatch, an ignore blocklist, and an
output_modality (mirror, voice, or text). See Peer Groups
for the field reference.
Where to set this:
Gateway dashboard
Open /config/peer_groups in the web dashboard.
zerocode
In the Config pane, under Peer groups.
- Auth: raw private key (
nsecbech32 or hex). - Inbound: kind-1 (text), kind-4 (DM, NIP-04), and kind-1059 (gift-wrap, NIP-17).
- Outbound: same kinds. Zap handling is experimental.
- Relays: the agent connects to all listed relays; use 3–5 for reliability. If
relaysis omitted, ZeroClaw connects to a built-in set of popular public relays.
Twitter / X
Inbound senders are gated against the peer set resolved for the bound
agent, drawn from the peer_groups config the agent belongs to. Matching strips
a leading @ and is case-insensitive against the channel’s native sender
identifier. An empty set denies everyone; a set containing "*" accepts
anyone; otherwise only the listed external peers (and peer agents) are accepted.
This is separate from gateway pairing (gateway.require_pairing), which
authenticates HTTP/WebSocket clients, not chat-channel senders.
A peer group for twitter sets channel to twitter, lists the allowed senders in
external_peers (for twitter, the Twitter/X @username; ["*"] accepts anyone), optionally
names peer agents for cross-agent dispatch, an ignore blocklist, and an
output_modality (mirror, voice, or text). See Peer Groups
for the field reference.
Where to set this:
Gateway dashboard
Open /config/peer_groups in the web dashboard.
zerocode
In the Config pane, under Peer groups.
- Auth: Twitter API v2 OAuth 2.0 Bearer Token only.
- Inbound: mentions via the Filtered Stream endpoint.
- Outbound: posts, replies, threads.
- Caveat: the free tier is rate-limited to the point of near-uselessness. Budget accordingly.
Inbound senders are gated against the peer set resolved for the bound
agent, drawn from the peer_groups config the agent belongs to. Matching strips
a leading @ and is case-insensitive against the channel’s native sender
identifier. An empty set denies everyone; a set containing "*" accepts
anyone; otherwise only the listed external peers (and peer agents) are accepted.
This is separate from gateway pairing (gateway.require_pairing), which
authenticates HTTP/WebSocket clients, not chat-channel senders.
A peer group for reddit sets channel to reddit, lists the allowed senders in
external_peers (for reddit, the Reddit username without the u/ prefix (case-insensitive); ["*"] accepts anyone), optionally
names peer agents for cross-agent dispatch, an ignore blocklist, and an
output_modality (mirror, voice, or text). See Peer Groups
for the field reference.
Where to set this:
Gateway dashboard
Open /config/peer_groups in the web dashboard.
zerocode
In the Config pane, under Peer groups.
- Auth: OAuth 2.0 with a refresh token. Generate one with a script-type Reddit app and the
passwordorcodeflow. - Inbound: the unread inbox, which is mentions, comment replies and DMs. Every item must come from a peer.
- Outbound: posts, comments, private messages.
subreddits narrows where an item may come from; the peer set decides who
may send one. Both apply, and neither substitutes for the other. A DM carries no
subreddit, so subreddits cannot filter it and the peer set is the only gate.
Operating social channels safely
Bots on public social networks attract adversarial input. Two precautions:
- Restrict who the agent will respond to. Gate inbound senders with a peer group (per channel, above): an empty peer set denies everyone,
["*"]accepts anyone. This applies to every social channel, so an enabled channel with no peer group configured answers no one until you populate it. - Keep autonomy level at
Supervisedor lower. A public-facing agent inFullautonomy is effectively a public shell. For public-facing channels, restrict the tool surface in the global tool-policy config rather than expecting per-channeltools_allow(no such per-channel field exists).
Rate limits
Rate-limit handling differs by channel. Twitch writes IRC PRIVMSG frames directly and has no adapter-specific limiter. If you hit persistent rate-limiting, throttle the agent’s posting cadence at the source rather than relying on per-channel streaming knobs (none of these channels expose draft-update intervals; their schema is intentionally minimal).