Configuring Tool Routing and Conditional Execution in Agent Graphs: A LangGraph Production Guide
Tool routing and conditional execution in agent graphs are configured by registering functions with the @tool decorator to enable automatic dispatch, then implementing ConditionalEdge predicates that inspect message metadata and tool outputs at runtime to determine the next workflow node.
The NirDiamant/agents-towards-production repository demonstrates production-ready patterns for building stateful agent workflows using LangGraph's graph-based orchestration engine. This guide examines how to configure dynamic tool routing and conditional logic by analyzing the actual implementation patterns found in the RunPod GPU deployment tutorial and secure Arcade tool-calling examples.
Understanding Agent Graph Architecture
LangGraph structures agent workflows as directed graphs composed of nodes and edges. Each node represents either an agent or a tool, while edges define the permissible transitions between them.
When an agent completes a step, it emits a Message object containing two critical routing fields:
tool_call– A string identifying the specific tool to invoke (for example, Research Tool as registered inhandler.py)metadata– Optional key-value pairs that conditional edges inspect to determine execution paths
The graph runtime evaluates the tool_call field and automatically routes the message to the corresponding tool node. This routing mechanism is implemented in tutorials/runpod-gpu-deploy/crew-ai-ollama-runpod-tutorial/handler.py, where the @tool decorator registers functions that the graph can dynamically dispatch.
Implementing Tool Routing with Decorators
Tool routing relies on explicit registration to map string identifiers to executable functions. The crewai.tools module provides the @tool decorator for this purpose.
Registering a Tool
When you decorate a function with @tool("Tool Name"), LangGraph adds it to the graph's routable registry:
from crewai.tools import tool
@tool("Research Tool")
def fake_research(topic: str) -> str:
"""Retrieves academic papers and summaries for the given topic."""
results = fetch_papers(topic)
return f"Research findings: {results}"
The string Research Tool becomes the routing key. When an agent's output contains tool_call: "Research Tool", the graph automatically forwards execution to this function. This pattern is demonstrated in tutorials/runpod-gpu-deploy/crew-ai-ollama-runpod-tutorial/handler.py, where the RunPod serverless handler builds a graph that routes between blog writing agents and research tools.
Building Conditional Execution Flows
Beyond static tool routing, production graphs require conditional edges that branch based on runtime state. LangGraph implements this through the ConditionalEdge class, which accepts a predicate function that inspects the current state dictionary.
Defining Conditional Logic
Conditional edges evaluate boolean functions that receive the complete state object (including metadata and previous tool outputs) and return a decision:
from langgraph.graph import StateGraph, ConditionalEdge
graph = StateGraph()
# Define nodes
graph.add_node("writer", writer_agent)
graph.add_node("research", fake_research)
graph.add_node("final", output_formatter)
# Static transition
graph.add_edge("writer", "research")
# Dynamic transition based on metadata inspection
def needs_research(state):
"""Check if the message metadata indicates research is required."""
return "needs_research" in state.get("metadata", {})
graph.add_conditional_edge(
"writer",
ConditionalEdge(
condition=needs_research,
target="research",
fallback="final"
)
)
In this configuration, the graph routes from writer to research only when the needs_research predicate returns True; otherwise, it proceeds directly to the final node.
Routing Based on Tool Output
You can also route based on the content returned by tools. The following pattern from tutorials/LangGraph-agent/langgraph_tutorial.ipynb demonstrates inspecting tool outputs to decide whether to summarize or re-search:
def enough_info(state):
"""Determine if search returned sufficient information."""
return "relevant" in state.get("output", "").lower()
graph.add_conditional_edge(
"search",
ConditionalEdge(
condition=enough_info,
target="summarise",
fallback="search_again"
)
)
Here, the condition function examines the output field populated by the previous tool execution, creating a feedback loop that continues researching until quality criteria are met.
Production Security and Deployment Patterns
Production deployments often require secure, multi-user tool routing where requests are vetted before execution. The Arcade tutorial in tutorials/arcade-secure-tool-calling/README.md demonstrates this pattern by inserting a guardrail node between the agent and tool execution.
In this architecture, the graph still routes based on tool_call, but an intermediate node inspects the tool_call value and user authentication context before forwarding to the actual tool node. This ensures that sensitive tools (like email senders or database writers) cannot be invoked without explicit user approval and authorization checks.
FastAPI Integration for External Routing
For external API exposure, tutorials/fastapi-agent/app.py demonstrates wrapping the agent graph in a FastAPI endpoint. This allows external systems to trigger graph execution while maintaining internal routing logic:
# handler.py pattern from RunPod tutorial
def handler(job):
topic = job["input"].get("topic", "technology")
blog = create_blog_post(topic) # Internally builds and runs a LangGraph
return {"status": "success", "blog_post": blog}
The create_blog_post function internally constructs a StateGraph, adds conditional edges for research validation, and executes the workflow, abstracting the routing complexity from the API consumer.
Summary
- Tool registration uses the
@tooldecorator to map string identifiers to functions, enabling the graph runtime to routetool_callvalues to the correct executable node. - Conditional execution relies on
ConditionalEdgeobjects that accept predicate functions inspecting thestatedictionary (includingmetadataandoutputfields) to determine the next node. - State inspection allows graphs to create loops and branches based on tool results, message metadata, or external context flags.
- Security patterns from the Arcade tutorial demonstrate inserting guardrail nodes between routing decisions and tool execution for authorization checks.
- Deployment flexibility is achieved by wrapping graphs in FastAPI or RunPod handlers while preserving internal routing logic defined in files like
tutorials/runpod-gpu-deploy/crew-ai-ollama-runpod-tutorial/handler.py.
Frequently Asked Questions
How does LangGraph automatically route to the correct tool?
LangGraph matches the tool_call string in the agent's output message against registered tool names. When you decorate a function with @tool("Tool Name"), that name is added to the graph's routing table. Upon execution, if state["tool_call"] == "Tool Name", the graph invokes the corresponding function. This automatic dispatch is demonstrated in tutorials/runpod-gpu-deploy/crew-ai-ollama-runpod-tutorial/handler.py.
What data structure holds state in conditional edges?
The state is a Python dictionary passed to condition functions, typically containing keys like metadata (for routing flags set by agents), output (containing the last tool's return value), and messages (the conversation history). According to the NirDiamant/agents-towards-production source code, you inspect these fields to implement logic such as return "needs_research" in state["metadata"].
How do you create loops in agent graphs for iterative refinement?
Define a conditional edge where the fallback parameter points back to the previous node or agent. For example, if a research tool's output fails a quality check in the condition function, set fallback="search_again" to route back to the search node, creating a loop that exits only when the condition returns True and routes to the target node.
Where can I find examples of secure tool routing with user isolation?
The tutorials/arcade-secure-tool-calling/README.md file demonstrates secure routing patterns where tool requests are intercepted by a guardrail node. This node validates user permissions and context before allowing the graph to proceed to the actual tool execution node, ensuring that multi-user agents cannot execute unauthorized operations.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →