fix: scope subagent handoff to direct tools (#115466)

This commit is contained in:
Shakker
2026-07-29 01:49:04 +01:00
committed by Shakker
parent 7620475a2f
commit f6bd2b6518
2 changed files with 34 additions and 3 deletions

View File

@@ -478,6 +478,26 @@ describe("Codex app-server native code mode config", () => {
dynamicTools: [],
},
);
const withWrongNamespace = buildDeveloperInstructions(
createAttemptParams({ provider: "openai" }),
{
dynamicTools: [
{
type: "namespace",
name: "openclaw",
description: "",
tools: [
{
type: "function",
name: "sessions_yield",
description: "Different tool with the same leaf name",
inputSchema: { type: "object" },
},
],
},
],
},
);
expect(withSessionsYield).toContain(
"end the current turn with `openclaw_direct.sessions_yield`",
@@ -488,6 +508,8 @@ describe("Codex app-server native code mode config", () => {
expect(withSessionsYield).toContain("Never loop-poll for native child completion.");
expect(withoutSessionsYield).not.toContain("`openclaw_direct.sessions_yield`");
expect(withoutSessionsYield).not.toContain("native `wait_agent`");
expect(withWrongNamespace).not.toContain("`openclaw_direct.sessions_yield`");
expect(withWrongNamespace).not.toContain("native `wait_agent`");
});
it("summarizes deferred dynamic tool names in developer instructions", () => {

View File

@@ -4,7 +4,11 @@ import {
type EmbeddedRunAttemptParams,
} from "openclaw/plugin-sdk/agent-harness-runtime";
import { listRegisteredPluginAgentPromptGuidance } from "openclaw/plugin-sdk/plugin-runtime";
import { flattenCodexDynamicToolFunctions, type CodexDynamicToolSpec } from "./protocol.js";
import {
CODEX_OPENCLAW_DIRECT_DYNAMIC_TOOL_NAMESPACE,
flattenCodexDynamicToolFunctions,
type CodexDynamicToolSpec,
} from "./protocol.js";
export function buildDeveloperInstructions(
params: EmbeddedRunAttemptParams,
@@ -33,9 +37,14 @@ export function buildDeveloperInstructions(
function buildNativeSubagentCompletionInstruction(
dynamicTools: readonly CodexDynamicToolSpec[] | undefined,
): string | undefined {
const hasSessionsYield = flattenCodexDynamicToolFunctions(dynamicTools).some(
(tool) => tool.name.trim() === "sessions_yield",
const directNamespace = dynamicTools?.find(
(tool) =>
tool.type === "namespace" &&
tool.name.trim() === CODEX_OPENCLAW_DIRECT_DYNAMIC_TOOL_NAMESPACE,
);
const hasSessionsYield =
directNamespace?.type === "namespace" &&
directNamespace.tools.some((tool) => tool.name.trim() === "sessions_yield");
if (!hasSessionsYield) {
return undefined;
}