๐ฏ What You'll Learn Today
LangGraph Tutorial: Implementing Tool Calling Node - Unit 2.1 Exercise 2
This tutorial is also available in Google Colab here or for download here
Joint Initiative: This tutorial is part of a collaboration between AI Product Engineer and the Nebius Academy.
This tutorial demonstrates how to implement a tool calling node in LangGraph that can intelligently decide when to use tools and structure appropriate tool calls based on user input.
Key Concepts Covered
- Tool Call Decision Making
- State Management
- Message Processing
- Tool Call Structuring
import json
from typing import Annotated, Any, TypedDict
!pip install langchain-core
!pip install langgraph
from langchain_core.messages import BaseMessage, HumanMessage
from langgraph.graph.message import add_messages
Step 1: State Definition
We define our state structure for managing tool interactions.
Why This Matters
Proper state management is crucial because
- Enables tracking of conversation history
- Maintains tool call records
- Stores tool outputs for future reference
- Facilitates debugging and monitoring
Debug Tips
-
State Verification:
- Print state contents before operations
- Verify message list structure
- Check tool_calls initialization
- Monitor tool_outputs updates
class State(TypedDict):
"""State container for tool interactions.
This state implementation tracks three key elements:
1. Message history with special handling
2. Tool call records
3. Tool execution outputs
Attributes:
messages: List of conversation messages with proper annotation
tool_calls: Record of all tool invocations
tool_outputs: Results from tool executions
"""
messages: Annotated[list[BaseMessage], add_messages]
tool_calls: list[dict]
tool_outputs: list[Any]
Step 2: Tool Calling Node Implementation
We implement the core logic for determining when to use tools and how to structure tool calls.
Why This Matters
Tool calling logic is crucial because
- Determines appropriate tool usage
- Structures tool parameters correctly
- Maintains conversation flow
- Handles edge cases gracefully
Debug Tips
-
Node Behavior:
- Log decision points
- Track tool call generation
- Verify parameter structure
- Monitor edge cases
def llm_node(state: State) -> State:
"""Decides when and how to call tools based on conversation state.
This function demonstrates several key concepts:
1. State initialization handling
2. Message content analysis
3. Tool call generation
4. State updates
Args:
state: Current conversation and tool state
Returns:
Updated state with new messages or tool calls
Note:
The function specifically handles queries about France's capital
as an example use case.
"""
# Handle initial state with no messages
if not state.get("messages"):
return {
"messages": [HumanMessage(content="What is the capital of France?")],
"tool_calls": [],
"tool_outputs": [],
}
# Analyze last message for tool needs
last_message = state["messages"][-1].content
# Generate tool call if needed
if "capital of France" in last_message:
return {
"tool_calls": [
{
"tool_name": "TavilySearchResults",
"args": {"query": "capital of France"},
}
]
}
# Return unchanged state if no tool needed
return state
Step 3: Usage Demonstration
Example showing how to use the tool calling node.
Debug Tips
-
Testing:
- Try various input messages
- Verify tool call structure
- Check state preservation
- Test edge cases
def demonstrate_tool_calling():
"""Demonstrates the tool calling node functionality."""
# Initialize state
initial_state = {
"messages": [HumanMessage(content="What is the capital of France?")],
"tool_calls": [],
"tool_outputs": [],
}
# Process through node
result = llm_node(initial_state)
# Display results
print("Tool Calls Generated:")
print(json.dumps(result.get("tool_calls", []), indent=2))
if __name__ == "__main__":
demonstrate_tool_calling()
Common Pitfalls
- Not handling empty message lists
- Incorrect tool call parameter structure
- Missing state fields
- Improper message content analysis
Key Takeaways
- State Design: Proper state structure enables reliable tool interactions
- Decision Logic: Clear conditions for tool usage
- Tool Call Format: Consistent structure for tool invocation
- Error Handling: Graceful handling of edge cases
Next Steps
- Add more sophisticated tool selection logic
- Implement error handling
- Add support for multiple tools
- Enhance message analysis
- Add tool call validation
Expected Output
Tool Calls Generated
[
{
"tool_name": "TavilySearchResults",
"args": {
"query": "capital of France"
}
}
]
๐ฌ๐ง Chapter