Clawq communicates with the outside world through channels --- modular communication backends that implement a common interface. Several integrations ship today, including chat channels such as Telegram, Discord, and Slack plus webhook-driven integrations such as GitHub and MS Teams.
Interrupting a running turn
In chat channels, prefix a message with ! to interrupt the
current turn for that same session and then send the rest as a normal
message. For example, !stop interrupts the in-flight turn and
sends stop next. A bare ! becomes
[interrupted].
If a shell_exec tool call is running when interrupted, the
process is moved to a background shell instead of being killed. Use
bg_shell_status, bg_shell_wait, and
bg_shell_result tools to track it.
The Channel.S Module Type
Every channel implements the Channel.S OCaml module signature:
module type S = sig
val name : string
val start :
config:Runtime_config.t ->
session_manager:Session.t ->
unit Lwt.t
end
The contract is intentionally narrow. A channel receives the global runtime
configuration and a session manager, then runs as a long-lived Lwt promise.
The daemon supervisor (daemon.ml) starts all enabled channels in parallel and
monitors them for failures.
Channel Overview
| Channel | Protocol | Transport | Status |
|---|---|---|---|
| Telegram | Bot API (long polling) | HTTPS | Implemented |
| Discord | Gateway v10 (WebSocket) | WSS + REST | Implemented |
| Slack | Socket Mode | WSS | Implemented |
| Slack (Events API) | HTTP push | HTTPS | Implemented |
| GitHub | Webhooks + API replies | HTTPS | Implemented |
| Web | HTTP gateway | REST | Implemented |
| CLI | stdin/stdout | Local | Implemented |
| MS Teams | Bot Framework webhook | HTTPS | Implemented |
| IRC | IRC protocol (RFC 2812) | TCP/TLS | Implemented |
| Matrix | Client-Server API | HTTPS | Implemented |
| Mattermost | WebSocket + REST | WSS + REST | Implemented |
| IMAP/SMTP | TCP/TLS | Implemented | |
| DingTalk | Stream Mode | HTTPS | Implemented |
| Lark/Feishu | Bot Event Callback | HTTPS | Implemented |
| LINE | Messaging API | HTTPS | Implemented |
| Nostr | NIP-01 relay + NIP-04 DMs | WSS | Implemented |
| OneBot | OneBot v11 | WS + HTTP | Implemented |
| Cloud API | HTTPS | Implemented | |
| iMessage | AppleScript + SQLite | Local | Implemented |
| Signal | signal-cli REST | HTTPS | Implemented |
Telegram
Telegram is the fastest channel to set up. Clawq connects via the Telegram Bot API using long polling --- no webhooks, no public IP required.
Configuration
{
"channels": {
"telegram": {
"accounts": {
"main": {
"bot_token": "123456:ABC-DEF...",
"allow_from": ["*"]
}
}
}
}
}
Or via the CLI:
clawq config set channels.telegram.accounts.main.bot_token "123456:ABC-DEF..."
clawq config set channels.telegram.accounts.main.allow_from '["*"]'
Setup
The fastest path is the interactive wizard:
clawq setup telegram
Or manually:
- Create a bot with @BotFather on Telegram.
- Copy the bot token into your config.
- Start the daemon with
clawq agent. - Send your bot a message to verify the connection.
Key Features
- Long polling with configurable timeout (default 30s) --- no inbound firewall rules needed.
- Rate limiting via the shared
Rate_limitertoken bucket. - Media support --- voice messages, photos, and documents are received
and routed to the agent. Voice messages are automatically transcribed
when an STT provider is configured: a “Transcribing…” progress message
is sent, updated to “Transcribing… Done!” on completion, and the
transcribed text is forwarded to the agent as
[Voice]: <text>. Validation enforces limits (under 25 MB, under 1 hour) and skips likely music files. - Token redaction --- bot tokens are automatically redacted in log output
via the
redact_tokenhelper. - Silent notifications --- messages are sent with notification disabled by default, so users are not constantly pinged by bot responses.
- Thinking format --- when
show_thinkingis enabled, thinking blocks are rendered as blockquote + italic (> _thinking..._) for a clean Telegram display.
How It Works
telegram.ml calls getUpdates in a loop, parsing each update into an
internal update record with chat ID, user ID, text, and optional media
fields. Each update is dispatched to the session manager, which routes it
to the appropriate agent session. Responses are sent back via
sendMessage.
Discord
Clawq connects to Discord using the Gateway v10 WebSocket protocol for receiving events and the REST API for sending messages. The implementation includes full connection lifecycle management: Hello, Identify, Heartbeat, Resume, and Reconnect.
Configuration
{
"channels": {
"discord": {
"enabled": true,
"bot_token": "MTIzNDU2Nzg5...",
"allow_guilds": ["*"],
"allow_users": ["*"]
}
}
}
Setup
The fastest path is the interactive wizard:
clawq setup discord
The wizard walks through setting the bot token, allowed guilds/users, and gateway intents. Or manually:
- Create a Discord application at the Discord Developer Portal.
- Add a Bot to the application and copy its token.
- Invite the bot to your server with the
applications.commandsandbotscopes, plusSend MessagesandRead Message Historypermissions. - Configure the token and start
clawq agent.
Key Features
- WebSocket gateway with automatic heartbeat, session resume, and reconnect on disconnect.
- Group chat filtering --- in guild channels, the bot only responds when explicitly @mentioned, addressed by name (e.g. “clawq, …”), or sent a slash command. DMs are always processed.
- Guild and user allowlists --- restrict which servers and users can interact with the bot.
- REST rate limit tracking --- server-driven rate limits are parsed from
response headers (
X-RateLimit-Remaining,X-RateLimit-Reset) with per-route bucket tracking and global rate limit handling. - Message chunking --- responses longer than 2000 characters are automatically split into multiple messages.
- Voice transcription --- audio attachments (
.ogg,.opus,.webm, etc.) are automatically transcribed via the configured STT provider. A “Transcribing…” progress message is sent and updated to “Transcribing… Done!” on completion. Music files are skipped unless the filename contains “voice” or “recording”. Size limit: 25 MB.
Architecture
The Discord channel is split across two modules:
discord_gateway.ml--- the Gateway protocol state machine. Manages the WebSocket connection, heartbeat loop, sequence tracking, identify/resume handshakes, and dispatch event routing.discord.ml--- the channel implementation. Handles message parsing, access control, REST API calls (with rate limit buckets), and session routing.
Both modules use the shared ws_client.ml WebSocket client, which provides
TLS connections with proper certificate verification via ca-certs.
Slack
Clawq supports two Slack integration modes: Socket Mode (recommended) and the Events API (requires a public endpoint).
Socket Mode (Recommended)
Socket Mode uses a WebSocket connection initiated by the bot, so no public URL is needed --- similar to Telegram’s long polling approach.
{
"channels": {
"slack": {
"enabled": true,
"mode": "socket",
"bot_token": "xoxb-...",
"app_token": "xapp-...",
"allow_channels": ["*"],
"allow_users": ["*"]
}
}
}
Setup:
Use the interactive wizard (clawq setup slack) or follow the manual steps:
- Create a Slack app at api.slack.com/apps.
- Enable Socket Mode in the app settings.
- Generate an App-Level Token (
xapp-...) with theconnections:writescope. - Install the app to your workspace and copy the Bot Token (
xoxb-...). - Subscribe to
message.channelsandmessage.imevents. - Configure both tokens and start
clawq agent.
slack_socket.ml calls apps.connections.open to obtain a WSS URL, then
connects and listens for envelope-wrapped events. Each envelope is acknowledged
by sending back the envelope_id, and the contained event is forwarded to
the standard Slack event parser.
Events API Mode
The Events API mode uses HTTP push --- Slack sends events to your gateway’s
/slack/events endpoint.
{
"channels": {
"slack": {
"enabled": true,
"mode": "events_api",
"bot_token": "xoxb-...",
"signing_secret": "abc123...",
"allow_channels": ["*"],
"allow_users": ["*"]
}
}
}
This mode requires a publicly reachable endpoint. The http_server.ml gateway
handles the /slack/events route, and slack.ml verifies every request using
HMAC-SHA256 signature verification with the signing secret and a 5-minute
timestamp window.
Key Features (Both Modes)
- Channel and user allowlists --- control which Slack channels and users can interact with the bot.
- HMAC signature verification (Events API) --- every incoming request is cryptographically verified.
- Envelope acknowledgement (Socket Mode) --- ensures Slack does not redeliver events.
- Voice transcription --- audio file attachments are automatically transcribed via the configured STT provider with progress messages. Music files are skipped; size limit: 25 MB.
GitHub
GitHub uses per-repo webhook endpoints on the clawq gateway. It supports both
the original /clawq comment flow for pull requests and a generalized hook
system for broader automation such as failed CI investigation.
Configuration
{
"channels": {
"github": {
"auth": {
"type": "pat",
"token": "ghp_..."
},
"repos": [
{
"name": "acme/backend",
"webhook_secret": "super-secret-value",
"webhook_path": "/github/webhook/backend",
"allow_users": ["octocat"],
"react_to": ["issue_comment", "pull_request", "workflow_job"],
"include_pr_files": true
}
]
}
}
}
Hook Files
Generalized automations are loaded from ~/.clawq/workspace/gh-hooks/.
---
name: investigate-ci-failure
repo: acme/backend
event: workflow_job
match:
status: completed
conclusion: failure
---
Investigate the failed CI job for {{repo}} on {{branch}}.
Payload snapshot: {{payload_path}}
Verified webhook deliveries are snapshotted under
~/.clawq/workspace/tmp/github-deliveries/, and old snapshots are cleaned up
opportunistically when new deliveries arrive.
Setup
Use the interactive wizard (clawq setup github) or follow the manual steps:
- Create a GitHub Personal Access Token and store it under
channels.github.auth.token. - Configure one repo entry per GitHub repository with a unique
webhook_path, awebhook_secret, and the canonicalowner/repoinname. - In GitHub, create a webhook pointing at your public clawq URL plus that
path, for example
https://your-host/github/webhook/backend. - Subscribe the webhook to the events you want clawq to process.
- Add any hook files to
~/.clawq/workspace/gh-hooks/and startclawq agent.
Session Keys
Each GitHub thread maps to a stable clawq session key so that follow-up
/clawq interactions resume the same conversation context:
| Thread surface | Session key format |
|---|---|
| PR event or comment on a PR | github:{owner}/{repo}:pr:{number} |
| Issue comment (non-PR) | github:{owner}/{repo}:issue:{number} |
| PR review comment | github:{owner}/{repo}:pr:{number} |
Review comments on the same PR share a session with the PR timeline, so the agent has full PR context regardless of which comment surface invoked it. Replies are routed back to the correct GitHub API surface: issue/PR comments use the Issues API, while review comments reply in-thread via the Pull Reviews API.
Comment/Reply Lifecycle
When a /clawq command is detected in a GitHub comment, clawq follows a
defined lifecycle to provide clear feedback:
- Acknowledge --- an “eyes” reaction is added to the triggering comment so the user knows the command was received.
- Placeholder --- a placeholder comment is posted with a spinner
(
> /clawq ...\n\n⏳ Working on it...) for issue and PR comments. Review comments skip this step since replies are threaded differently. - Process --- the webhook returns HTTP 200 immediately; the agent turn
runs asynchronously via
Lwt.async. - Finalize --- the placeholder comment is edited with the final response
(or a new comment/reply is posted if no placeholder exists). All bot
replies include a
<!-- clawq-reply -->marker. - Notify --- a channel notifier is registered for the session so that autonomous or deferred agent responses are posted to the same GitHub thread.
Bot self-loop protection: incoming comments containing the
<!-- clawq-reply --> marker are silently ignored, preventing the bot from
reacting to its own replies.
Delivery deduplication: the X-GitHub-Delivery header is tracked in an
in-memory LRU set (capacity 500). Duplicate deliveries are rejected before
any processing occurs.
Key Features
- Signature verification --- deliveries must pass GitHub HMAC validation
with the configured
webhook_secret. - Repo identity enforcement --- the payload repo must match the configured
channels.github.repos[].namefor that webhook path. - Unique webhook paths --- duplicate
webhook_pathbindings are rejected as ambiguous. - Stable sessions --- repeated
/clawqinteractions on the same issue or PR resume the same session context (see Session Keys above). - Async processing --- the webhook returns HTTP 200 immediately; agent processing happens asynchronously with acknowledgment, placeholder, and edit lifecycle (see Comment/Reply Lifecycle above).
- Delivery deduplication --- duplicate webhook deliveries are suppressed
via an in-memory LRU set keyed by the
X-GitHub-Deliveryheader. - Bot self-loop protection --- replies include an HTML comment marker; incoming comments with that marker are silently ignored.
- File-backed hooks --- non-comment events such as
workflow_jobcan route prompts into sessions using repo-scoped markdown hook files. - Trust gating ---
allow_usersgates arbitrary-content events such aspush; only a small system-event subset (workflow_job,workflow_run,check_run,check_suite,ping) bypasses that allowlist.
MS Teams
MS Teams uses the Microsoft Bot Framework webhook protocol. Teams POSTs activity JSON to your configured webhook path; clawq replies via the Bot Framework REST API using OAuth 2.0 bearer tokens.
What you'll need
- An Azure account with permission to register apps and create Bot resources
- A publicly reachable HTTPS URL for your clawq instance (use a tunnel — see below)
- About 20–30 minutes for Azure portal setup
How It Works
- Teams sends a POST to your webhook path with a JSON
Activitypayload. - clawq responds
202 Acceptedimmediately. - Asynchronously, clawq verifies JWT claims, extracts the message text
(stripping
<at>mention tags), looks up or creates a session keyed asteams:<team_id>:<conversation_id>, and runs the agent turn. Sessions are shared per-channel; sender identity is passed via context headers. - The reply is posted back via
{serviceUrl}/v3/conversations/{conversation_id}/activities/{activity_id}. In group chats, the bot only responds when explicitly @mentioned, addressed by name, or sent a slash command. When it does reply, the sender is @mentioned so they receive a notification.
Configuration
{
"channels": {
"teams": {
"app_id": "your-azure-app-id",
"app_secret": "your-azure-client-secret",
"tenant_id": "your-azure-tenant-id",
"webhook_path": "/teams/webhook",
"allow_teams": ["*"],
"allow_users": ["*"]
}
}
}
Setup
Use the interactive wizard (clawq setup teams) to configure the clawq-side credentials, then follow the Azure setup below.
Get your public HTTPS URL first
You need a publicly reachable HTTPS URL before entering anything into Azure. HTTP will be rejected. Start here before opening the Azure portal.
Step 0 — Get your public URL
Start clawq with a tunnel to obtain a stable HTTPS URL:
clawq config set tunnel.enabled true
clawq config set tunnel.provider cloudflare # or ngrok, tailscale
clawq agent
Note the tunnel URL printed at startup (e.g.
https://abc123.trycloudflare.com). Your Messaging Endpoint will be
https://abc123.trycloudflare.com/teams/webhook.
Step 1 — Register an Azure AD application
- Open Azure App registrations → New registration.
- Give it a name (e.g. “clawq-bot”). Leave redirect URIs blank. Register.
- Note the Application (client) ID — this is your
app_id. - Note the Directory (tenant) ID — this is your
tenant_id. - Go to Certificates & secrets → New client secret. Copy the secret
value immediately — it is only shown once. This is your
app_secret.
Client secret expiry
Azure client secrets expire after 12–24 months by default. Set a calendar
reminder to rotate it before expiry. When it expires, clawq will log
Teams: token fetch failed and outbound replies will stop.
Step 2 — Create an Azure Bot
- Open Azure Bot Service → Create.
- Set Messaging endpoint to your URL from Step 0:
https://your-tunnel-url/teams/webhook - Under Microsoft App ID, select Use existing app registration and enter the Application ID from Step 1.
- Finish creation. In the Bot resource, open the Channels blade and add Microsoft Teams.
Step 3 — Create a Teams App Manifest
This step is required. Without it, the bot is registered in Azure but completely invisible inside Teams — you will not be able to find or message it.
- Open the Teams Developer Portal → Apps → New app.
- Fill in the App name, description, and developer info.
- Under App features → Bot, click Enter a bot ID and enter your Application (client) ID from Step 1.
- Under Scope, check Personal and/or Team depending on use.
- Go to Publish → Publish to your org (or sideload for testing).
- If publishing to your org, an admin must approve the app in the Teams Admin Center.
- In Teams, go to Apps → search for your bot by name → Add. When installing to an org, searching by name is the easiest way to find your bot.
Step 4 — Configure clawq
clawq config set channels.teams.app_id "your-application-id"
clawq config set channels.teams.app_secret "your-client-secret"
clawq config set channels.teams.tenant_id "your-tenant-id"
Step 5 — Verify and start
clawq channel test teams # verifies OAuth credentials against Azure AD
clawq agent
clawq channel # confirm teams shows as configured
Common Mistakes
- Forgot the Teams App Manifest (Step 3): The bot will be registered in Azure but invisible in Teams. You cannot message a bot that has no Teams app.
- Using
http://instead ofhttps://: Azure rejects non-HTTPS endpoints. Always usehttps://for the Messaging Endpoint. - Entered the Messaging Endpoint before having a tunnel URL: Go back into the Azure Bot resource and update the Messaging Endpoint after you have your real URL.
- Copied
app_idinstead of the client secret intoapp_secret: The client secret is the value shown under Certificates & secrets, not the Application ID. - Client secret expired: Secrets expire. Rotate via Azure Portal → Certificates & secrets → New client secret.
Key Features
- JWT claim validation --- inbound requests carry a Bot Framework JWT;
clawq verifies
aud,iss,exp, andnbfclaims. RS256 signature verification is not performed (known limitation). - OAuth 2.0 outbound auth --- clawq fetches a client_credentials bearer token from Azure AD, cached with a 60 s safety margin before expiry.
- Message splitting --- replies longer than 28,672 characters are split at whitespace boundaries and sent as multiple activities.
- Async processing --- the webhook returns HTTP 202 immediately; agent processing happens asynchronously.
- Team and user allowlists --- restrict which Teams and users can interact
with the bot via
allow_teamsandallow_users. - Activity deduplication --- duplicate Bot Framework deliveries are suppressed via an in-memory LRU set.
- Group chat filtering --- in group conversations, the bot only responds when explicitly @mentioned, addressed by name (e.g. “clawq, …”), or sent a slash command. 1:1 chats always receive a response.
- @mention in group chats --- when the bot does respond in group conversations, it automatically @mentions the sender using Bot Framework mention entities, ensuring they receive a notification.
- Native markdown tables --- slash commands like
/status,/costs, and/usagerender with native markdown tables in Teams for clean formatting. - Voice transcription --- audio attachments are automatically transcribed via the configured STT provider with progress messages. Music files are skipped; size limit: 25 MB.
- Interactive menus --- menu subcommands (
/model menu,/thinking menu,/config menu,/skills,/costs menu,/bg menu) render as Adaptive Cards with clickable buttons on Teams. On other channels they render as text-formatted lists. Paginated menus show 9 items per page with nav buttons. - File uploads ---
/debug_dump_chatsends session state as a JSON file. In personal chats withfile_consent_cardsenabled, a file consent card is sent alongside a temporary download link as a fallback. In group chats (or when consent cards are disabled), only the download link is used (requirestunnel.url). If no public URL is configured, falls back to sending the first 25 KB as truncated text. - Notification suppression --- tool status messages (thinking indicators, tool call updates) do not trigger Teams notifications; only final replies do.
See the Microsoft Teams bot documentation and the Bot Framework authentication guide for full details.
Web Gateway
The HTTP gateway (http_server.ml) exposes a REST API and serves the embedded
web chat UI. It is always active when the daemon runs and also handles the Slack
Events API integration.
Endpoints
POST /chat
Send a message to the agent.
Body: { "message": "...", "session_key": "..." }
Headers: Authorization: Bearer <auth_token>
OR x-api-key: <auth_token>
When gateway.require_pairing is enabled, browser clients must first pair via
/pair. API clients with a valid auth_token bypass pairing entirely.
GET /chat/stream
SSE streaming endpoint. Emits events as the agent processes a turn:
| Event | Payload |
|---|---|
message | Text chunk from the model |
thinking | Model reasoning block (when thinking is enabled) |
tool_call | Tool invocation update |
done | Turn complete |
error | Error during the turn |
GET /health
Health check. Returns {"status":"ok"} when the daemon is running.
GET /commands
Returns slash command metadata used for autocomplete in the web UI.
GET /ui-version
Returns the current embedded UI version hash. The web UI polls this to detect when a reload is needed after a daemon update.
POST /pair
Browser pairing endpoint. Takes a 6-digit OTP code (shown by clawq otp-show)
and returns a session token on success.
Body: { "code": "123456" }
Returns: { "token": "..." }
GET /
Serves the embedded web chat UI.
Auth vs Pairing
There are two ways to authenticate with the gateway:
auth_token— a static bearer token configured ingateway.auth_token. Suitable for programmatic API access (scripts, integrations). Bypasses pairing.- Browser pairing — used by the web UI. The user obtains a 6-digit OTP via
clawq otp-showor a Telegram/paircommand, submits it toPOST /pair, and receives a session token valid for the configured pairing TTL.
Set gateway.require_pairing = true to require browser clients to pair before
chatting. This does not affect clients that provide a valid auth_token.
Matrix
Clawq connects to Matrix homeservers via the Client-Server API, using
long-polling /sync to receive events and the room send endpoint for replies.
Configuration
{
"channels": {
"matrix": {
"homeserver_url": "https://matrix.example.com",
"access_token": "syt_...",
"user_id": "@clawq:example.com",
"allow_rooms": ["*"],
"allow_users": ["*"]
}
}
}
Setup
clawq setup matrix
Or manually: create a Matrix account for your bot, generate an access token, and configure the homeserver URL and credentials.
Key Features
- Sync-based polling --- uses the
/syncendpoint with asincetoken for incremental event retrieval. - Room and user allowlists --- restrict which rooms and users can interact with the bot.
- Message editing --- supports editing previous messages in-place.
- Markdown rendering --- messages support standard Markdown formatting.
IRC
Clawq connects to IRC servers via raw TCP or TLS sockets, implementing the core IRC protocol (RFC 2812) for sending and receiving messages.
Configuration
{
"channels": {
"irc": {
"host": "irc.libera.chat",
"port": 6697,
"tls": true,
"nick": "clawq-bot",
"password": null,
"sasl": false,
"channels": ["#mychannel"],
"allow_from": ["*"]
}
}
}
Setup
clawq setup irc
Or manually: configure the IRC server host, port, TLS setting, bot nickname, and channel list.
Key Features
- TCP/TLS connections --- supports both plaintext and TLS-encrypted connections.
- SASL authentication --- optional SASL PLAIN authentication for registered nicks.
- PING/PONG keepalive --- responds to server PINGs to maintain the connection.
- Channel and DM support --- handles both channel messages and private messages.
- Message chunking --- responses are split at the 512-byte IRC message limit.
- User allowlist --- restrict which IRC users can trigger the bot.
Mattermost
Clawq connects to Mattermost servers using the WebSocket API for receiving events and the REST API v4 for sending messages.
Configuration
{
"channels": {
"mattermost": {
"url": "https://mattermost.example.com",
"access_token": "your-personal-access-token",
"team_id": "team-id-here",
"channel_ids": ["channel-id-1"],
"allow_users": ["*"]
}
}
}
Setup
clawq setup mattermost
Or manually: create a personal access token in Mattermost, find your team and channel IDs, and configure the connection.
Key Features
- WebSocket event stream --- real-time message delivery via the Mattermost WebSocket API.
- Markdown support --- responses are formatted with standard Markdown, which Mattermost renders natively.
- Message editing --- supports editing previous messages in-place.
- Channel and user allowlists --- restrict which channels and users the bot responds to.
Clawq monitors an email inbox via IMAP and replies via SMTP, enabling email-based agent interactions.
Configuration
{
"channels": {
"email": {
"imap_host": "imap.gmail.com",
"imap_port": 993,
"smtp_host": "smtp.gmail.com",
"smtp_port": 587,
"username": "bot@example.com",
"password": "app-password",
"from_address": "bot@example.com",
"allow_from": ["*"],
"poll_interval_s": 30.0
}
}
}
Setup
clawq setup email
Or manually: configure IMAP and SMTP credentials for the bot’s email account. For Gmail, use an App Password.
Key Features
- IMAP polling --- periodically checks for new messages with configurable poll interval.
- SMTP replies --- sends responses as email replies with proper threading
headers (
In-Reply-To,References). - Sender allowlist --- restrict which email addresses can trigger the bot.
- Subject threading --- replies preserve the email subject with
Re:prefix for clean threading in email clients.
DingTalk
Clawq connects to DingTalk (aka DingDing) using the Stream Mode protocol for receiving robot messages and the REST API for sending replies.
Configuration
{
"channels": {
"dingtalk": {
"app_key": "your-app-key",
"app_secret": "your-app-secret",
"agent_id": "your-agent-id",
"allow_from": ["*"],
"webhook_url": null
}
}
}
Setup
clawq setup dingtalk
Or manually: create a DingTalk robot in the developer console, enable Stream Mode, and configure the app credentials.
Key Features
- Stream Mode --- receives messages via the DingTalk stream protocol, no public URL required.
- Conversation replies --- sends replies to the originating conversation
using the
openConversationId. - Group and DM support --- handles both group chat and 1-on-1 conversations.
- User allowlist --- restrict which DingTalk users can interact with the bot.
Lark/Feishu
Clawq integrates with Lark (Feishu) using the Event Callback mechanism for receiving messages and the REST API for sending replies.
Configuration
{
"channels": {
"lark": {
"enabled": true,
"app_id": "cli_...",
"app_secret": "your-app-secret",
"verification_token": "your-verification-token",
"endpoint": "/lark/webhook",
"mode": "webhook",
"allow_users": ["*"]
}
}
}
Setup
clawq setup lark
Or manually: create a Lark app in the developer console, configure event subscriptions, and set the webhook URL to your clawq gateway endpoint.
Key Features
- Event callbacks --- receives messages via Lark’s event subscription system.
- Tenant access token --- authenticates API calls using auto-refreshed tenant tokens.
- Group and P2P support --- handles both group chat and peer-to-peer conversations.
- User allowlist --- restrict which Lark users can interact with the bot.
LINE
Clawq connects to LINE using the Messaging API with webhook-based event delivery and both reply and push message endpoints for responses.
Configuration
{
"channels": {
"line": {
"channel_access_token": "your-channel-access-token",
"channel_secret": "your-channel-secret",
"allow_from": ["*"]
}
}
}
Setup
clawq setup line
Or manually: create a LINE Messaging API channel in the LINE Developers Console, configure the webhook URL to your clawq gateway, and copy the channel access token and secret.
Key Features
- Webhook events --- receives messages via LINE’s webhook push mechanism.
- Reply tokens --- uses one-time reply tokens for immediate responses; falls back to push messages for delayed replies.
- Signature verification --- validates webhook payloads using HMAC-SHA256 with the channel secret.
- User allowlist --- restrict which LINE users can interact with the bot.
Nostr
Clawq connects to Nostr relays via WebSocket, using NIP-04 encrypted direct messages for private agent conversations.
Configuration
{
"channels": {
"nostr": {
"relays": ["wss://relay.damus.io", "wss://nos.lol"],
"private_key": "nsec1...",
"pubkey": "npub1...",
"nak_path": "/usr/local/bin/nak",
"allow_from": ["*"]
}
}
}
Setup
clawq setup nostr
Or manually: generate a Nostr keypair, configure relay URLs, and install the
nak CLI tool for event signing and encryption.
Key Features
- Multi-relay support --- connects to multiple relays simultaneously for redundancy.
- NIP-04 encrypted DMs --- messages are encrypted end-to-end using the NIP-04 standard.
- Event signing --- all outgoing events are signed with the bot’s private
key via the
naktool. - Subscription filters --- subscribes to DM events addressed to the bot’s public key.
- User allowlist --- restrict which Nostr pubkeys can interact with the bot.
OneBot
Clawq connects to QQ and other Chinese IM platforms via the OneBot v11 protocol, supporting both WebSocket and HTTP transports.
Configuration
{
"channels": {
"onebot": {
"ws_url": "ws://127.0.0.1:6700",
"http_url": "http://127.0.0.1:5700",
"access_token": null,
"allow_from": ["*"],
"allow_groups": ["*"]
}
}
}
Setup
clawq setup onebot
Or manually: install a OneBot-compatible bot framework (e.g., go-cqhttp, Lagrange), configure the WebSocket and HTTP endpoints, and optionally set an access token for authentication.
Key Features
- WebSocket event stream --- receives events via the OneBot v11 WebSocket forward connection.
- HTTP API --- sends messages via the OneBot HTTP API (
send_private_msg,send_group_msg). - Group and private chat --- handles both private messages and group conversations.
- Message recall --- supports deleting (recalling) messages via the API.
- User and group allowlists --- restrict which users and groups can interact with the bot.
Clawq integrates with WhatsApp using the Cloud API (Meta Business Platform) for sending and receiving messages.
Configuration
{
"channels": {
"whatsapp": {
"phone_number_id": "123456789",
"access_token": "EAAx...",
"verify_token": "my-verify-token",
"allow_from": ["*"]
}
}
}
Setup
clawq setup whatsapp
Or manually: create a WhatsApp Business app in the Meta Developer Portal, configure the webhook URL to your clawq gateway, set the verify token for the webhook handshake, and copy the access token.
Key Features
- Cloud API --- sends and receives messages through Meta’s WhatsApp Cloud API.
- Webhook verification --- handles the GET challenge/response handshake required by Meta.
- Webhook events --- receives incoming messages via POST webhook delivery.
- Phone number allowlist --- restrict which phone numbers can interact with the bot.
iMessage
Clawq integrates with iMessage on macOS using AppleScript for sending messages and SQLite for reading incoming messages from the Messages database.
Configuration
{
"channels": {
"imessage": {
"poll_interval_s": 2.0,
"allow_from": ["*"]
}
}
}
Setup
clawq setup imessage
This channel only works on macOS. Grant clawq Full Disk Access in System Preferences to allow reading the Messages SQLite database.
Key Features
- SQLite polling --- monitors
~/Library/Messages/chat.dbfor new incoming messages at a configurable poll interval. - AppleScript sending --- sends replies via
osascriptusing the Messages AppleScript interface. - Handle-based sessions --- each contact (phone number or email) maps to a stable session key.
- Contact allowlist --- restrict which iMessage handles can interact with the bot.
macOS only
This channel requires macOS with Full Disk Access permissions. It will not work on Linux or Windows.
Signal
Clawq connects to Signal via the signal-cli REST API, which runs as a separate service that bridges Signal’s protocol to HTTP.
Configuration
{
"channels": {
"signal": {
"base_url": "http://127.0.0.1:8080",
"account": "+1234567890",
"api_mode": "json-rpc",
"allow_from": ["*"],
"max_chunk_bytes": 6000
}
}
}
Setup
clawq setup signal
Or manually: install and configure signal-cli-rest-api, register or link a phone number, and point clawq at the REST API endpoint.
Key Features
- signal-cli REST bridge --- communicates with Signal through the signal-cli REST API service.
- Group and DM support --- handles both group messages and direct messages.
- Message chunking --- long responses are split at configurable byte
boundaries (
max_chunk_bytes). - Reactions --- supports sending emoji reactions to messages.
- Contact allowlist --- restrict which Signal numbers can interact with the bot.
Web Channel
The web channel provides a simple HTTP REST API for programmatic access to clawq sessions, separate from the main web gateway.
Configuration
{
"web_channel": {
"enabled": true,
"path_prefix": "/web",
"totp_secret": null,
"token_ttl_hours": 24
}
}
Setup
Enable the web channel in your config and optionally configure TOTP authentication. The channel is served by the main HTTP gateway.
Key Features
- REST API --- simple JSON request/response interface for sending messages and receiving replies.
- Session management --- supports custom session IDs for maintaining conversation context.
- Optional TOTP auth --- can require TOTP-based authentication for access.
- CORS support --- includes CORS headers for browser-based access.
Adding a New Channel
To add a new channel:
- Create a new module that satisfies
Channel.S. - Add the corresponding config type to
runtime_config.ml. - Wire it into
daemon.mlalongside the existing channels. - Place it in
clawq_runtime_integrations(not core) per the runtime split rules.
The narrow Channel.S interface means most of the work is in the
protocol-specific implementation --- the integration point with the rest of
clawq is minimal.