Summary
Telegram ACP configured bindings (bindings[] with type: "acp") only work for group chats and forum topics, not for direct messages (DMs). This prevents using persistent ACP sessions in Telegram DM conversations with dedicated agent bots.
Root Cause
In normalizeTelegramAcpConversationId(), the function explicitly rejects any chatId that does not start with "-" (i.e., group chat IDs):
function normalizeTelegramAcpConversationId(conversationId) {
const parsed = parseTelegramTopicConversation({ conversationId });
if (!parsed || !parsed.chatId.startsWith("-")) return null;
// ...
}
This means DM peer IDs (positive integers like 6689123501) are filtered out, and the binding is silently ignored.
Similarly, matchTelegramAcpConversation() checks incoming.chatId.startsWith("-"), which also rejects DM conversations.
Expected Behavior
A configured binding like this should work for Telegram DMs:
{
"type": "acp",
"agentId": "claude",
"match": {
"channel": "telegram",
"accountId": "claude",
"peer": { "kind": "direct", "id": "6689123501" }
},
"acp": { "mode": "persistent" }
}
When a user sends a message to the dedicated agent bot in DM, it should route through the ACP binding and create/resume an ACP harness session, just like it does for group topics.
Actual Behavior
- The binding passes
openclaw config validate ✅
- But at runtime,
normalizeTelegramAcpConversationId() returns null for DM peer IDs
- The binding is silently ignored
- Messages fall through to native embedded runtime instead of ACP harness
Use Case
We run dedicated Telegram bots for different ACP agents (Claude Code, Codex, etc.). Each bot has its own accountId. Users DM these bots expecting to interact with the actual ACP harness (e.g., Claude Code CLI). Without DM binding support, there is no way to persistently bind a Telegram DM conversation to an ACP session through config.
Currently, the only workaround is /acp spawn in a group topic, which defeats the purpose of having dedicated DM bots.
Additional Context
- Gateway restart can cause existing ACP session metadata to be lost from
sessions.json, making the DM → ACP routing even less reliable
agents.list[].runtime.type: "acp" does NOT automatically route DM messages through ACP — it only provides defaults for /acp spawn
- The
acpManager.resolveSession() check in agentCommandInternal() returns kind: "none" for DM sessions without .acp metadata, falling through to native embedded runtime
Environment
- OpenClaw version: latest (2026.4.5+)
- Channel: Telegram
- ACP backend: acpx (embedded)
Summary
Telegram ACP configured bindings (
bindings[]withtype: "acp") only work for group chats and forum topics, not for direct messages (DMs). This prevents using persistent ACP sessions in Telegram DM conversations with dedicated agent bots.Root Cause
In
normalizeTelegramAcpConversationId(), the function explicitly rejects anychatIdthat does not start with"-"(i.e., group chat IDs):This means DM peer IDs (positive integers like
6689123501) are filtered out, and the binding is silently ignored.Similarly,
matchTelegramAcpConversation()checksincoming.chatId.startsWith("-"), which also rejects DM conversations.Expected Behavior
A configured binding like this should work for Telegram DMs:
{ "type": "acp", "agentId": "claude", "match": { "channel": "telegram", "accountId": "claude", "peer": { "kind": "direct", "id": "6689123501" } }, "acp": { "mode": "persistent" } }When a user sends a message to the dedicated agent bot in DM, it should route through the ACP binding and create/resume an ACP harness session, just like it does for group topics.
Actual Behavior
openclaw config validate✅normalizeTelegramAcpConversationId()returnsnullfor DM peer IDsUse Case
We run dedicated Telegram bots for different ACP agents (Claude Code, Codex, etc.). Each bot has its own
accountId. Users DM these bots expecting to interact with the actual ACP harness (e.g., Claude Code CLI). Without DM binding support, there is no way to persistently bind a Telegram DM conversation to an ACP session through config.Currently, the only workaround is
/acp spawnin a group topic, which defeats the purpose of having dedicated DM bots.Additional Context
sessions.json, making the DM → ACP routing even less reliableagents.list[].runtime.type: "acp"does NOT automatically route DM messages through ACP — it only provides defaults for/acp spawnacpManager.resolveSession()check inagentCommandInternal()returnskind: "none"for DM sessions without.acpmetadata, falling through to native embedded runtimeEnvironment