From 8a9b0ee4f484d2b337c38c030abd8efc194f35ed Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sat, 1 Aug 2026 13:47:29 +0800 Subject: [PATCH] fix(agents): retain tools for direct completion delivery --- .../command/attempt-execution.cli.test.ts | 25 ++++++++++++------- src/agents/command/attempt-execution.ts | 5 +++- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/agents/command/attempt-execution.cli.test.ts b/src/agents/command/attempt-execution.cli.test.ts index fbad85aa3add..b683d00e6a00 100644 --- a/src/agents/command/attempt-execution.cli.test.ts +++ b/src/agents/command/attempt-execution.cli.test.ts @@ -228,15 +228,22 @@ const SUBAGENT_ANNOUNCE_DELIVERY_CASES: readonly SubagentAnnounceDeliveryCase[] ]; const SUBAGENT_ANNOUNCE_EMBEDDED_DELIVERY_CASES: readonly SubagentAnnounceDeliveryCase[] = [ - ...SUBAGENT_ANNOUNCE_DELIVERY_CASES.map((testCase) => - testCase.name === "automatic source replies" - ? { - ...testCase, - expectedDisableTools: false, - expectedToolsAllow: SUBAGENT_ANNOUNCE_REQUESTER_TOOLS, - } - : testCase, - ), + ...SUBAGENT_ANNOUNCE_DELIVERY_CASES.map((testCase) => { + if (testCase.name === "automatic source replies") { + return { + ...testCase, + expectedDisableTools: false, + expectedToolsAllow: SUBAGENT_ANNOUNCE_REQUESTER_TOOLS, + }; + } + if (!testCase.expectedDisableTools) { + return { + ...testCase, + expectedToolsAllow: testCase.runtimeToolsAllow ?? SUBAGENT_ANNOUNCE_REQUESTER_TOOLS, + }; + } + return testCase; + }), { name: "a raw model run despite message-tool-only delivery", sourceReplyDeliveryMode: "message_tool_only", diff --git a/src/agents/command/attempt-execution.ts b/src/agents/command/attempt-execution.ts index 034ffdd1ff87..501e16bcbeba 100644 --- a/src/agents/command/attempt-execution.ts +++ b/src/agents/command/attempt-execution.ts @@ -731,7 +731,10 @@ export function runAgentAttempt(params: { trustedSubagentAnnounceHandoff && !isRawModelRun && !isCliExecutionProvider && - !messageToolOwnsVisibleReply(params.opts); + (!messageToolOwnsVisibleReply(params.opts) || completionNeedsMessageDelivery); + // Message-tool-only delivery constrains the visible reply, not the parent + // continuation's verified authority. Keep the inherited cap while requiring + // message to survive every applicable policy before enabling any tools. // An explicit cap is enforced even when tools are disabled; clear it so a // denied completion can finish tool-free and its owner can relay frozen text. const runtimeToolsAllow = isSubagentAnnounceHandoff