Merge branch 'main' into fix/imessage-groupish-threads

This commit is contained in:
Peter Steinberger
2026-01-09 17:16:44 +00:00
committed by GitHub
428 changed files with 26439 additions and 6160 deletions

View File

@@ -136,8 +136,8 @@ Example “single server, only allow me, only allow #help”:
Notes:
- `requireMention: true` means the bot only replies when mentioned (recommended for shared channels).
- `routing.groupChat.mentionPatterns` also count as mentions for guild messages.
- Multi-agent override: `routing.agents.<agentId>.mentionPatterns` takes precedence.
- `agents.list[].groupChat.mentionPatterns` (or `messages.groupChat.mentionPatterns`) also count as mentions for guild messages.
- Multi-agent override: set per-agent patterns on `agents.list[].groupChat.mentionPatterns`.
- If `channels` is present, any channel not listed is denied by default.
### 6) Verify it works

View File

@@ -93,8 +93,8 @@ DMs:
Groups:
- `imessage.groupPolicy = open | allowlist | disabled`.
- `imessage.groupAllowFrom` controls who can trigger in groups when `allowlist` is set.
- Mention gating uses `routing.groupChat.mentionPatterns` (iMessage has no native mention metadata).
- Multi-agent override: `routing.agents.<agentId>.mentionPatterns` takes precedence.
- Mention gating uses `agents.list[].groupChat.mentionPatterns` (or `messages.groupChat.mentionPatterns`) because iMessage has no native mention metadata.
- Multi-agent override: set per-agent patterns on `agents.list[].groupChat.mentionPatterns`.
## How it works (behavior)
- `imsg` streams message events; the gateway normalizes them into the shared provider envelope.
@@ -160,5 +160,5 @@ Provider options:
- `imessage.textChunkLimit`: outbound chunk size (chars).
Related global options:
- `routing.groupChat.mentionPatterns`.
- `agents.list[].groupChat.mentionPatterns` (or `messages.groupChat.mentionPatterns`).
- `messages.responsePrefix`.

440
docs/providers/msteams.md Normal file
View File

@@ -0,0 +1,440 @@
---
summary: "Microsoft Teams bot support status, capabilities, and configuration"
read_when:
- Working on MS Teams provider features
---
# Microsoft Teams (Bot Framework)
> "Abandon all hope, ye who enter here."
Updated: 2026-01-08
Status: text + DM attachments are supported; channel/group attachments require Microsoft Graph permissions. Polls are sent via Adaptive Cards.
## Goals
- Talk to Clawdbot via Teams DMs, group chats, or channels.
- Keep routing deterministic: replies always go back to the provider they arrived on.
- Default to safe channel behavior (mentions required unless configured otherwise).
## How it works
1. Create an **Azure Bot** (App ID + secret + tenant ID).
2. Build a **Teams app package** that references the bot and includes the RSC permissions below.
3. Upload/install the Teams app into a team (or personal scope for DMs).
4. Configure `msteams` in `~/.clawdbot/clawdbot.json` (or env vars) and start the gateway.
5. The gateway listens for Bot Framework webhook traffic on `/api/messages` by default.
## Azure Bot Setup (Prerequisites)
Before configuring Clawdbot, you need to create an Azure Bot resource.
### Step 1: Create Azure Bot
1. Go to [Create Azure Bot](https://portal.azure.com/#create/Microsoft.AzureBot)
2. Fill in the **Basics** tab:
| Field | Value |
|-------|-------|
| **Bot handle** | Your bot name, e.g., `clawdbot-msteams` (must be unique) |
| **Subscription** | Select your Azure subscription |
| **Resource group** | Create new or use existing |
| **Pricing tier** | **Free** for dev/testing |
| **Type of App** | **Single Tenant** (recommended - see note below) |
| **Creation type** | **Create new Microsoft App ID** |
> **Deprecation notice:** Creation of new multi-tenant bots was deprecated after 2025-07-31. Use **Single Tenant** for new bots.
3. Click **Review + create****Create** (wait ~1-2 minutes)
### Step 2: Get Credentials
1. Go to your Azure Bot resource → **Configuration**
2. Copy **Microsoft App ID** → this is your `appId`
3. Click **Manage Password** → go to the App Registration
4. Under **Certificates & secrets****New client secret** → copy the **Value** → this is your `appPassword`
5. Go to **Overview** → copy **Directory (tenant) ID** → this is your `tenantId`
### Step 3: Configure Messaging Endpoint
1. In Azure Bot → **Configuration**
2. Set **Messaging endpoint** to your webhook URL:
- Production: `https://your-domain.com/api/messages`
- Local dev: Use a tunnel (see [Local Development](#local-development-tunneling) below)
### Step 4: Enable Teams Channel
1. In Azure Bot → **Channels**
2. Click **Microsoft Teams** → Configure → Save
3. Accept the Terms of Service
## Local Development (Tunneling)
Teams can't reach `localhost`. Use a tunnel for local development:
**Option A: ngrok**
```bash
ngrok http 3978
# Copy the https URL, e.g., https://abc123.ngrok.io
# Set messaging endpoint to: https://abc123.ngrok.io/api/messages
```
**Option B: Tailscale Funnel**
```bash
tailscale funnel 3978
# Use your Tailscale funnel URL as the messaging endpoint
```
## Teams Developer Portal (Alternative)
Instead of manually creating a manifest ZIP, you can use the [Teams Developer Portal](https://dev.teams.microsoft.com/apps):
1. Click **+ New app**
2. Fill in basic info (name, description, developer info)
3. Go to **App features****Bot**
4. Select **Enter a bot ID manually** and paste your Azure Bot App ID
5. Check scopes: **Personal**, **Team**, **Group Chat**
6. Click **Distribute****Download app package**
7. In Teams: **Apps****Manage your apps****Upload a custom app** → select the ZIP
This is often easier than hand-editing JSON manifests.
## Testing the Bot
**Option A: Azure Web Chat (verify webhook first)**
1. In Azure Portal → your Azure Bot resource → **Test in Web Chat**
2. Send a message - you should see a response
3. This confirms your webhook endpoint works before Teams setup
**Option B: Teams (after app installation)**
1. Install the Teams app (sideload or org catalog)
2. Find the bot in Teams and send a DM
3. Check gateway logs for incoming activity
## Setup (minimal text-only)
1. **Bot registration**
- Create an Azure Bot (see above) and note:
- App ID
- Client secret (App password)
- Tenant ID (single-tenant)
2. **Teams app manifest**
- Include a `bot` entry with `botId = <App ID>`.
- Scopes: `personal`, `team`, `groupChat`.
- `supportsFiles: true` (required for personal scope file handling).
- Add RSC permissions (below).
- Create icons: `outline.png` (32x32) and `color.png` (192x192).
- Zip all three files together: `manifest.json`, `outline.png`, `color.png`.
3. **Configure Clawdbot**
```json
{
"msteams": {
"enabled": true,
"appId": "<APP_ID>",
"appPassword": "<APP_PASSWORD>",
"tenantId": "<TENANT_ID>",
"webhook": { "port": 3978, "path": "/api/messages" }
}
}
```
You can also use environment variables instead of config keys:
- `MSTEAMS_APP_ID`
- `MSTEAMS_APP_PASSWORD`
- `MSTEAMS_TENANT_ID`
4. **Bot endpoint**
- Set the Azure Bot Messaging Endpoint to:
- `https://<host>:3978/api/messages` (or your chosen path/port).
5. **Run the gateway**
- The Teams provider starts automatically when `msteams` config exists and credentials are set.
## Current Teams RSC Permissions (Manifest)
These are the **existing resourceSpecific permissions** in our Teams app manifest. They only apply inside the team/chat where the app is installed.
**For channels (team scope):**
- `ChannelMessage.Read.Group` (Application) - receive all channel messages without @mention
- `ChannelMessage.Send.Group` (Application)
- `Member.Read.Group` (Application)
- `Owner.Read.Group` (Application)
- `ChannelSettings.Read.Group` (Application)
- `TeamMember.Read.Group` (Application)
- `TeamSettings.Read.Group` (Application)
**For group chats:**
- `ChatMessage.Read.Chat` (Application) - receive all group chat messages without @mention
## Example Teams Manifest (redacted)
Minimal, valid example with the required fields. Replace IDs and URLs.
```json
{
"$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.23/MicrosoftTeams.schema.json",
"manifestVersion": "1.23",
"version": "1.0.0",
"id": "00000000-0000-0000-0000-000000000000",
"name": { "short": "Clawdbot" },
"developer": {
"name": "Your Org",
"websiteUrl": "https://example.com",
"privacyUrl": "https://example.com/privacy",
"termsOfUseUrl": "https://example.com/terms"
},
"description": { "short": "Clawdbot in Teams", "full": "Clawdbot in Teams" },
"icons": { "outline": "outline.png", "color": "color.png" },
"accentColor": "#5B6DEF",
"bots": [
{
"botId": "11111111-1111-1111-1111-111111111111",
"scopes": ["personal", "team", "groupChat"],
"isNotificationOnly": false,
"supportsCalling": false,
"supportsVideo": false,
"supportsFiles": true
}
],
"webApplicationInfo": {
"id": "11111111-1111-1111-1111-111111111111"
},
"authorization": {
"permissions": {
"resourceSpecific": [
{ "name": "ChannelMessage.Read.Group", "type": "Application" },
{ "name": "ChannelMessage.Send.Group", "type": "Application" },
{ "name": "Member.Read.Group", "type": "Application" },
{ "name": "Owner.Read.Group", "type": "Application" },
{ "name": "ChannelSettings.Read.Group", "type": "Application" },
{ "name": "TeamMember.Read.Group", "type": "Application" },
{ "name": "TeamSettings.Read.Group", "type": "Application" },
{ "name": "ChatMessage.Read.Chat", "type": "Application" }
]
}
}
}
```
### Manifest caveats (must-have fields)
- `bots[].botId` **must** match the Azure Bot App ID.
- `webApplicationInfo.id` **must** match the Azure Bot App ID.
- `bots[].scopes` must include the surfaces you plan to use (`personal`, `team`, `groupChat`).
- `bots[].supportsFiles: true` is required for file handling in personal scope.
- `authorization.permissions.resourceSpecific` must include channel read/send if you want channel traffic.
### Updating an existing app
To update an already-installed Teams app (e.g., to add RSC permissions):
1. Update your `manifest.json` with the new settings
2. **Increment the `version` field** (e.g., `1.0.0` → `1.1.0`)
3. **Re-zip** the manifest with icons (`manifest.json`, `outline.png`, `color.png`)
4. Upload the new zip:
- **Option A (Teams Admin Center):** Teams Admin Center → Teams apps → Manage apps → find your app → Upload new version
- **Option B (Sideload):** In Teams → Apps → Manage your apps → Upload a custom app
5. **For team channels:** Reinstall the app in each team for new permissions to take effect
6. **Fully quit and relaunch Teams** (not just close the window) to clear cached app metadata
## Capabilities: RSC only vs Graph
### With **Teams RSC only** (app installed, no Graph API permissions)
Works:
- Read channel message **text** content.
- Send channel message **text** content.
- Receive **personal (DM)** file attachments.
Does NOT work:
- Channel/group **image or file contents** (payload only includes HTML stub).
- Downloading attachments stored in SharePoint/OneDrive.
- Reading message history (beyond the live webhook event).
### With **Teams RSC + Microsoft Graph Application permissions**
Adds:
- Downloading hosted contents (images pasted into messages).
- Downloading file attachments stored in SharePoint/OneDrive.
- Reading channel/chat message history via Graph.
### RSC vs Graph API
| Capability | RSC Permissions | Graph API |
|------------|-----------------|-----------|
| **Real-time messages** | Yes (via webhook) | No (polling only) |
| **Historical messages** | No | Yes (can query history) |
| **Setup complexity** | App manifest only | Requires admin consent + token flow |
| **Works offline** | No (must be running) | Yes (query anytime) |
**Bottom line:** RSC is for real-time listening; Graph API is for historical access. For catching up on missed messages while offline, you need Graph API with `ChannelMessage.Read.All` (requires admin consent).
## Graph-enabled media + history (required for channels)
If you need images/files in **channels** or want to fetch **message history**, you must enable Microsoft Graph permissions and grant admin consent.
1. In Entra ID (Azure AD) **App Registration**, add Microsoft Graph **Application permissions**:
- `ChannelMessage.Read.All` (channel attachments + history)
- `Chat.Read.All` or `ChatMessage.Read.All` (group chats)
2. **Grant admin consent** for the tenant.
3. Bump the Teams app **manifest version**, re-upload, and **reinstall the app in Teams**.
4. **Fully quit and relaunch Teams** to clear cached app metadata.
## Known Limitations
### Webhook timeouts
Teams delivers messages via HTTP webhook. If processing takes too long (e.g., slow LLM responses), you may see:
- Gateway timeouts
- Teams retrying the message (causing duplicates)
- Dropped replies
Clawdbot handles this by returning quickly and sending replies proactively, but very slow responses may still cause issues.
### Formatting
Teams markdown is more limited than Slack or Discord:
- Basic formatting works: **bold**, *italic*, `code`, links
- Complex markdown (tables, nested lists) may not render correctly
- Adaptive Cards are used for polls; other card types are not yet supported
## Configuration
Key settings (see `/gateway/configuration` for shared provider patterns):
- `msteams.enabled`: enable/disable the provider.
- `msteams.appId`, `msteams.appPassword`, `msteams.tenantId`: bot credentials.
- `msteams.webhook.port` (default `3978`)
- `msteams.webhook.path` (default `/api/messages`)
- `msteams.dmPolicy`: `pairing | allowlist | open | disabled` (default: pairing)
- `msteams.allowFrom`: allowlist for DMs (AAD object IDs or UPNs).
- `msteams.textChunkLimit`: outbound text chunk size.
- `msteams.mediaAllowHosts`: allowlist for inbound attachment hosts (defaults to Microsoft/Teams domains).
- `msteams.requireMention`: require @mention in channels/groups (default true).
- `msteams.replyStyle`: `thread | top-level` (see [Reply Style](#reply-style-threads-vs-posts)).
- `msteams.teams.<teamId>.replyStyle`: per-team override.
- `msteams.teams.<teamId>.requireMention`: per-team override.
- `msteams.teams.<teamId>.channels.<conversationId>.replyStyle`: per-channel override.
- `msteams.teams.<teamId>.channels.<conversationId>.requireMention`: per-channel override.
## Routing & Sessions
- Direct messages use session key: `msteams:<userId>` (shared main session).
- Channel/group messages use session keys based on conversation id:
- `msteams:channel:<conversationId>`
- `msteams:group:<conversationId>`
## Reply Style: Threads vs Posts
Teams recently introduced two channel UI styles over the same underlying data model:
| Style | Description | Recommended `replyStyle` |
|-------|-------------|--------------------------|
| **Posts** (classic) | Messages appear as cards with threaded replies underneath | `thread` (default) |
| **Threads** (Slack-like) | Messages flow linearly, more like Slack | `top-level` |
**The problem:** The Teams API does not expose which UI style a channel uses. If you use the wrong `replyStyle`:
- `thread` in a Threads-style channel → replies appear nested awkwardly
- `top-level` in a Posts-style channel → replies appear as separate top-level posts instead of in-thread
**Solution:** Configure `replyStyle` per-channel based on how the channel is set up:
```json
{
"msteams": {
"replyStyle": "thread",
"teams": {
"19:abc...@thread.tacv2": {
"channels": {
"19:xyz...@thread.tacv2": {
"replyStyle": "top-level"
}
}
}
}
}
}
```
## Attachments & Images
**Current limitations:**
- **DMs:** Images and file attachments work via Teams bot file APIs.
- **Channels/groups:** Attachments live in M365 storage (SharePoint/OneDrive). The webhook payload only includes an HTML stub, not the actual file bytes. **Graph API permissions are required** to download channel attachments.
Without Graph permissions, channel messages with images will be received as text-only (the image content is not accessible to the bot).
By default, Clawdbot only downloads media from Microsoft/Teams hostnames. Override with `msteams.mediaAllowHosts` (use `["*"]` to allow any host).
## Polls (Adaptive Cards)
Clawdbot sends Teams polls as Adaptive Cards (there is no native Teams poll API).
- CLI: `clawdbot message poll --provider msteams --to conversation:<id> ...`
- Votes are recorded by the gateway in `~/.clawdbot/msteams-polls.json`.
- The gateway must stay online to record votes.
- Polls do not auto-post result summaries yet (inspect the store file if needed).
## Proactive messaging
- Proactive messages are only possible **after** a user has interacted, because we store conversation references at that point.
- See `/gateway/configuration` for `dmPolicy` and allowlist gating.
## Team and Channel IDs (Common Gotcha)
The `groupId` query parameter in Teams URLs is **NOT** the team ID used for configuration. Extract IDs from the URL path instead:
**Team URL:**
```
https://teams.microsoft.com/l/team/19%3ABk4j...%40thread.tacv2/conversations?groupId=...
└────────────────────────────┘
Team ID (URL-decode this)
```
**Channel URL:**
```
https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/ChannelName?groupId=...
└─────────────────────────┘
Channel ID (URL-decode this)
```
**For config:**
- Team ID = path segment after `/team/` (URL-decoded, e.g., `19:Bk4j...@thread.tacv2`)
- Channel ID = path segment after `/channel/` (URL-decoded)
- **Ignore** the `groupId` query parameter
## Private Channels
Bots have limited support in private channels:
| Feature | Standard Channels | Private Channels |
|---------|-------------------|------------------|
| Bot installation | Yes | Limited |
| Real-time messages (webhook) | Yes | May not work |
| RSC permissions | Yes | May behave differently |
| @mentions | Yes | If bot is accessible |
| Graph API history | Yes | Yes (with permissions) |
**Workarounds if private channels don't work:**
1. Use standard channels for bot interactions
2. Use DMs - users can always message the bot directly
3. Use Graph API for historical access (requires `ChannelMessage.Read.All`)
## Troubleshooting
### Common issues
- **Images not showing in channels:** Graph permissions or admin consent missing. Reinstall the Teams app and fully quit/reopen Teams.
- **No responses in channel:** mentions are required by default; set `msteams.requireMention=false` or configure per team/channel.
- **Version mismatch (Teams still shows old manifest):** remove + re-add the app and fully quit Teams to refresh.
- **401 Unauthorized from webhook:** Expected when testing manually without Azure JWT - means endpoint is reachable but auth failed. Use Azure Web Chat to test properly.
### Manifest upload errors
- **"Icon file cannot be empty":** The manifest references icon files that are 0 bytes. Create valid PNG icons (32x32 for `outline.png`, 192x192 for `color.png`).
- **"webApplicationInfo.Id already in use":** The app is still installed in another team/chat. Find and uninstall it first, or wait 5-10 minutes for propagation.
- **"Something went wrong" on upload:** Upload via https://admin.teams.microsoft.com instead, open browser DevTools (F12) → Network tab, and check the response body for the actual error.
- **Sideload failing:** Try "Upload an app to your org's app catalog" instead of "Upload a custom app" - this often bypasses sideload restrictions.
### RSC permissions not working
1. Verify `webApplicationInfo.id` matches your bot's App ID exactly
2. Re-upload the app and reinstall in the team/chat
3. Check if your org admin has blocked RSC permissions
4. Confirm you're using the right scope: `ChannelMessage.Read.Group` for teams, `ChatMessage.Read.Chat` for group chats
## References
- [Create Azure Bot](https://learn.microsoft.com/en-us/azure/bot-service/bot-service-quickstart-registration) - Azure Bot setup guide
- [Teams Developer Portal](https://dev.teams.microsoft.com/apps) - create/manage Teams apps
- [Teams app manifest schema](https://learn.microsoft.com/en-us/microsoftteams/platform/resources/schema/manifest-schema)
- [Receive channel messages with RSC](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/conversations/channel-messages-with-rsc)
- [RSC permissions reference](https://learn.microsoft.com/en-us/microsoftteams/platform/graph-api/rsc/resource-specific-consent)
- [Teams bot file handling](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/bots-filesv4) (channel/group requires Graph)
- [Proactive messaging](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/conversations/send-proactive-messages)

View File

@@ -92,6 +92,6 @@ Provider options:
- `signal.mediaMaxMb`: inbound/outbound media cap (MB).
Related global options:
- `routing.groupChat.mentionPatterns` (Signal does not support native mentions).
- Multi-agent override: `routing.agents.<agentId>.mentionPatterns` takes precedence.
- `agents.list[].groupChat.mentionPatterns` (Signal does not support native mentions).
- `messages.groupChat.mentionPatterns` (global fallback).
- `messages.responsePrefix`.

View File

@@ -248,8 +248,8 @@ Slack tool actions can be gated with `slack.actions.*`:
| emojiList | enabled | Custom emoji list |
## Notes
- Mention gating is controlled via `slack.channels` (set `requireMention` to `true`); `routing.groupChat.mentionPatterns` also count as mentions.
- Multi-agent override: `routing.agents.<agentId>.mentionPatterns` takes precedence.
- Mention gating is controlled via `slack.channels` (set `requireMention` to `true`); `agents.list[].groupChat.mentionPatterns` (or `messages.groupChat.mentionPatterns`) also count as mentions.
- Multi-agent override: set per-agent patterns on `agents.list[].groupChat.mentionPatterns`.
- Reaction notifications follow `slack.reactionNotifications` (use `reactionAllowlist` with mode `allowlist`).
- Bot-authored messages are ignored by default; enable via `slack.allowBots` or `slack.channels.<id>.allowBots`.
- For the Slack tool, reaction removal semantics are in [/tools/reactions](/tools/reactions).

View File

@@ -64,10 +64,10 @@ group messages, so use admin if you need full visibility.
## How it works (behavior)
- Inbound messages are normalized into the shared provider envelope with reply context and media placeholders.
- Group replies require a mention by default (native @mention or `routing.groupChat.mentionPatterns`).
- Multi-agent override: `routing.agents.<agentId>.mentionPatterns` takes precedence.
- Group replies require a mention by default (native @mention or `agents.list[].groupChat.mentionPatterns` / `messages.groupChat.mentionPatterns`).
- Multi-agent override: set per-agent patterns on `agents.list[].groupChat.mentionPatterns`.
- Replies always route back to the same Telegram chat.
- Long-polling uses grammY runner with per-chat sequencing; overall concurrency is capped by `agent.maxConcurrent`.
- Long-polling uses grammY runner with per-chat sequencing; overall concurrency is capped by `agents.defaults.maxConcurrent`.
## Formatting (Telegram HTML)
- Outbound Telegram text uses `parse_mode: "HTML"` (Telegrams supported tag subset).
@@ -81,7 +81,7 @@ group messages, so use admin if you need full visibility.
## Group activation modes
By default, the bot only responds to mentions in groups (`@botname` or patterns in `routing.groupChat.mentionPatterns`). To change this behavior:
By default, the bot only responds to mentions in groups (`@botname` or patterns in `agents.list[].groupChat.mentionPatterns`). To change this behavior:
### Via config (recommended)
@@ -280,7 +280,7 @@ Provider options:
- `telegram.actions.sendMessage`: gate Telegram tool message sends.
Related global options:
- `routing.groupChat.mentionPatterns` (mention gating patterns).
- `routing.agents.<agentId>.mentionPatterns` overrides for multi-agent setups.
- `agents.list[].groupChat.mentionPatterns` (mention gating patterns).
- `messages.groupChat.mentionPatterns` (global fallback).
- `commands.native`, `commands.text`, `commands.useAccessGroups` (command behavior).
- `messages.responsePrefix`, `messages.ackReaction`, `messages.ackReactionScope`.

View File

@@ -43,6 +43,7 @@ If you want pairing instead of allowlist, set `whatsapp.dmPolicy` to `pairing`.
### Personal number (fallback)
Quick fallback: run Clawdbot on **your own number**. Message yourself (WhatsApp “Message yourself”) for testing so you dont spam contacts. Expect to read verification codes on your main phone during setup and experiments. **Must enable self-chat mode.**
When the wizard asks for your personal WhatsApp number, enter the phone you will message from (the owner/sender), not the assistant number.
**Sample config (personal number, self-chat):**
```json
@@ -58,6 +59,9 @@ Quick fallback: run Clawdbot on **your own number**. Message yourself (WhatsApp
}
```
Tip: if you set the routed agents `identity.name`, you can omit
`messages.responsePrefix` and it will default to `[{identity.name}]`.
### Number sourcing tips
- **Local eSIM** from your country's mobile carrier (most reliable)
- Austria: [hot.at](https://www.hot.at)
@@ -147,7 +151,7 @@ Behavior:
## Limits
- Outbound text is chunked to `whatsapp.textChunkLimit` (default 4000).
- Media items are capped by `agent.mediaMaxMb` (default 5 MB).
- Media items are capped by `agents.defaults.mediaMaxMb` (default 5 MB).
## Outbound send (text + media)
- Uses active web listener; error if gateway not running.
@@ -163,13 +167,13 @@ Behavior:
## Media limits + optimization
- Default cap: 5 MB (per media item).
- Override: `agent.mediaMaxMb`.
- Override: `agents.defaults.mediaMaxMb`.
- Images are auto-optimized to JPEG under cap (resize + quality sweep).
- Oversize media => error; media reply falls back to text warning.
## Heartbeats
- **Gateway heartbeat** logs connection health (`web.heartbeatSeconds`, default 60s).
- **Agent heartbeat** is global (`agent.heartbeat.*`) and runs in the main session.
- **Agent heartbeat** is global (`agents.defaults.heartbeat.*`) and runs in the main session.
- Uses the configured heartbeat prompt (default: `Read HEARTBEAT.md if exists. Consider outstanding tasks. Checkup sometimes on your human during (user local) day time.`) + `HEARTBEAT_OK` skip behavior.
- Delivery defaults to the last used provider (or configured target).
@@ -188,16 +192,15 @@ Behavior:
- `whatsapp.groupPolicy` (group policy).
- `whatsapp.groups` (group allowlist + mention gating defaults; use `"*"` to allow all)
- `whatsapp.actions.reactions` (gate WhatsApp tool reactions).
- `routing.groupChat.mentionPatterns`
- Multi-agent override: `routing.agents.<agentId>.mentionPatterns` takes precedence.
- `routing.groupChat.historyLimit`
- `agents.list[].groupChat.mentionPatterns` (or `messages.groupChat.mentionPatterns`)
- `messages.groupChat.historyLimit`
- `messages.messagePrefix` (inbound prefix)
- `messages.responsePrefix` (outbound prefix)
- `agent.mediaMaxMb`
- `agent.heartbeat.every`
- `agent.heartbeat.model` (optional override)
- `agent.heartbeat.target`
- `agent.heartbeat.to`
- `agents.defaults.mediaMaxMb`
- `agents.defaults.heartbeat.every`
- `agents.defaults.heartbeat.model` (optional override)
- `agents.defaults.heartbeat.target`
- `agents.defaults.heartbeat.to`
- `session.*` (scope, idle, store, mainKey)
- `web.enabled` (disable provider startup when false)
- `web.heartbeatSeconds`