From 453e47274a5c1c993cfcfe210ff2a3e4f7d02061 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Tue, 30 Jun 2026 21:41:28 -0400 Subject: [PATCH] Inject inbox context into non-chat task runs Heartbeat and manual task runs now load the agent's recent @mentions and include them directly in the task prompt. This gives agents conversational context even before they call read_messages, ensuring they respond to teammates who addressed them rather than silently ignoring messages. --- .../main/services/task-execution-service.ts | 23 +++++++++++++++++++ .../src/main/services/task-prompts.ts | 14 +++++++++++ 2 files changed, 37 insertions(+) diff --git a/AgentCompany-New/src/main/services/task-execution-service.ts b/AgentCompany-New/src/main/services/task-execution-service.ts index a87f6ec4..8d9aa9c8 100644 --- a/AgentCompany-New/src/main/services/task-execution-service.ts +++ b/AgentCompany-New/src/main/services/task-execution-service.ts @@ -13,6 +13,7 @@ import { buildAgentInstructions, buildTaskPrompt, type ChatContextBlock, + type InboxContextBlock, type GoalRow, type ProjectRow, type SkillRuntimeSnapshotRow, @@ -120,6 +121,7 @@ export class TaskExecutionService { workspace: workspace ? { id: workspace.id, localPath: workspace.local_path } : null, }; const chatContext = this.loadChatContext(orgId, isolation); + const inboxContext = chatContext ? null : this.loadInboxContext(orgId, agent.id); const isCeo = !agent.manager_agent_id; const hasReports = this.agentHasReports(orgId, agent.id); const externalTools = await loadComposioTools(this.db, orgId); @@ -147,6 +149,7 @@ export class TaskExecutionService { hasReports, managerName: this.agentName(orgId, agent.manager_agent_id), chatContext, + inboxContext, }), toolContext, externalTools, @@ -370,6 +373,26 @@ export class TaskExecutionService { }; } + private loadInboxContext(orgId: string, agentId: string): InboxContextBlock | null { + const messages = this.db.prepare(` + select m.body_md, + coalesce(a.name, e.display_name, m.sender_type) as sender_name, + s.name as channel_name + from chat_mentions cm + join chat_messages m on m.id = cm.message_id + join chat_spaces s on s.id = m.space_id + left join agents a on a.id = m.sender_id and m.sender_type = 'agent' + left join employees e on e.id = m.sender_id and m.sender_type = 'employee' + where cm.target_type = 'agent' and cm.target_id = ? and m.org_id = ? and m.deleted_at is null + order by m.created_at desc + limit 10 + `).all(agentId, orgId) as Array<{ body_md: string; sender_name: string; channel_name: string }>; + if (messages.length === 0) return null; + return { + transcript: messages.reverse().map((m) => `[${m.sender_name} in #${m.channel_name}]: ${m.body_md}`).join("\n"), + }; + } + private agentHasReports(orgId: string, agentId: string): boolean { const row = this.db.prepare("select 1 from agents where org_id = ? and manager_agent_id = ? and lifecycle = 'active' limit 1") .get(orgId, agentId); diff --git a/AgentCompany-New/src/main/services/task-prompts.ts b/AgentCompany-New/src/main/services/task-prompts.ts index bc0e0d6d..931c4ca4 100644 --- a/AgentCompany-New/src/main/services/task-prompts.ts +++ b/AgentCompany-New/src/main/services/task-prompts.ts @@ -107,6 +107,10 @@ function roleVoice(input: AgentInstructionContext): string { return "You own your craft. Ask the question early instead of guessing, do the work properly, and when you are stuck for more than a few minutes say so in the thread instead of spinning in place."; } +export interface InboxContextBlock { + transcript: string; +} + export function buildTaskPrompt(input: { task: TaskExecutionTaskRow; agent: TaskExecutionAgentRow; @@ -120,6 +124,7 @@ export function buildTaskPrompt(input: { hasReports: boolean; managerName: string | null; chatContext: ChatContextBlock | null; + inboxContext: InboxContextBlock | null; }): string { const lines = [ "Execute this AgentCompany task.", @@ -169,6 +174,15 @@ export function buildTaskPrompt(input: { ); return lines.join("\n"); } + if (input.inboxContext) { + lines.push( + "", + "Recent messages that mention you:", + input.inboxContext.transcript, + "", + "Respond to anyone above who needs your input before starting the task.", + ); + } if (input.isManager && !input.hasReports) { lines.push( "",