How to Fix 'tool calling failure' in LangChain (Python)
tool calling failure in LangChain usually means the model was asked to use a tool, but the tool-call payload coming back from the LLM was invalid, incomplete, or impossible for LangChain to parse. You’ll typically see this when using ChatOpenAI, bind_tools(), ToolNode, or an agent executor with function/tool calling enabled.
In practice, it shows up when your tool schema doesn’t match the arguments the model emits, when the model doesn’t actually support tool calling, or when your prompt/setup makes the agent produce plain text instead of a structured tool call.
The Most Common Cause
The #1 cause is a mismatch between the tool signature and how you defined or passed it to LangChain. The model returns a tool call with arguments that don’t match the Python function schema, and LangChain raises errors like:
- •
langchain_core.exceptions.OutputParserException - •
InvalidToolCall - •
ToolMessage: Error invoking tool - •
tool calling failure
Here’s the broken pattern:
| Broken | Fixed |
|---|---|
Tool expects city: str, but prompt encourages free-form text | Tool schema matches exactly what the model should send |
| Manual string parsing inside the tool | Typed args via Pydantic / annotations |
| Model not bound correctly | Use bind_tools() on a tool-capable chat model |
# BROKEN
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
from langchain.agents import create_tool_calling_agent, AgentExecutor
from langchain_core.prompts import ChatPromptTemplate
@tool
def get_weather(city: str) -> str:
return f"Weather in {city}: sunny"
llm = ChatOpenAI(model="gpt-3.5-turbo") # often wrong for tool calling in practice
tools = [get_weather]
prompt = ChatPromptTemplate.from_messages([
("system", "Use tools when needed."),
("human", "{input}")
])
agent = create_tool_calling_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools)
# This can fail if the model emits invalid args or doesn't support tools well
executor.invoke({"input": "What's the weather?"})
# FIXED
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
from langchain.agents import create_tool_calling_agent, AgentExecutor
from langchain_core.prompts import ChatPromptTemplate
@tool
def get_weather(city: str) -> str:
"""Get weather for a city."""
return f"Weather in {city}: sunny"
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
llm_with_tools = llm.bind_tools([get_weather])
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful assistant. Use tools only when needed."),
("human", "{input}")
])
agent = create_tool_calling_agent(llm_with_tools, [get_weather], prompt)
executor = AgentExecutor(agent=agent, tools=[get_weather], verbose=True)
executor.invoke({"input": "What's the weather in Nairobi?"})
The important part is that the model is actually configured for tool calling and the function signature is simple and explicit. If your tool takes multiple arguments, make them typed and named clearly.
Other Possible Causes
1) Using a model that does not support tool calling well
Some models will “pretend” to call tools by returning text that looks like JSON. LangChain then fails because it expected a structured tool_calls payload.
# Risky
llm = ChatOpenAI(model="gpt-3.5-turbo")
Use a model known to support structured tool calls reliably:
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
If you’re on Anthropic or another provider, make sure you’re using their LangChain integration and not assuming OpenAI-style behavior.
2) Tool schema too complex or ambiguous
Nested dicts, optional fields without defaults, or loosely typed inputs often cause malformed calls.
from pydantic import BaseModel, Field
class SearchArgs(BaseModel):
query: str = Field(..., description="Search query")
top_k: int = Field(default=3, ge=1, le=10)
@tool(args_schema=SearchArgs)
def search_docs(query: str, top_k: int = 3) -> str:
return f"Searching {top_k} docs for {query}"
If you rely on dict blobs instead of typed fields, LangChain has less to validate and more room to fail.
3) Prompt instructs the model to answer directly instead of using tools
If your system prompt says things like “never call tools” or your few-shot examples show direct answers only, the agent may skip structured calls entirely.
# Bad system message
("system", "Answer directly. Do not use tools.")
Fix it by being explicit:
("system", "Use available tools whenever they help answer the user.")
4) Version mismatch between LangChain packages
This error also appears when langchain, langchain-core, langchain-openai, and agent-related packages are out of sync.
Check versions:
pip show langchain langchain-core langchain-openai langgraph
Upgrade together:
pip install -U langchain langchain-core langchain-openai langgraph
A mismatched install can produce weird failures around AIMessage.tool_calls parsing and agent execution.
How to Debug It
- •Print the raw AI message
- •Inspect whether you got a real structured call or just text.
- •Look for
message.tool_callsandmessage.additional_kwargs.
response = llm_with_tools.invoke("What's the weather in Nairobi?")
print(response)
print(getattr(response, "tool_calls", None))
print(getattr(response, "additional_kwargs", None))
- •
Turn on verbose logging
- •For agents: set
verbose=True. - •For LangChain internals: enable debug tracing if needed.
- •You want to see whether the agent attempted a tool call before failing.
- •For agents: set
- •
Validate your tool schema independently
- •Call the Python function directly.
- •Check whether argument names/types match what you expect.
- •If using Pydantic schemas, instantiate them manually first.
args = {"city": "Nairobi"}
print(get_weather.invoke(args)) # if wrapped as a LangChain tool
- •Swap in a known-good model
- •Test with
gpt-4o-minior another supported chat model. - •If it works there but not elsewhere, you’ve isolated a provider/model capability issue.
- •Test with
Prevention
- •
Keep tools simple:
- •Use typed parameters.
- •Avoid deeply nested schemas unless you need them.
- •Prefer one responsibility per tool.
- •
Bind tools explicitly:
- •Use
llm.bind_tools([...]). - •Don’t assume passing tools into an agent is enough if your LLM wrapper isn’t configured correctly.
- •Use
- •
Pin compatible package versions:
- •Upgrade LangChain packages together.
- •Test changes with one known-good agent flow before rolling them into production.
If you’re debugging this in production code, start by checking whether your model emitted a real tool_calls structure. In most cases, that tells you immediately whether this is a schema problem, a model capability problem, or just a version mismatch.
Keep learning
- •The complete AI Agents Roadmap — my full 8-step breakdown
- •Free: The AI Agent Starter Kit — PDF checklist + starter code
- •Work with me — I build AI for banks and insurance companies
By Cyprian Aarons, AI Consultant at Topiax.
Want the complete 8-step roadmap?
Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.
Get the Starter Kit