Skip to content

Commit f74a04e

Browse files
committed
fix: tighten telegram topic-agent docs + fallback tests (#33647) (thanks @kesor)
1 parent 8eeb049 commit f74a04e

File tree

3 files changed

+63
-3
lines changed

3 files changed

+63
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Docs: https://docs.openclaw.ai
1010
- Docs/Web search: remove outdated Brave free-tier wording and replace prescriptive AI ToS guidance with neutral compliance language in Brave setup docs. (#26860) Thanks @HenryLoenwind.
1111
- Tools/Diffs guidance loading: move diffs usage guidance from unconditional prompt-hook injection to the plugin companion skill path, reducing unrelated-turn prompt noise while keeping diffs tool behavior unchanged. (#32630) thanks @sircrumpet.
1212
- Agents/tool-result truncation: preserve important tail diagnostics by using head+tail truncation for oversized tool results while keeping configurable truncation options. (#20076) thanks @jlwestsr.
13+
- Telegram/topic agent routing: support per-topic `agentId` overrides in forum groups and DM topics so topics can route to dedicated agents with isolated sessions. (#33647) Thanks @kesor.
1314

1415
### Fixes
1516

docs/channels/telegram.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,8 @@ curl "https://api.telegram.org/bot<bot_token>/getUpdates"
444444
- message sends omit `message_thread_id` (Telegram rejects `sendMessage(...thread_id=1)`)
445445
- typing actions still include `message_thread_id`
446446

447-
Topic inheritance: topic entries inherit group settings unless overridden (`requireMention`, `allowFrom`, `skills`, `systemPrompt`, `enabled`, `groupPolicy`, `agentId`).
447+
Topic inheritance: topic entries inherit group settings unless overridden (`requireMention`, `allowFrom`, `skills`, `systemPrompt`, `enabled`, `groupPolicy`).
448+
`agentId` is topic-only and does not inherit from group defaults.
448449

449450
**Per-topic agent routing**: Each topic can route to a different agent by setting `agentId` in the topic config. This gives each topic its own isolated workspace, memory, and session. Example:
450451

@@ -773,7 +774,7 @@ Primary reference:
773774
- `channels.telegram.groups.<id>.allowFrom`: per-group sender allowlist override.
774775
- `channels.telegram.groups.<id>.systemPrompt`: extra system prompt for the group.
775776
- `channels.telegram.groups.<id>.enabled`: disable the group when `false`.
776-
- `channels.telegram.groups.<id>.topics.<threadId>.*`: per-topic overrides (same fields as group).
777+
- `channels.telegram.groups.<id>.topics.<threadId>.*`: per-topic overrides (group fields + topic-only `agentId`).
777778
- `channels.telegram.groups.<id>.topics.<threadId>.agentId`: route this topic to a specific agent (overrides group-level and binding routing).
778779
- `channels.telegram.groups.<id>.topics.<threadId>.groupPolicy`: per-topic override for groupPolicy (`open | allowlist | disabled`).
779780
- `channels.telegram.groups.<id>.topics.<threadId>.requireMention`: per-topic mention gating override.

src/telegram/bot-message-context.topic-agentid.test.ts

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,30 @@
1-
import { describe, expect, it } from "vitest";
1+
import { beforeEach, describe, expect, it, vi } from "vitest";
2+
import { loadConfig } from "../config/config.js";
23
import { buildTelegramMessageContextForTest } from "./bot-message-context.test-harness.js";
34

5+
const { defaultRouteConfig } = vi.hoisted(() => ({
6+
defaultRouteConfig: {
7+
agents: {
8+
list: [{ id: "main", default: true }, { id: "zu" }, { id: "q" }, { id: "support" }],
9+
},
10+
channels: { telegram: {} },
11+
messages: { groupChat: { mentionPatterns: [] } },
12+
},
13+
}));
14+
15+
vi.mock("../config/config.js", async (importOriginal) => {
16+
const actual = await importOriginal<typeof import("../config/config.js")>();
17+
return {
18+
...actual,
19+
loadConfig: vi.fn(() => defaultRouteConfig),
20+
};
21+
});
22+
423
describe("buildTelegramMessageContext per-topic agentId routing", () => {
24+
beforeEach(() => {
25+
vi.mocked(loadConfig).mockReturnValue(defaultRouteConfig as never);
26+
});
27+
528
it("uses group-level agent when no topic agentId is set", async () => {
629
const ctx = await buildTelegramMessageContextForTest({
730
message: {
@@ -120,6 +143,41 @@ describe("buildTelegramMessageContext per-topic agentId routing", () => {
120143
expect(ctx?.ctxPayload?.SessionKey).toContain("agent:main:");
121144
});
122145

146+
it("falls back to default agent when topic agentId does not exist", async () => {
147+
vi.mocked(loadConfig).mockReturnValue({
148+
agents: {
149+
list: [{ id: "main", default: true }, { id: "zu" }],
150+
},
151+
channels: { telegram: {} },
152+
messages: { groupChat: { mentionPatterns: [] } },
153+
} as never);
154+
155+
const ctx = await buildTelegramMessageContextForTest({
156+
message: {
157+
message_id: 1,
158+
chat: {
159+
id: -1001234567890,
160+
type: "supergroup",
161+
title: "Forum",
162+
is_forum: true,
163+
},
164+
date: 1700000000,
165+
text: "@bot hello",
166+
message_thread_id: 3,
167+
from: { id: 42, first_name: "Alice" },
168+
},
169+
options: { forceWasMentioned: true },
170+
resolveGroupActivation: () => true,
171+
resolveTelegramGroupConfig: () => ({
172+
groupConfig: { requireMention: false },
173+
topicConfig: { agentId: "ghost" },
174+
}),
175+
});
176+
177+
expect(ctx).not.toBeNull();
178+
expect(ctx?.ctxPayload?.SessionKey).toContain("agent:main:");
179+
});
180+
123181
it("routes DM topic to specific agent when agentId is set", async () => {
124182
const ctx = await buildTelegramMessageContextForTest({
125183
message: {

0 commit comments

Comments
 (0)