diff --git a/CHANGELOG.md b/CHANGELOG.md index b4674f652b7..58975764167 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -158,6 +158,7 @@ Docs: https://docs.openclaw.ai - Memory host SDK: report malformed remote JSON with caller-scoped errors for POST and batch file upload responses instead of leaking raw parser failures. - Media providers: report malformed operation-poll and audio-transcription JSON with provider-owned errors instead of leaking raw parser failures. - MiniMax, Gemini, Kimi, and Ollama web search: report malformed API JSON with provider-owned errors instead of leaking raw parser failures. +- Web search: mark the managed `web_search` `query` argument as required in the advertised tool schema, so schema-following local models stop emitting `queries` payloads that fail at execution. Fixes #82097. Thanks @SpidFightFR. - Twilio voice-call: report malformed successful API JSON responses with provider-owned errors instead of leaking raw parser failures. - Voice-call provider APIs: report malformed successful guarded JSON responses with provider-prefixed errors instead of leaking raw parser failures. - Realtime transcription: report malformed provider websocket JSON frames with owned parser errors instead of leaking raw `SyntaxError` objects. diff --git a/src/agents/tools/web-search.test.ts b/src/agents/tools/web-search.test.ts index cb6ed3fe124..06eeafcacde 100644 --- a/src/agents/tools/web-search.test.ts +++ b/src/agents/tools/web-search.test.ts @@ -10,6 +10,13 @@ import { mergeScopedSearchConfig } from "./web-search-provider-config.js"; import { createWebSearchTool } from "./web-search.js"; describe("web_search tool schema", () => { + it("marks query as required for model tool-call schemas", () => { + const tool = createWebSearchTool(); + const parameters = tool?.parameters as { required?: unknown } | undefined; + + expect(parameters?.required).toEqual(["query"]); + }); + it("advertises the shared runtime count limit", () => { const tool = createWebSearchTool(); const parameters = tool?.parameters as diff --git a/src/agents/tools/web-search.ts b/src/agents/tools/web-search.ts index ae731c87957..13bfdc2a48b 100644 --- a/src/agents/tools/web-search.ts +++ b/src/agents/tools/web-search.ts @@ -8,6 +8,7 @@ import { resolveWebSearchToolRuntimeContext } from "./web-tool-runtime-context.j const WebSearchSchema = { type: "object", + required: ["query"], properties: { query: { type: "string", description: "Search query string." }, count: { diff --git a/test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/codex-dynamic-tools.discord-group.json b/test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/codex-dynamic-tools.discord-group.json index 03ec0756c2e..14a96f2b37d 100644 --- a/test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/codex-dynamic-tools.discord-group.json +++ b/test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/codex-dynamic-tools.discord-group.json @@ -1174,6 +1174,7 @@ "type": "string" } }, + "required": ["query"], "type": "object" }, "name": "web_search", diff --git a/test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/codex-dynamic-tools.heartbeat-turn.json b/test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/codex-dynamic-tools.heartbeat-turn.json index 7bf9149a94e..0ee1f2d834b 100644 --- a/test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/codex-dynamic-tools.heartbeat-turn.json +++ b/test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/codex-dynamic-tools.heartbeat-turn.json @@ -1206,6 +1206,7 @@ "type": "string" } }, + "required": ["query"], "type": "object" }, "name": "web_search", diff --git a/test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/codex-dynamic-tools.telegram-direct.json b/test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/codex-dynamic-tools.telegram-direct.json index 500d1a8f7e0..3f9daefa6a3 100644 --- a/test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/codex-dynamic-tools.telegram-direct.json +++ b/test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/codex-dynamic-tools.telegram-direct.json @@ -1170,6 +1170,7 @@ "type": "string" } }, + "required": ["query"], "type": "object" }, "name": "web_search", diff --git a/test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/discord-group-codex-message-tool.md b/test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/discord-group-codex-message-tool.md index 47b6f88a995..a399e4d17da 100644 --- a/test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/discord-group-codex-message-tool.md +++ b/test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/discord-group-codex-message-tool.md @@ -217,8 +217,8 @@ This is the deterministic model-bound layer stack OpenClaw can snapshot for the "roughTokens": 140 }, "dynamicToolsJson": { - "chars": 44328, - "roughTokens": 11082 + "chars": 44373, + "roughTokens": 11094 }, "openClawDeveloperInstructions": { "chars": 5436, @@ -229,8 +229,8 @@ This is the deterministic model-bound layer stack OpenClaw can snapshot for the "roughTokens": 7129 }, "totalWithDynamicToolsJson": { - "chars": 72846, - "roughTokens": 18212 + "chars": 72891, + "roughTokens": 18223 }, "userInputText": { "chars": 870, diff --git a/test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/telegram-direct-codex-message-tool.md b/test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/telegram-direct-codex-message-tool.md index ead928c9301..c9956570480 100644 --- a/test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/telegram-direct-codex-message-tool.md +++ b/test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/telegram-direct-codex-message-tool.md @@ -217,8 +217,8 @@ This is the deterministic model-bound layer stack OpenClaw can snapshot for the "roughTokens": 140 }, "dynamicToolsJson": { - "chars": 44019, - "roughTokens": 11005 + "chars": 44064, + "roughTokens": 11016 }, "openClawDeveloperInstructions": { "chars": 4412, @@ -229,8 +229,8 @@ This is the deterministic model-bound layer stack OpenClaw can snapshot for the "roughTokens": 6748 }, "totalWithDynamicToolsJson": { - "chars": 71013, - "roughTokens": 17754 + "chars": 71058, + "roughTokens": 17765 }, "userInputText": { "chars": 370, diff --git a/test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/telegram-heartbeat-codex-tool.md b/test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/telegram-heartbeat-codex-tool.md index 215194391ac..bc599a2919a 100644 --- a/test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/telegram-heartbeat-codex-tool.md +++ b/test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/telegram-heartbeat-codex-tool.md @@ -218,8 +218,8 @@ This is the deterministic model-bound layer stack OpenClaw can snapshot for the "roughTokens": 140 }, "dynamicToolsJson": { - "chars": 45197, - "roughTokens": 11300 + "chars": 45242, + "roughTokens": 11311 }, "openClawDeveloperInstructions": { "chars": 4412, @@ -230,8 +230,8 @@ This is the deterministic model-bound layer stack OpenClaw can snapshot for the "roughTokens": 7155 }, "totalWithDynamicToolsJson": { - "chars": 73818, - "roughTokens": 18455 + "chars": 73863, + "roughTokens": 18466 }, "userInputText": { "chars": 608,