Agents: validate persisted tool-call names

This commit is contained in:
Vignesh Natarajan
2026-02-21 23:06:44 -08:00
parent 29a782b9cd
commit cdfe45eeb8
11 changed files with 248 additions and 8 deletions

View File

@@ -78,6 +78,7 @@ import {
buildEmbeddedSystemPrompt,
createSystemPromptOverride,
} from "./system-prompt.js";
import { collectAllowedToolNames } from "./tool-name-allowlist.js";
import { splitSdkTools } from "./tool-split.js";
import type { EmbeddedPiCompactResult } from "./types.js";
import { describeUnknownError, mapThinkingLevel } from "./utils.js";
@@ -383,6 +384,7 @@ export async function compactEmbeddedPiSessionDirect(
modelAuthMode: resolveModelAuthMode(model.provider, params.config),
});
const tools = sanitizeToolsForGoogle({ tools: toolsRaw, provider });
const allowedToolNames = collectAllowedToolNames({ tools });
logToolSchemasForGoogle({ tools, provider });
const machineName = await getMachineDisplayName();
const runtimeChannel = normalizeMessageChannel(params.messageChannel ?? params.messageProvider);
@@ -532,6 +534,7 @@ export async function compactEmbeddedPiSessionDirect(
agentId: sessionAgentId,
sessionKey: params.sessionKey,
allowSyntheticToolResults: transcriptPolicy.allowSyntheticToolResults,
allowedToolNames,
});
trackSessionManagerAccess(params.sessionFile);
const settingsManager = SettingsManager.create(effectiveWorkspace, agentDir);
@@ -587,6 +590,7 @@ export async function compactEmbeddedPiSessionDirect(
modelApi: model.api,
modelId,
provider,
allowedToolNames,
config: params.config,
sessionManager,
sessionId: params.sessionId,

View File

@@ -426,6 +426,7 @@ export async function sanitizeSessionHistory(params: {
modelApi?: string | null;
modelId?: string;
provider?: string;
allowedToolNames?: Iterable<string>;
config?: OpenClawConfig;
sessionManager: SessionManager;
sessionId: string;
@@ -458,7 +459,9 @@ export async function sanitizeSessionHistory(params: {
const sanitizedThinking = policy.sanitizeThinkingSignatures
? sanitizeAntigravityThinkingBlocks(droppedThinking)
: droppedThinking;
const sanitizedToolCalls = sanitizeToolCallInputs(sanitizedThinking);
const sanitizedToolCalls = sanitizeToolCallInputs(sanitizedThinking, {
allowedToolNames: params.allowedToolNames,
});
const repairedTools = policy.repairToolUseResultPairing
? sanitizeToolUseResultPairing(sanitizedToolCalls)
: sanitizedToolCalls;

View File

@@ -105,6 +105,7 @@ import {
createSystemPromptOverride,
} from "../system-prompt.js";
import { dropThinkingBlocks } from "../thinking.js";
import { collectAllowedToolNames } from "../tool-name-allowlist.js";
import { installToolResultContextGuard } from "../tool-result-context-guard.js";
import { splitSdkTools } from "../tool-split.js";
import { describeUnknownError, mapThinkingLevel } from "../utils.js";
@@ -395,6 +396,10 @@ export async function runEmbeddedAttempt(
disableMessageTool: params.disableMessageTool,
});
const tools = sanitizeToolsForGoogle({ tools: toolsRaw, provider: params.provider });
const allowedToolNames = collectAllowedToolNames({
tools,
clientTools: params.clientTools,
});
logToolSchemasForGoogle({ tools, provider: params.provider });
const machineName = await getMachineDisplayName();
@@ -591,6 +596,7 @@ export async function runEmbeddedAttempt(
sessionKey: params.sessionKey,
inputProvenance: params.inputProvenance,
allowSyntheticToolResults: transcriptPolicy.allowSyntheticToolResults,
allowedToolNames,
});
trackSessionManagerAccess(params.sessionFile);
@@ -777,6 +783,7 @@ export async function runEmbeddedAttempt(
modelApi: params.model.api,
modelId: params.modelId,
provider: params.provider,
allowedToolNames,
config: params.config,
sessionManager,
sessionId: params.sessionId,

View File

@@ -0,0 +1,26 @@
import type { AgentTool } from "@mariozechner/pi-agent-core";
import type { ClientToolDefinition } from "./run/params.js";
function addName(names: Set<string>, value: unknown): void {
if (typeof value !== "string") {
return;
}
const trimmed = value.trim();
if (trimmed) {
names.add(trimmed);
}
}
export function collectAllowedToolNames(params: {
tools: AgentTool[];
clientTools?: ClientToolDefinition[];
}): Set<string> {
const names = new Set<string>();
for (const tool of params.tools) {
addName(names, tool.name);
}
for (const tool of params.clientTools ?? []) {
addName(names, tool.function?.name);
}
return names;
}