Nextcloud Talk
Nextcloud Talk integration via the Talk Bot webhook protocol. Self-hosted, federated, and E2E-capable: another sovereign-communication option alongside Matrix and Mattermost.
Who can talk to the agent
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 nextcloud sets channel to nextcloud, lists the allowed senders in
external_peers (for nextcloud, the Nextcloud actor ID; ["*"] 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.
What this integration does
- Receives inbound Talk events via
POST /nextcloud-talkon the gateway - Verifies webhook signatures (HMAC-SHA256) when a secret is configured
- Sends replies back to Talk rooms via the Nextcloud OCS API
Prerequisites
- Nextcloud server with the Talk app enabled (v17 or later recommended)
- Bot account in Talk settings, give it a display name (e.g.
zeroclaw-bot) - Bot app token from the Talk admin UI for OCS API bearer auth (used for outbound replies)
- Webhook secret from the Talk admin UI if you want signature verification (strongly recommended)
- Publicly-reachable gateway: see Setup → Container for tunnel options if self-hosted
Configuration
app_token* 🔑
Bot app token used for OCS API bearer auth.
Set it on any surface:
Gateway dashboard
Open /config/channels/nextcloud_talk and set the channels.nextcloud_talk.<alias>.app_token field.
zerocode
In the Config pane, set the channels.nextcloud_talk.<alias>.app_token field.
zeroclaw config
zeroclaw config set channels.nextcloud_talk.<alias>.app_token # masked input, stored encrypted
Environment variable
Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:
export ZEROCLAW_channels__nextcloud_talk__<alias>__app_token=
base_url*
Nextcloud base URL (e.g. "https://cloud.example.com").
Set it on any surface:
Gateway dashboard
Open /config/channels/nextcloud_talk and set the channels.nextcloud_talk.<alias>.base_url field.
zerocode
In the Config pane, set the channels.nextcloud_talk.<alias>.base_url field.
zeroclaw config
zeroclaw config set channels.nextcloud_talk.<alias>.base_url <value>
Environment variable
Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:
export ZEROCLAW_channels__nextcloud_talk__<alias>__base_url=
bot_name
Display name of the bot in Nextcloud Talk (e.g. “zeroclaw”). Used to filter out the bot’s own messages and prevent feedback loops. If not set, defaults to an empty string (no self-message filtering by name).
Set it on any surface:
Gateway dashboard
Open /config/channels/nextcloud_talk and set the channels.nextcloud_talk.<alias>.bot_name field.
zerocode
In the Config pane, set the channels.nextcloud_talk.<alias>.bot_name field.
zeroclaw config
zeroclaw config set channels.nextcloud_talk.<alias>.bot_name <value>
Environment variable
Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:
export ZEROCLAW_channels__nextcloud_talk__<alias>__bot_name=
draft_update_interval_ms
Minimum interval in milliseconds between consecutive OCS edit calls per room when stream_mode = "partial". Default: 1000 ms.
Set it on any surface:
Gateway dashboard
Open /config/channels/nextcloud_talk and set the channels.nextcloud_talk.<alias>.draft_update_interval_ms field.
zerocode
In the Config pane, set the channels.nextcloud_talk.<alias>.draft_update_interval_ms field.
zeroclaw config
zeroclaw config set channels.nextcloud_talk.<alias>.draft_update_interval_ms <value>
Environment variable
Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:
export ZEROCLAW_channels__nextcloud_talk__<alias>__draft_update_interval_ms=
excluded_tools
Tools excluded from this channel’s tool spec. When set, these tools are not exposed to the model when responding via this channel.
Set it on any surface:
Gateway dashboard
Open /config/channels/nextcloud_talk and set the channels.nextcloud_talk.<alias>.excluded_tools field.
zerocode
In the Config pane, set the channels.nextcloud_talk.<alias>.excluded_tools field.
zeroclaw config
zeroclaw config set channels.nextcloud_talk.<alias>.excluded_tools <value>
Environment variable
Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:
export ZEROCLAW_channels__nextcloud_talk__<alias>__excluded_tools=
proxy_url
Per-channel proxy URL (http, https, socks5, socks5h). Overrides the global [proxy] setting for this channel only.
Set it on any surface:
Gateway dashboard
Open /config/channels/nextcloud_talk and set the channels.nextcloud_talk.<alias>.proxy_url field.
zerocode
In the Config pane, set the channels.nextcloud_talk.<alias>.proxy_url field.
zeroclaw config
zeroclaw config set channels.nextcloud_talk.<alias>.proxy_url <value>
Environment variable
Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:
export ZEROCLAW_channels__nextcloud_talk__<alias>__proxy_url=
stream_mode
Controls whether and how streaming draft updates are delivered. - "off" (default): responses are sent as a single final message. - "partial": a placeholder is posted first and edited incrementally as tokens arrive, making long responses visible in real time.
Set it on any surface:
Gateway dashboard
Open /config/channels/nextcloud_talk and set the channels.nextcloud_talk.<alias>.stream_mode field.
zerocode
In the Config pane, set the channels.nextcloud_talk.<alias>.stream_mode field.
zeroclaw config
zeroclaw config set channels.nextcloud_talk.<alias>.stream_mode <value>
Environment variable
Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:
export ZEROCLAW_channels__nextcloud_talk__<alias>__stream_mode=
webhook_secret 🔑
Shared secret for webhook signature verification. Can also be set via ZEROCLAW_NEXTCLOUD_TALK_WEBHOOK_SECRET.
Set it on any surface:
Gateway dashboard
Open /config/channels/nextcloud_talk and set the channels.nextcloud_talk.<alias>.webhook_secret field.
zerocode
In the Config pane, set the channels.nextcloud_talk.<alias>.webhook_secret field.
zeroclaw config
zeroclaw config set channels.nextcloud_talk.<alias>.webhook_secret # masked input, stored encrypted
Environment variable
Export the override (POSIX shells; drop into ~/.bashrc, ~/.zshrc, .env, or a Dockerfile). Replace <alias> with the literal alias:
export ZEROCLAW_channels__nextcloud_talk__<alias>__webhook_secret=
The channel is read from the default alias. Set it through any config surface:
Gateway dashboard
Open /config/channels/nextcloud_talk in the web dashboard.
zerocode
In the Config pane, under Channels.
webhook_secret can also be supplied at runtime via the generic env override ZEROCLAW_channels__nextcloud_talk__default__webhook_secret, useful for rotating it without editing the config.
Gateway endpoint
sh
zeroclaw daemon
Configure your Talk bot’s webhook URL to point at:
https://<your-public-url>/nextcloud-talk
Local development? Configure [tunnel] in your config (ngrok, Cloudflare, or Tailscale) and the gateway exposes itself on startup: see Operations → Network deployment.
Signature verification
When webhook_secret is set, inbound requests must carry:
X-Nextcloud-Talk-RandomheaderX-Nextcloud-Talk-Signatureheader
ZeroClaw verifies:
expected_sig = hex(hmac_sha256(secret, random + raw_request_body))
if X-Nextcloud-Talk-Signature != expected_sig:
return 401
Without a secret, no verification: don’t expose this endpoint publicly in that mode.
Message routing
- Bot-originated events (
actorType = "bots") are ignored: prevents feedback loops - System events (joins, leaves, membership changes) are ignored
- Non-message events are ignored
- User messages are dispatched to the agent loop
- Replies go back to the originating room via the
tokenin the webhook payload
Quick validation
- Set
external_peers = ["*"]in the peer group for first-time testing - Send a test message in the configured Talk room
- Confirm ZeroClaw receives and replies in the same room
- Tighten the peer group to explicit actor IDs (e.g.
["alice", "bob"])
Troubleshooting
404 Nextcloud Talk not configured:[channels.nextcloud_talk.default]section missing orenabled = false401 Invalid signature: secret mismatch, wrong random header, or body-signing bug. Check the raw body is being signed (not the parsed JSON)- No reply, webhook
200: event was filtered. Check logs for “actorType = bots” or a sender not in the peer set - Replies delivered but look wrong: check thread context; Talk replies are currently root-level only
Streaming
Nextcloud Talk does not support message edits via the Bot API, so streaming draft updates are disabled for this channel. Replies are sent on stream completion only.
Self-hosting notes
- TLS: terminate at your reverse proxy; webhook signature verification works over HTTP-to-container loopback
- The OCS API is authenticated via Bearer token: use the bot app token from the Talk admin UI
- Rate limits are Nextcloud-server dependent; the default bot doesn’t run into them in normal conversation cadences
- Per-channel proxy: set
proxy_urlto override the global[proxy]setting for Nextcloud Talk only (http://,https://,socks5://,socks5h://)
See also
- Matrix: richer E2EE but more operational complexity
- Mattermost: similar self-hosted posture, different protocol
- Channels → Overview