A Framework Agent in Practice

You know tools. You know loops. You know state and graphs. You know what frameworks are for.

This chapter is the payoff: one working agent that solves a real (tiny) job.


The job

ShopTiny support:

  • Customer: “Order 4412 arrived broken — please refund me.”
  • Fake order store in memory (no real database)
  • Two tools: get_order, refund_order
  • Rule: refund only if amount is under $100 (large orders stay “needs human,” like earlier chapters)

The model must call tools. A plain chat reply that invents a refund is not enough.

Customer message → framework agent → tools → final reply.
  Customer message


  ┌─────────────────┐
  │ Framework agent │  ← LLM + tool loop (framework owns the runner)
  └────────┬────────┘
           │ get_order / refund_order

     Fake order store


     Final reply to customer

Same contract — best framework per language

Patterns stay the same. The library changes so you use what each ecosystem actually ships well:

Language Framework Why here
Python LangGraph (+ Gemini via LangChain) You already mapped graphs → LangGraph; strongest Py graph/agent stack
TypeScript LangGraph.js (+ Gemini) Same mental model as Python
Java LangChain4j (AiServices + @Tool) Best plain-Java agent toolkit (no Spring Boot required)
Go Google ADK Official Go agent kit; Gemini-native; tools + runner

Install notes live in each Code file. Put your API key in the practice file (fine for local learning). Do not publish a real key.


Where is the graph?

You will not see add_node / add_edge in this lab’s Code.

That is intentional. The framework already builds the ReAct-style graph:

START → agent (LLM) → tools? → agent → … → END
You write Framework owns
Tools (get_order, refund_order) The agent ↔ tools loop
System / instruction prompt When to stop and return a final reply
One customer message + run Nodes, edges, and the runner

Same ideas as Branching and Graphs — less plumbing. Comments in the Code panel show the hidden shape for each language.


Where are state, updates, and persistence?

Three different “state” ideas show up. Only some are in this lab’s Code.

1. Agent / graph state (conversation)

The framework keeps a message list while the run is alive:

Turn What gets appended
Start Customer (human) message
Model wants a tool AI message with a tool call
Tool finishes Tool result message
Done AI message with the final reply

You do not declare state = { order_id, amount, … } like in Explicit State.
create_react_agent / AiServices / ADK use messages as state. Each step updates that list by appending.

When the run ends, that in-memory list is gone (unless you add persistence — see below).

2. Shop data (your tools)

ORDERS is separate: a tiny fake database.
refund_order modifies it (status = "refunded"). That is normal app data, not LangGraph checkpoint state.

3. Persistence (save / resume) — not wired here

Persistence and Human-in-the-Loop taught save → exit → load → continue.

This lab does not save checkpoints to a file or pause for a human. One invoke / chat / Run, then done.

Frameworks can do that (LangGraph checkpointers, ADK sessions on disk, etc.). We left it out on purpose so this chapter stays “real agent, one happy path.” Comments in Code point to where you would plug persistence later.

Chapter idea In this lab?
Explicit refund fields you update by hand No — replaced by message list + tools
Message list growing each step Yes — framework owns it
ORDERS updated by refund_order Yes — your tool code
Save JSON / resume tomorrow No — see ch 19; optional next step

What “done” looks like

For order 4412 ($12 laptop stand):

  1. Agent calls get_order
  2. Sees a small amount → calls refund_order
  3. Replies that the refund went through

Try order 5501 ($900) yourself: refund should refuse and say a human is needed.


What you should remember

  1. A real agent is LLM + tools + a runner — not a chat demo with fake confidence.
  2. Frameworks differ by language; the job (lookup → decide → act) does not.
  3. After this, multi-agent and MCP are about teams and how tools are plugged in — not about inventing the basic agent loop again.

See it in Code

Open the Code panel. Run the sample for your language. Watch tool calls in the logs, then the final customer reply.