Telegram menu commands preserved via description trimming
A fix prevents custom skill commands from vanishing in Telegram's `/` menu when descriptions push the total payload over an undocumented API limit. Descriptions are now shortened first, keeping more commands visible.
Telegram bot menus now keep custom skill commands visible instead of silently dropping them.
The problem: Telegram's setMyCommands API enforces an undocumented ~5,750 character budget for the combined length of all command names and descriptions. When workspaces have many custom skills with lengthy descriptions, this budget gets exceeded even with fewer than 100 commands. The API then returns BOT_COMMANDS_TOO_MUCH, and OpenClaw's previous retry logic simply sliced off the last commands — typically custom workspace skills.
The fix changes the retry order. Instead of immediately dropping tail commands, the system now calculates the total character budget and progressively shortens descriptions to fit. Only when even minimal descriptions cannot fit does it resort to dropping commands.
This matters for users with many custom skills or plugins. Their commands remain visible in the / menu without manual intervention, while skills that do work via direct typing remain unaffected. The change sits in the Telegram extension and preserves the existing API retry fallback for unexpected rejections.
View Original GitHub Description
Summary
- Problem: Telegram menu registration only capped by command count and retried
BOT_COMMANDS_TOO_MUCHby dropping tail commands, even when the bot had fewer than 100 commands. - Why it matters: long skill/plugin/custom descriptions can silently push
setMyCommandsover Telegram's total payload budget and hide later commands from the/menu. - What changed: cap the menu at 100 entries, then fit that set into a conservative total text budget by shortening descriptions first and only dropping tail commands when even minimal descriptions cannot fit.
- What did NOT change (scope boundary): the existing retry-on-
BOT_COMMANDS_TOO_MUCHfallback remains in place for unexpected API-side rejections, and command ordering/handler registration semantics are unchanged.
Change Type (select all)
- Bug fix
- Feature
- Refactor required for the fix
- Docs
- Security hardening
- Chore/infra
Scope (select all touched areas)
- Gateway / orchestration
- Skills / tool execution
- Auth / tokens
- Memory / storage
- Integrations
- API / contracts
- UI / DX
- CI/CD / infra
Linked Issue/PR
- Closes #61060
- Related #61060
- This PR fixes a bug or regression
Root Cause (if applicable)
- Root cause:
extensions/telegram/src/bot-native-command-menu.tsonly enforced Telegram's 100-command count cap, whilesyncTelegramMenuCommands()handledBOT_COMMANDS_TOO_MUCHby repeatedly slicing the command list instead of first reducing description length. - Missing detection / guardrail: there was no preflight fit check for the total command-name-plus-description payload sent to
setMyCommands. - Contributing context (if known): skill descriptions can still be up to 100 chars, so a workspace with many visible commands can overflow Telegram's undocumented total menu budget even when the count is under 100.
Regression Test Plan (if applicable)
- Coverage level that should have caught this:
- Unit test
- Seam / integration test
- End-to-end test
- Existing coverage already sufficient
- Target test or file:
extensions/telegram/src/bot-native-command-menu.test.tsextensions/telegram/src/bot-native-commands.test.ts
- Scenario the test should lock in: keep sub-100 command sets visible by shortening long descriptions to fit the Telegram payload budget, and only drop tail commands when even minimally short descriptions cannot fit.
- Why this is the smallest reliable guardrail: it covers both the pure budgeting logic and the registration path that feeds
setMyCommandswithout needing live Telegram API calls. - Existing test that already covers this (if any): the existing
BOT_COMMANDS_TOO_MUCHretry tests still cover the API fallback path. - If no new test is added, why not: N/A
User-visible / Behavior Changes
- Telegram
/menus now keep more visible commands when the menu exceeds Telegram's total payload budget because descriptions are shortened before commands are dropped. - If command names alone still leave too little room, OpenClaw continues to drop tail commands, but only after trimming descriptions as far as possible.
Diagram (if applicable)
Before:
[build command menu] -> [under 100 commands but payload too large] -> [Telegram rejects] -> [drop tail commands]
After:
[build command menu] -> [under 100 commands but payload too large] -> [shorten descriptions] -> [register full set when possible]
Security Impact (required)
- New permissions/capabilities? (
Yes/No): No - Secrets/tokens handling changed? (
Yes/No): No - New/changed network calls? (
Yes/No): No - Command/tool execution surface changed? (
Yes/No): No - Data access scope changed? (
Yes/No): No - If any
Yes, explain risk + mitigation:
Repro + Verification
Environment
- OS: macOS 15.3
- Runtime/container: local Node/pnpm workspace
- Model/provider: N/A
- Integration/channel (if any): Telegram
- Relevant config (redacted):
channels.telegram.customCommandswith 92 commands and long descriptions
Steps
- Configure a Telegram bot with a command set below 100 entries but with long command descriptions.
- Start native Telegram command registration.
- Inspect the payload passed to
setMyCommands.
Expected
- Descriptions are shortened first so the full command set remains visible when it can fit within Telegram's total menu payload budget.
Actual
- Before this change, later commands were dropped once Telegram returned
BOT_COMMANDS_TOO_MUCH, even when shortening descriptions would have allowed the full set to register.
Evidence
- Failing test/log before + passing after
- Trace/log snippets
- Screenshot/recording
- Perf numbers (if relevant)
Human Verification (required)
- Verified scenarios:
pnpm test extensions/telegram/src/bot-native-command-menu.test.ts extensions/telegram/src/bot-native-commands.test.tspnpm build- confirmed the registration path keeps 92 long-description commands and logs the description-shortening path instead of dropping commands immediately
- Edge cases checked:
- payload fits after description trimming
- payload still cannot fit with one-character descriptions, so tail commands are dropped deterministically
- existing
BOT_COMMANDS_TOO_MUCHretry fallback still has coverage
- What you did not verify:
- live Telegram API registration
- full
pnpm checkis currently blocked on unrelated existingextensions/diffs/src/language-hints.test.tstype errors on the current base branch
Review Conversations
- I replied to or resolved every bot review conversation I addressed in this PR.
- I left unresolved only the conversations that still need reviewer or maintainer judgment.
Compatibility / Migration
- Backward compatible? (
Yes/No): Yes - Config/env changes? (
Yes/No): No - Migration needed? (
Yes/No): No - If yes, exact upgrade steps:
Risks and Mitigations
- Risk: the conservative text-budget constant may trim descriptions a little more than strictly necessary for some Telegram payloads.
- Mitigation: it preserves menu stability by fitting the full command set first and still leaves the existing API retry fallback in place.
Additional Notes
- AI assistance: cursor-assisted implementation and review.
- Testing level: build plus focused Telegram regression tests.
Made with Cursor