#20840: fix(message-tool): include other configured channels in tool description
agents
size: S
Cluster:
Message Tool Enhancements
## Summary
- **Problem:** `buildMessageToolDescription()` and `resolveMessageToolSchemaActions()` both return early when `currentChannel` is set, only listing that channel's actions. Cron and isolated agents inherit a default channel (e.g. Signal), so they can neither discover nor invoke actions from other configured channels.
- **Why it matters:** The description hides other channels from the LLM, and the schema enum rejects cross-channel actions at validation time. Agents that need to send messages cross-channel require hardcoded workarounds in every prompt.
- **What changed:** Both functions now include actions from all configured channel plugins when `currentChannel` is set. Updated existing schema scoping tests and added new description tests covering multi-channel and single-channel output.
- **What did NOT change (scope boundary):** No changes to tool execution, routing, permissions, or sandbox logic. `runMessageAction()` is untouched — it already routes to the correct channel at runtime via the `to`/`target` parameter.
## Change Type (select all)
- [x] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Docs
- [ ] Security hardening
- [ ] Chore/infra
## Scope (select all touched areas)
- [ ] Gateway / orchestration
- [x] Skills / tool execution
- [ ] Auth / tokens
- [ ] Memory / storage
- [ ] Integrations
- [ ] API / contracts
- [ ] UI / DX
- [ ] CI/CD / infra
## Linked Issue/PR
- Closes #20754
- Closes #20995
## User-visible / Behavior Changes
Tool description seen by the LLM changes from:
```
Send, delete, and manage messages via channel plugins. Current channel (signal) supports: react, send.
```
To:
```
Send, delete, and manage messages via channel plugins. Current channel (signal) supports: react, send. Other configured channels: telegram (delete, edit, react, send, topic-create), whatsapp (react, send).
```
Tool schema `action` enum now includes the union of all configured channels' actions instead of only the current channel's. This means cross-channel actions (e.g. `poll` from Discord when scoped to Telegram) pass validation and are routed correctly.
No changes to config, defaults, or CLI behavior.
## Security Impact (required)
- New permissions/capabilities? `No`
- Secrets/tokens handling changed? `No`
- New/changed network calls? `No`
- Command/tool execution surface changed? `No`
- Data access scope changed? `No` — the schema and description now accurately reflect channels the agent could already reach via `runMessageAction()`. No new access is granted; `currentChannel` was never a security boundary (the message tool is either fully enabled or disabled via `disableMessageTool`).
## Repro + Verification
### Environment
- OS: macOS (Darwin 25.3.0)
- Runtime/container: Node 22.16.0, pnpm 10.23.0
- Model/provider: N/A (description/schema change)
- Integration/channel (if any): N/A
- Relevant config (redacted): N/A
### Steps
1. Register two channel plugins (e.g. signal + telegram)
2. Create message tool with `currentChannelProvider: "signal"`
3. Inspect `tool.description` and `tool.parameters` action enum
### Expected
- Description includes both signal actions AND other configured channel actions.
- Schema action enum includes the union of all channels' actions.
### Actual
- Description only includes signal actions; other channels are invisible to the agent.
- Schema action enum only includes signal actions; cross-channel actions are rejected at validation.
## Evidence
- [x] Failing test/log before + passing after
New tests in `message-tool.e2e.test.ts`:
- `"includes other configured channels when currentChannel is set"` — verifies multi-channel description and schema
- `"does not include 'Other configured channels' when only one channel is configured"` — verifies single-channel deployments produce clean descriptions
Updated existing schema scoping tests to assert cross-channel actions are included. Full e2e suite: 13/13 passed. Unit suite: 748/748 passed, 6177/6177 tests.
## Human Verification (required)
- Verified scenarios: Built from source, ran `pnpm build && pnpm check && pnpm test:fast`, ran e2e tests for message-tool specifically.
- Edge cases checked: Single channel (no "Other configured channels" suffix), channels with no actions (skipped), `filterActionsForContext` still applies to current channel, execution routing via `runMessageAction()` unchanged.
- What I did **not** verify: Live gateway with real channel connections (no API keys configured).
## Compatibility / Migration
- Backward compatible? `Yes`
- Config/env changes? `No`
- Migration needed? `No`
## Failure Recovery (if this breaks)
- How to disable/revert this change quickly: Revert the single commit; both early returns are restored.
- Files/config to restore: `src/agents/tools/message-tool.ts`
- Known bad symptoms reviewers should watch for: Tool description becoming excessively long if many channels are configured (unlikely in single-user setups), or unexpected action validation passes (mitigated: `runMessageAction` still validates at execution time).
## Risks and Mitigations
- Risk: Description string grows longer with many configured channels, consuming more prompt tokens.
- Mitigation: OpenClaw is a single-user assistant — typical setups have 2–4 channels. The added text is minimal (one line per channel).
- Risk: Wider action enum could let the LLM attempt an action unsupported by a specific channel.
- Mitigation: `runMessageAction()` validates at execution time and returns clear errors. This matches the existing fallback behavior (no `currentChannel` path) which already exposes all actions.
## AI-Assisted Disclosure
This PR was reviewed and improved with assistance from Claude Code (Claude Opus 4.6). Specifically:
- **Code review**: Identified a stale comment on `message-tool.ts:542` that contradicted the new behavior, missing test cleanup (`afterEach`), and a gap in single-channel test coverage.
- **Fixes applied**: Updated the misleading comment, added `afterEach` registry cleanup to the description test block, and added a new test for single-channel deployments.
- **Manual verification**: Generated a throwaway script to verify multi-channel and single-channel tool description/schema output without requiring real channel connections.
All changes were human-reviewed before committing.
Most Similar PRs
#18940: Agents: expose message tool buttons schema in scoped contexts
by saurabhchopade · 2026-02-17
75.0%
#13584: tools: add description to message tool channel parameter
by carrotRakko · 2026-02-10
71.3%
#15626: Slack: add channel create for message tool
by imWildCat · 2026-02-13
70.5%
#20928: mattermost: add readMessages action for channel history
by hubertusgbecker · 2026-02-19
70.2%
#19102: Fix Telegram per-message link preview override
by Clawborn · 2026-02-17
69.6%
#21132: fix: allow message(action='read') in isolated/cron sessions + add H...
by matt-bedda · 2026-02-19
69.5%
#18893: fix(message): use currentMessageId for react fallback and suppress ...
by teededung · 2026-02-17
69.3%
#15864: feat: add deliverOnlyToolMessages config for clean messaging channe...
by gandalf-the-engineer · 2026-02-14
69.2%
#23226: fix(msteams): proactive messaging, EADDRINUSE fix, tool status, ada...
by TarogStar · 2026-02-22
68.3%
#9171: Fix: Route tool result deliveries through BlockReplyPipeline for pr...
by vishaltandale00 · 2026-02-04
68.1%