diff --git a/packages/core/src/tool/subagent.ts b/packages/core/src/tool/subagent.ts index 84131b18a6eb..b8c0975cdc50 100644 --- a/packages/core/src/tool/subagent.ts +++ b/packages/core/src/tool/subagent.ts @@ -69,8 +69,18 @@ export const Plugin = { state: "completed" | "error" | "cancelled", text: string, ) { + // TUI synthetic rows require a non-empty description to render in the parent transcript. + // Keep the structured XML body in text for model consumption; surface a short human label + // so background completions and failures remain visible without a follow-up model turn. + const label = + state === "error" + ? `Background subagent failed: ${description}` + : state === "cancelled" + ? `Background subagent cancelled: ${description}` + : `Background subagent completed: ${description}` yield* runtime.session.synthetic({ sessionID: parentID, + description: label, text: `\n${text}\n`, }) }) diff --git a/packages/core/test/tool-subagent.test.ts b/packages/core/test/tool-subagent.test.ts index 56e3587162d6..b0cd70e62684 100644 --- a/packages/core/test/tool-subagent.test.ts +++ b/packages/core/test/tool-subagent.test.ts @@ -289,6 +289,7 @@ describe("SubagentTool", () => { yield* SessionPending.promoteSteers(database.db, events, parent.id) const synthetic = (yield* sessions.context(parent.id)).filter((message) => message.type === "synthetic") expect(synthetic).toHaveLength(1) + expect(synthetic[0]?.description).toBe("Background subagent completed: background review") expect(synthetic[0]?.text).toContain(`