LangChain has redefined how we build intelligent AI applications — connecting language models (LLMs) with tools, memory, and structured reasoning.
Enter Function Calling — the next-generation solution for connecting LLMs to real-world actions, now supported natively by model providers like OpenAI, Anthropic, and Mistral.
This post will explain:
-
What Function / Tool Calling is.
-
Why it’s better than the old ReAct approach.
-
How LangChain implements a unified interface for it.
-
A complete, step-by-step code walkthrough using both OpenAI and Anthropic models.
-
How to integrate memory, vectorized documentation, and Streamlit UI for real-world apps.
๐ช Visual: Evolution from ReAct → Function Calling
๐ช Visual: Evolution from ReAct → Function Calling
1. ReAct Agents — The Thinking Loop
ReAct (short for Reason + Act) agents mimic how humans solve problems:
agent they thought, acted, observed results, and repeated until find an answer.
-
The LLM “thinks” out loud, describing its reasoning (“I should use the weather tool”).
-
It calls a tool, like a calculator or web search API.
-
Then it observes the result, learns from it, and continues reasoning.
-
The loop repeats until the agent concludes with a Final Answer.
Pros:
- Easy to debug and visualize
Cons:
- Slower, fragile to prompt errors, hard to scale
- Required complex prompts.
- Could break if even one token misfired.
2. Function Calling Agents — Structured and Reliable
- Function Calling agents represent the next generation of LangChain design.
- Instead of narrating reasoning, the model now outputs a structured JSON describing exactly which function to call — and with what arguments.
- LangChain executes this call automatically, retrieves the result, and returns a structured response — all without the model generating human-readable text in between.
- This makes the system faster, cheaper, and less error-prone, perfect for production-scale AI applications.
Pros:
- Deterministic, schema-safe, low latency
- Harder to interpret internal reasoning (“black box”)
Why This Matters
- This evolution reflects a broader shift in AI systems —
- from prompt engineering to API orchestration.
- In early ReAct setups, engineers designed clever prompts to make the model “think” correctly.
- Now, with Function Calling, the intelligence is encoded in structure, not in text patterns.
- LangChain abstracts away this complexity with:
create_tool_calling_agent()— unified across OpenAI, Anthropic, Mistral, Gemini- Schema-based
@tooldecorators - Automatic JSON parsing & validation
The result: reliable AI pipelines that think less like humans, but work more like APIs — stable, scalable, and predictable.
1. What Is Function Calling?
1. What Is Function Calling?
- Function Calling is an LLM capability that allows the model to generate structured JSON indicating which external function to call and what arguments to pass.
{"name": "get_weather","arguments": {"city": "Dubai","unit": "celsius"}}
- Instead of producing plain text (“Let’s check the weather in Dubai”), the LLM programmatically requests a function call — eliminating ambiguity.
- This makes the model’s output
- Structured
- Deterministic
- Easier to parse and execute
2. Why Function Calling > ReAct
2. Why Function Calling > ReAct
✅ In short: Function Calling makes LLMs API-aware and reliable.
3. Key Capabilities
3. Key Capabilities
LangChain’s Function (Tool) Calling system includes:
-
Unified Interface: Works with OpenAI, Anthropic, Fireworks, Mistral, and Gemini.
-
Bind Functions: Use
@tooldecorator to define Python functions that can be called by the LLM. -
Automatic Tool Calling: The model decides when and how to call your tools.
-
Agent Abstraction: Use
create_tool_calling_agent()to build robust agents easily. -
Cross-Model Compatibility: Works across all LLM vendors with consistent syntax.
4. Code Example — Function / Tool Calling Agent
4. Code Example — Function / Tool Calling Agent
๐งฑ Step 1 — Setup Imports and Environment
e
from dotenv import load_dotenvfrom langchain_anthropic import ChatAnthropicfrom langchain_openai import ChatOpenAIfrom langchain_core.prompts import ChatPromptTemplatefrom langchain_core.tools import toolfrom langchain.agents import create_tool_calling_agent, AgentExecutorfrom langchain_community.tools.tavily_search import TavilySearchResultsload_dotenv()
-
dotenv→ loads your API keys (Anthropic, OpenAI, etc.). -
ChatAnthropic,ChatOpenAI→ LLM interfaces. -
ChatPromptTemplate→ defines the structured prompt format. -
@tool→ decorator to expose Python functions to the LLM. -
AgentExecutor→ runs the agent loop. -
TavilySearchResults→ example search tool from LangChain Community.
๐งฎ Step 2 — Define a Function (Tool)
@tooldef multiply(x: float, y: float) -> float:"""Multiply 'x' times 'y'."""return x * y
- This function will be automatically available to the LLM.
- When the model thinks, “I need to multiply 5 and 10,” it’ll produce a structured call to this tool.
๐ฌ Step 3 — Define the Prompt
prompt = ChatPromptTemplate.from_messages([("system", "You are a helpful assistant."),("human", "{input}"),("placeholder", "{agent_scratchpad}"),])
-
The system message defines the assistant’s personality.
-
The human message injects the user query dynamically.
-
The placeholder is where LangChain stores the “memory” of intermediate steps.
๐ง Step 4 — Initialize Tools and LLM
tools = [TavilySearchResults(), multiply]# Choose either Anthropic or OpenAI # llm = ChatOpenAI(model="gpt-4-turbo", temperature=0)llm = ChatAnthropic(model="claude-3-sonnet-20240229", temperature=0
⚙️ Step 5 — Create the Tool-Calling Agent
agent = create_tool_calling_agent(llm, tools, prompt)agent_executor = AgentExecutor(agent=agent, tools=tools)
๐ Step 6 — Run the Agent
res = agent_executor.invoke({"input": "What is the weather in Dubai right now? Compare it with San Francisco, output should be in Celsius.",})print(res)
Full Code :
from dotenv import load_dotenv from langchain_anthropic import ChatAnthropic from langchain_core.prompts import ChatPromptTemplate from langchain_core.tools import tool from langchain.agents import create_tool_calling_agent, AgentExecutor from langchain_openai import ChatOpenAI from langchain_community.tools.tavily_search import TavilySearchResults load_dotenv() @tool def multiply(x: float, y: float) -> float: """Multiply 'x' times 'y'.""" return x * y if __name__ == "__main__": print("Hello Tool Calling") prompt = ChatPromptTemplate.from_messages( [ ("system", "you're a helpful assistant"), ("human", "{input}"), ("placeholder", "{agent_scratchpad}"), ] ) tools = [TavilySearchResults(), multiply] # llm = ChatOpenAI(model="gpt-4-turbo") llm = ChatAnthropic(model="claude-3-sonnet-20240229", temperature=0) agent = create_tool_calling_agent(llm, tools, prompt) agent_executor = AgentExecutor(agent=agent, tools=tools) res = agent_executor.invoke( { "input": "what is the weather in dubai right now? compare it with San Fransisco, output should in in celsious", } ) print(res)
✅ Output Example:
{"output": "Dubai: 34°C, clear skies; San Francisco: 17°C, cloudy."}
5. How Function Calling Works Behind the Scenes
5. How Function Calling Works Behind the Scenes
-
LLM Reasoning:Model decides to call a tool (e.g.,
get_weather). -
JSON Function Call:The model produces a structured payload like:
-
LangChain Execution:
-
Parses the JSON.
-
Finds the tool.
-
Executes it safely.
-
-
Result Return:
-
Tool’s output returned to the model.
-
Model uses it to craft a final answer.
-
✅ No string parsing. ✅ No fragile regex. ✅ Fully structured logic.
Function Calling vs ReAct — Summary
๐ ALL AI / LangChain Post
