LangGraph Agents

Course Content

LangGraph Agents

7 sections · 49 lessons

How do you implement structured tool outputs and robust parsing in a graph workflow?


What you need to know

Into the tool

Python
from typing import Literalfrom pydantic import BaseModel, Fieldfrom langchain.tools import toolclass RefundArgs(BaseModel):    order_id: str = Field(pattern=r"^OD-\d{5,}$", description="Order id like OD-88123")    amount_inr: int = Field(gt=0, le=100_000)    reason: Literal["damaged", "not_delivered", "wrong_item", "other"]@tool(args_schema=RefundArgs)def issue_refund(order_id: str, amount_inr: int, reason: str) -> dict:    """Issue a refund for a delivered order. Needs human approval above Rs 5,000."""    return {"refund_id": "RF-" + order_id[3:], "status": "queued", "amount_inr": amount_inr}

The docstring and field descriptions become what the model reads. Pattern and range checks run before the function body.

Out of the tool

  • Return a dict or a list of dicts with stable keys.
  • Keep what the model needs short; put the full result in state if other nodes need it.
  • A tool can return Command(update={...}) to write typed state directly, including a ToolMessage for its call.

Final structured answer

Python
class Decision(BaseModel):    decision: Literal["refund", "replace", "reject"]    amount_inr: int    reason: stragent = create_agent("anthropic:claude-sonnet-4-5", tools=[...], response_format=Decision)result = agent.invoke({"messages": [...]})result["structured_response"]            # a Decision object

response_format uses the provider's native structured output when supported, or a tool-call strategy otherwise (ProviderStrategy, ToolStrategy).

Repair on failure

On a ValidationError, write the error and the bad output to state and route to a repair node that shows both to the model. Two attempts, then a fallback such as a human queue.

Size control

A tool returning 500 rows into messages fills the context window. Summarise, paginate, or return the top N plus a count.

A real-life example

A logistics company's agent answered "where is my parcel?" by calling a tracking API that returned 4 KB of raw scan events. The model sometimes read an old "Out for delivery" line as current. The team changed the tool to return {"status": "IN_TRANSIT", "last_scan": "Nagpur hub", "eta": "2026-09-26"} and put the full event list in state for a support dashboard. Wrong-status answers fell from 7% to under 1%, and each turn used 1,100 fewer tokens.

Follow-up questions to expect

  • "What if the model keeps producing invalid arguments?" — Improve field descriptions and examples first; then cap retries and fall back. Constant invalid calls usually mean the schema is confusing.
  • "JSON mode or structured output?" — Structured output with a schema. JSON mode guarantees valid JSON, not your fields.
  • "Where do you validate business rules like 'refund less than order value'?" — In the tool or a policy node with access to the order, since the schema alone does not know the order.