Skip to main content
In this lesson we show how to build a small, agentic workflow using LangGraph’s conditional edges to route between execution paths. The demo is intentionally compact: based on the user’s question, the graph will either perform a live web search via Tavily or answer immediately using an LLM. Both routes converge into a final formatting step. You can also generate a visual representation (Mermaid) of the graph to inspect routing and convergence. Key concepts covered:
  • State-driven routing using conditional edges
  • Composable nodes that read/write shared typed state
  • Converging branches into a single terminal formatter
  • Integrating external APIs (OpenAI Responses API and Tavily search)

Setup and imports

Install dependencies if needed (uncomment the pip line in a fresh environment), then initialize clients and environment variables.
Make sure OPENAI_API_KEY and TAVILY_API_KEY are available in your environment before running the examples. Leaving keys in source code is not recommended for production.
This example uses:
  • OpenAI Responses API client for LLM calls.
  • Tavily client for web search; the exact method name for searching may vary by SDK version—adapt as needed.

Typed shared state

We define a typed AgentState that nodes will read from and write to. LangGraph’s nodes interact through this shared state rather than direct node-to-node parameter passing.
The state begins with question and accumulates intent, search_results, draft_answer, and final_answer as the graph runs.

Node overview

We implement four nodes: Use the table above to quickly see responsibilities and expected state writes.

classify_intent

This node returns a single label — "search" or "answer" — which controls conditional routing.
Use a terse classifier prompt to minimize hallucination and to make the decision deterministic. If you want higher fidelity, consider a small validation step after classification.

search_web

This node fetches results from Tavily and normalizes them into a simple list of dictionaries with title, url, and content.
Notes:
  • SDKs differ: if tavily_client.search returns a paged object or resp.results, adapt the extraction accordingly.
  • Keep the normalized output small and consistent to simplify downstream formatting.

answer_direct

Ask the LLM to answer concisely without performing a web lookup. The draft is stored in draft_answer.

format_output

The final node handles both branches:
  • If intent == "search", it formats Tavily results into a readable summary.
  • If intent == "answer", it returns the LLM’s draft answer.

Wiring the graph

We wire the graph to start at classify_intent, branch conditionally to search_web or answer_direct, and then converge at format_output before transitioning to END.
Conditional edges let the graph decide the next node dynamically based on the current state. This makes branching explicit, easier to reason about, and straightforward to visualize.

Run examples

Run two sample invocations to exercise both routes:
Expected behavior:
  • The first question should choose answer, produce draft_answer via the LLM, and return it as final_answer.
  • The second should choose search, fetch results with Tavily, and return a formatted list of top matches.

Visualize the graph

To inspect control flow and conditional edges, export the graph as Mermaid source and render it in any Mermaid-compatible tool (for example, mermaid.live or the VS Code Mermaid preview). Many graph implementations expose a method such as to_mermaid() or get_mermaid()—check your graph object’s API. Recommended rendering steps:
  1. Get the Mermaid source string from your graph object.
  2. Paste the Mermaid code into an external renderer (e.g., https://mermaid.live/).
  3. Inspect branching points and convergence to verify the routing.

Extending this pattern

This pattern scales well:
  • Add more classifier labels and map them to additional tool nodes via add_conditional_edges.
  • Insert validation or hallucination-checking nodes before the formatter.
  • Persist important facts into memory nodes that future queries can read.
References and further reading:

Watch Video