From 0ebd9d6b22f829ebda1c14f9bff09d6b9f6e17cc Mon Sep 17 00:00:00 2001 From: Jiayuan Zhang Date: Fri, 13 Feb 2026 01:37:29 +0800 Subject: [PATCH] feat(agent): add connected channels section to system prompt Add ChannelInfo type and buildChannelsSection() that informs the LLM about connected messaging channels and their capabilities (e.g. send files). Wire through SystemPromptOptions and runner.ts. Co-Authored-By: Claude Opus 4.6 --- packages/core/src/agent/runner.ts | 1 + .../core/src/agent/system-prompt/builder.ts | 3 ++ .../core/src/agent/system-prompt/index.ts | 1 + .../core/src/agent/system-prompt/sections.ts | 35 +++++++++++++++++++ .../core/src/agent/system-prompt/types.ts | 10 ++++++ 5 files changed, 50 insertions(+) diff --git a/packages/core/src/agent/runner.ts b/packages/core/src/agent/runner.ts index 3e7c2f22..92ce68dd 100644 --- a/packages/core/src/agent/runner.ts +++ b/packages/core/src/agent/runner.ts @@ -1192,6 +1192,7 @@ export class Agent { tools: toolNames, skillsPrompt, runtime, + channels: this.toolsOptions.channels, }); } } diff --git a/packages/core/src/agent/system-prompt/builder.ts b/packages/core/src/agent/system-prompt/builder.ts index 82d01860..f7120d72 100644 --- a/packages/core/src/agent/system-prompt/builder.ts +++ b/packages/core/src/agent/system-prompt/builder.ts @@ -10,6 +10,7 @@ import type { SystemPromptReport, } from "./types.js"; import { + buildChannelsSection, buildHeartbeatSection, buildConditionalToolSections, buildExtraPromptSection, @@ -51,6 +52,7 @@ export function buildSystemPromptWithReport(options: SystemPromptOptions): { skillsPrompt, runtime, subagent, + channels, extraSystemPrompt, includeSafety = true, } = options; @@ -70,6 +72,7 @@ export function buildSystemPromptWithReport(options: SystemPromptOptions): { { name: "runtime", lines: buildRuntimeSection(runtime, mode) }, { name: "time-awareness", lines: buildTimeAwarenessSection(tools, mode) }, { name: "profile-dir", lines: buildProfileDirSection(profileDir, mode) }, + { name: "channels", lines: buildChannelsSection(channels, mode) }, { name: "subagent", lines: buildSubagentSection(subagent, mode) }, { name: "extra", lines: buildExtraPromptSection(extraSystemPrompt, mode) }, ]; diff --git a/packages/core/src/agent/system-prompt/index.ts b/packages/core/src/agent/system-prompt/index.ts index 6c1a9ffe..5944eb39 100644 --- a/packages/core/src/agent/system-prompt/index.ts +++ b/packages/core/src/agent/system-prompt/index.ts @@ -8,6 +8,7 @@ export { formatPromptReport } from "./report.js"; export { SAFETY_CONSTITUTION } from "./constitution.js"; export type { + ChannelInfo, ProfileContent, PromptSection, RuntimeInfo, diff --git a/packages/core/src/agent/system-prompt/sections.ts b/packages/core/src/agent/system-prompt/sections.ts index 99573cbd..60caee95 100644 --- a/packages/core/src/agent/system-prompt/sections.ts +++ b/packages/core/src/agent/system-prompt/sections.ts @@ -8,6 +8,7 @@ import { SAFETY_CONSTITUTION } from "./constitution.js"; import { formatRuntimeLine } from "./runtime-info.js"; import { resolveHeartbeatPrompt } from "../../heartbeat/heartbeat-text.js"; import type { + ChannelInfo, ProfileContent, RuntimeInfo, SubagentContext, @@ -461,6 +462,40 @@ export function buildSubagentSection( return lines; } +/** + * Connected channels section — tells the agent which messaging channels are active + * and what capabilities they have (e.g. send files). Full mode only. + */ +export function buildChannelsSection( + channels: ChannelInfo[] | undefined, + mode: SystemPromptMode, +): string[] { + if (mode !== "full" || !channels || channels.length === 0) return []; + + const lines: string[] = ["## Connected Channels", ""]; + + for (const ch of channels) { + lines.push(`- **${ch.name}**`); + if (ch.canSendMedia) { + lines.push( + " Capabilities: receive text/voice/image/video/document, send text, send files (photo, document, video, audio)", + ); + lines.push(" Use the `send_file` tool to send files to channel users."); + } else { + lines.push(" Capabilities: receive text, send text"); + } + } + + lines.push( + "", + "Messages from channels are prefixed with `[ChannelName · private]` or `[ChannelName · group]`.", + "When responding to channel messages, adapt your formatting for messaging platforms (shorter paragraphs, no complex markdown).", + "", + ); + + return lines; +} + /** * Extra system prompt — appended at the end if provided. */ diff --git a/packages/core/src/agent/system-prompt/types.ts b/packages/core/src/agent/system-prompt/types.ts index cf1cc1ba..0741a80e 100644 --- a/packages/core/src/agent/system-prompt/types.ts +++ b/packages/core/src/agent/system-prompt/types.ts @@ -37,6 +37,14 @@ export interface RuntimeInfo { cwd?: string | undefined; } +/** Describes a connected messaging channel and its capabilities */ +export interface ChannelInfo { + /** Human-readable channel name (e.g. "Telegram") */ + name: string; + /** Whether the channel supports outbound media via send_file */ + canSendMedia: boolean; +} + /** Subagent context for minimal/none modes */ export interface SubagentContext { /** Parent session that spawned this subagent */ @@ -77,6 +85,8 @@ export interface SystemPromptOptions { subagent?: SubagentContext | undefined; /** Workspace directory path (for agent working directory info) */ workspaceDir?: string | undefined; + /** Connected messaging channels (for channel awareness section) */ + channels?: ChannelInfo[] | undefined; /** Extra system prompt to append */ extraSystemPrompt?: string | undefined; /** Whether to include the safety constitution (default: true) */