{"record":{"id":"f5a8614762e935dc","repo":"alibaba/page-agent","slug":"no-tool-call","errorCode":"NO_TOOL_CALL","errorMessage":"No tool call found in response","messagePattern":"No tool call found in response","errorType":"exception","errorClass":"InvokeError","httpStatus":null,"severity":"error","filePath":"packages/llms/src/OpenAIClient.ts","lineNumber":183,"sourceCode":"\t\t\t\t\tdata\n\t\t\t\t)\n\t\t\tdefault:\n\t\t\t\tthrow new InvokeError(\n\t\t\t\t\tInvokeErrorTypes.INVALID_SCHEMA,\n\t\t\t\t\t`Unexpected finish_reason: ${choice.finish_reason}`,\n\t\t\t\t\tundefined,\n\t\t\t\t\tdata\n\t\t\t\t)\n\t\t}\n\n\t\t// Apply normalizeResponse if provided (for fixing format issues automatically)\n\t\tconst normalizedData = options?.normalizeResponse ? options.normalizeResponse(data) : data\n\t\tconst normalizedChoice = (normalizedData as any).choices?.[0]\n\n\t\t// Get tool name from response\n\t\tconst toolCallName = normalizedChoice?.message?.tool_calls?.[0]?.function?.name\n\t\tif (!toolCallName) {\n\t\t\tthrow new InvokeError(\n\t\t\t\tInvokeErrorTypes.NO_TOOL_CALL,\n\t\t\t\t'No tool call found in response',\n\t\t\t\tundefined,\n\t\t\t\tdata\n\t\t\t)\n\t\t}\n\n\t\tconst tool = tools[toolCallName]\n\t\tif (!tool) {\n\t\t\tthrow new InvokeError(\n\t\t\t\tInvokeErrorTypes.UNKNOWN,\n\t\t\t\t`Tool \"${toolCallName}\" not found in tools`,\n\t\t\t\tundefined,\n\t\t\t\tdata\n\t\t\t)\n\t\t}\n\n\t\t// Extract and parse tool arguments","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/alibaba/page-agent/blob/d02db1ee7c41f5315beda88bab2fe935c580f662/packages/llms/src/OpenAIClient.ts#L165-L201","documentation":"After a successful LLM call, OpenAIClient.invoke expects the model to respond with a tool call; if choices[0].message.tool_calls[0].function.name is missing it throws InvokeError NO_TOOL_CALL. This happens when the model answered with plain text (or an empty message) instead of invoking one of the provided tools.","triggerScenarios":"invoke() is called with a tools map but the model returns a natural-language completion with no tool_calls; also when a custom normalizeResponse strips or renames the tool_calls field, or the provider doesn't support function calling.","commonSituations":"Model doesn't support function/tool calling (e.g. some open models behind an OpenAI-compatible facade); prompt leads the model to chat instead of act; temperature too high producing conversational replies; provider returns tool calls under a different field name.","solutions":["Check error.data.choices[0].message.content to see what the model actually said","Use a model that supports tool/function calling and ensure tools are passed on the request","Tighten the system prompt to force tool usage; lower temperature","If the provider uses a different response shape, normalize it via the normalizeResponse option"],"exampleFix":"// before\nconst res = await llm.invoke(messages, tools) // model replies with text\n\n// after\n// catch and surface the model's textual answer\ntry {\n  const res = await llm.invoke(messages, tools)\n} catch (e) {\n  if (e.code === 'NO_TOOL_CALL') {\n    console.warn('Model said instead:', e.data?.choices?.[0]?.message?.content)\n  }\n  throw e\n}","handlingStrategy":"fallback","validationCode":"null","typeGuard":"function isNoToolCallError(e: unknown): e is InvokeError {\n  return e instanceof InvokeError && e.code === InvokeErrorTypes.NO_TOOL_CALL\n}","tryCatchPattern":"try {\n  const res = await llm.invoke(messages, tools)\n} catch (e) {\n  if (isNoToolCallError(e)) {\n    const text = e.data?.choices?.[0]?.message?.content\n    return { fallbackAnswer: text } // degrade gracefully to the model's text answer\n  }\n  throw e\n}","preventionTips":["Use tool-calling-capable models","Prompt explicitly that the model must use a tool","Verify with a smoke-test call when switching providers"],"tags":["llm","tool-calling","no-tool-call","function-calling"],"backgroundTag":"llm-no-tool-call-in-response","analyzedSha":"d02db1ee7c41f5315beda88bab2fe935c580f662","analyzedAt":"2026-08-28T19:39:48.634Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}