fix: tighten telegram topic-agent docs + fallback tests (#33647) (thanks @kesor)

This commit is contained in:
Ayaan Zaidi
2026-03-04 09:34:42 +05:30
committed by Ayaan Zaidi
parent 8eeb049683
commit f74a04e4ba
3 changed files with 63 additions and 3 deletions

View File

@@ -10,6 +10,7 @@ Docs: https://docs.openclaw.ai
- 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.
- 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.
- 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.
- 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.
### Fixes

View File

@@ -444,7 +444,8 @@ curl "https://api.telegram.org/bot<bot_token>/getUpdates"
- message sends omit `message_thread_id` (Telegram rejects `sendMessage(...thread_id=1)`)
- typing actions still include `message_thread_id`
Topic inheritance: topic entries inherit group settings unless overridden (`requireMention`, `allowFrom`, `skills`, `systemPrompt`, `enabled`, `groupPolicy`, `agentId`).
Topic inheritance: topic entries inherit group settings unless overridden (`requireMention`, `allowFrom`, `skills`, `systemPrompt`, `enabled`, `groupPolicy`).
`agentId` is topic-only and does not inherit from group defaults.
**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:
@@ -773,7 +774,7 @@ Primary reference:
- `channels.telegram.groups.<id>.allowFrom`: per-group sender allowlist override.
- `channels.telegram.groups.<id>.systemPrompt`: extra system prompt for the group.
- `channels.telegram.groups.<id>.enabled`: disable the group when `false`.
- `channels.telegram.groups.<id>.topics.<threadId>.*`: per-topic overrides (same fields as group).
- `channels.telegram.groups.<id>.topics.<threadId>.*`: per-topic overrides (group fields + topic-only `agentId`).
- `channels.telegram.groups.<id>.topics.<threadId>.agentId`: route this topic to a specific agent (overrides group-level and binding routing).
- `channels.telegram.groups.<id>.topics.<threadId>.groupPolicy`: per-topic override for groupPolicy (`open | allowlist | disabled`).
- `channels.telegram.groups.<id>.topics.<threadId>.requireMention`: per-topic mention gating override.

View File

@@ -1,7 +1,30 @@
import { describe, expect, it } from "vitest";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { loadConfig } from "../config/config.js";
import { buildTelegramMessageContextForTest } from "./bot-message-context.test-harness.js";
const { defaultRouteConfig } = vi.hoisted(() => ({
defaultRouteConfig: {
agents: {
list: [{ id: "main", default: true }, { id: "zu" }, { id: "q" }, { id: "support" }],
},
channels: { telegram: {} },
messages: { groupChat: { mentionPatterns: [] } },
},
}));
vi.mock("../config/config.js", async (importOriginal) => {
const actual = await importOriginal<typeof import("../config/config.js")>();
return {
...actual,
loadConfig: vi.fn(() => defaultRouteConfig),
};
});
describe("buildTelegramMessageContext per-topic agentId routing", () => {
beforeEach(() => {
vi.mocked(loadConfig).mockReturnValue(defaultRouteConfig as never);
});
it("uses group-level agent when no topic agentId is set", async () => {
const ctx = await buildTelegramMessageContextForTest({
message: {
@@ -120,6 +143,41 @@ describe("buildTelegramMessageContext per-topic agentId routing", () => {
expect(ctx?.ctxPayload?.SessionKey).toContain("agent:main:");
});
it("falls back to default agent when topic agentId does not exist", async () => {
vi.mocked(loadConfig).mockReturnValue({
agents: {
list: [{ id: "main", default: true }, { id: "zu" }],
},
channels: { telegram: {} },
messages: { groupChat: { mentionPatterns: [] } },
} as never);
const ctx = await buildTelegramMessageContextForTest({
message: {
message_id: 1,
chat: {
id: -1001234567890,
type: "supergroup",
title: "Forum",
is_forum: true,
},
date: 1700000000,
text: "@bot hello",
message_thread_id: 3,
from: { id: 42, first_name: "Alice" },
},
options: { forceWasMentioned: true },
resolveGroupActivation: () => true,
resolveTelegramGroupConfig: () => ({
groupConfig: { requireMention: false },
topicConfig: { agentId: "ghost" },
}),
});
expect(ctx).not.toBeNull();
expect(ctx?.ctxPayload?.SessionKey).toContain("agent:main:");
});
it("routes DM topic to specific agent when agentId is set", async () => {
const ctx = await buildTelegramMessageContextForTest({
message: {