LangGraph builds agents as state machines: nodes do work, edges route control, and the agent loop is something you compose explicitly. LangChain ships the model wrapper (ChatAnthropic) and the @tool decorator; LangGraph ships the graph runtime, plus prebuilt ToolNode and tools_condition helpers.
This recipe is a four-tool browser agent: open_session, navigate, snapshot, extract. Each tool drives a Steel cloud session over Playwright. The graph has three nodes (agent, tools, format) and runs against github.com/trending/python, returning a Pydantic-validated FinalReport.
graph = StateGraph(State)
graph.add_node("agent", agent_node)
graph.add_node("tools", ToolNode(tools))
graph.add_node("format", format_node)
graph.add_edge(START, "agent")
graph.add_conditional_edges(
"agent",
tools_condition,
{"tools": "tools", END: "format"},
)
graph.add_edge("tools", "agent")
graph.add_edge("format", END)
app = graph.compile()If you'd rather skip the explicit construction, langgraph.prebuilt.create_react_agent(model, tools, prompt=SYSTEM, response_format=FinalReport) builds the same three-node graph in one call.
Run it
cd examples/langgraph
cp .env.example .env # set STEEL_API_KEY and ANTHROPIC_API_KEY
uv sync
uv run playwright install chromium
uv run main.pyGet keys at app.steel.dev/settings/api-keys and console.anthropic.com. Each tool call prints its latency; the open_session tool returns a Live View URL you can open in another tab to watch the agent work.
Your output varies. Structure looks like this:
Steel + LangGraph Starter
============================================================
open_session: 1840ms
step: agent -> navigate | 1207 tokens
navigate: 712ms
step: agent -> snapshot | 1502 tokens
snapshot: 412ms (3812 chars, 49 links)
step: agent -> extract | 1741 tokens
extract: 198ms (3 rows)
step: agent -> (text only) | 4998 tokens
step: format
Agent finished.
{
"summary": "Three trending Python repos focused on agentic workflows...",
"repos": [
{
"name": "owner/repo",
"url": "https://github.com/owner/repo",
"stars": "1,240",
"description": "..."
},
...
]
}
Releasing Steel session...
Session released. Replay: https://app.steel.dev/sessions/ab12cd34...A run takes ~20 to 40 seconds and a few cents of Steel session time plus Anthropic tokens. The finally block calls steel.sessions.release(). Skip it and the session keeps billing until the default 5-minute timeout.
Make it yours
- Use the prebuilt. Replace the explicit graph with
create_react_agent(model, tools, prompt=SYSTEM, response_format=FinalReport)fromlanggraph.prebuilt. Same behavior, three lines. - Add a checkpointer. Pass
checkpointer=MemorySaver()tograph.compile(...)and athread_idin the run config. The graph snapshots state after every node, so a crashed run can resume from the last checkpoint. UseSqliteSaver(fromlanggraph-checkpoint-sqlite) for persistence across processes. - Stream events. Swap
app.ainvoke(...)forasync for event in app.astream_events(..., version="v2"). You'll seeon_tool_start,on_tool_end, andon_chat_model_streamevents you can pipe to a UI. - Trace with LangSmith. Set
LANGSMITH_API_KEYandLANGSMITH_TRACING=truein.env. No code changes; every node and tool call shows up at smith.langchain.com. - Swap the model. Any
langchain-*chat model works.ChatOpenAI(model="gpt-5-mini")swaps Anthropic for OpenAI without touching the graph.
Related
OpenAI Agents SDK (Python) · Browser Use · LangGraph docs