Skip to content
EZGraph Get started

No EZGraph key required. Free production use. No runtime fee. Bring your own model provider. Support Jev. Run in your own infrastructure. Optional support is available.

QuoteGraph tutorial

QuoteGraph is a guided car-insurance quote, not a toy conversation. It collects a driver, a catalogued vehicle, an insurance history, and coverage choices. It calculates three quote tiers in code, answers “what if” questions without a second model call, and completes only when the customer accepts a tier from the current quote.

It is the track to read for the core EZGraph contract: LlmNodes whose tool handlers validate input, write durable state, and return go(), stay(), direct(), or finish(). There are no decision nodes here; for those, read the DecisionHotelGraph track.

The implementation lives in ezgraph-demo/src/graphs/quote-graph/, and its tests live in ezgraph-demo/test/quote-graph/. The same application is also written in plain LangGraph in src/graphs/quote-langgraph/; the QuoteGraph case study compares the two.

The node graph

QuoteGraph: DriverNode to VehicleNode, which resolves against the VehicleCatalog, to HistoryNode in its own history space, to CoverageNode, which rates the quote with the RatingEngine and enters QuoteNode; QuoteNode adjusts with direct(), revises back to CoverageNode, or accepts with finish().
Every arrow is a builder returned by a tool handler. The yellow boxes are plain TypeScript modules with no model and no EZGraph imports.

The shape is a pipeline with one loop at the end:

  1. Four collection stages move forward. Each saves its validated facts and returns go() to the next stage, which runs in the same turn. A rejected tool call returns stay() and the model asks again.
  2. Coverage is the pricing boundary. CoverageNode validates the selection against vehicle ownership, calls the rating engine, seeds QuoteNode with the tiers, and enters it.
  3. The quote loops until it is accepted. adjust_quote re-rates and replies with code-written text through direct(). revise_coverage goes back to CoverageNode with the customer’s words. accept_quote checks the tier against the current list and completes with finish().

The six registered nodes

Node History space Owns What it demonstrates
DriverNode quote-intake driver Schema plus calendar, age, state-code, and licence rules; the entry node
VehicleNode quote-intake resolvedVehicleId, vehicle Two tools, lookup before capture, trim disambiguation, a prompt that reacts to entry
HistoryNode quote-incidents history An isolated history space; month-precision date rules
CoverageNode quote-intake coverage A lender rule, deterministic rating, and seeding another node’s state
QuoteNode quote-present tiers, acceptedTier, referenceNumber direct() answers, a backward route with a forwarded request, finish()
TerminateSessionNode quote-terminal nothing Ending the conversation at the customer’s request

Supporting files

The graph, state, and node files import from @picoflow/ezgraph. The backend modules are plain TypeScript that a unit test can call directly. Each node loads its Markdown prompts with Prompt.file() at module scope and renders live values with Prompt.replace() in getPrompt().

File Responsibility
quote-graph.ts Graph definition, idle-session policy, and topology
quote-graph.state.ts Domain types, the node-state registry, and the generated LangGraph annotation
backend/quote-clock.ts “Today” (pinnable with QUOTE_GRAPH_CURRENT_DATE) and strict date arithmetic
backend/vehicle-catalog.ts Loads data/vehicles.json and searches it by year, make, model, and trim
backend/rating-engine.ts Coverage validation, the rating subject, the risk factor, premiums, and tiers
data/vehicles.json Twelve ratable vehicles with trim, body style, risk group, and MSRP
nodes/*.node.ts Load role and stage prompts directly, render {{PLACEHOLDER}} values, and append the local end-chat instruction
prompt/role.md Persona, tone, and the termination rule shared by every stage
prompt/driver.md, vehicle.md, history.md, coverage.md, quote.md One stage specification per node

What this track does and does not cover

Feature In QuoteGraph?
LlmNode tools with Zod schemas and @Tool handlers yes, all five stages
go(), stay(), direct(), finish() yes
withMessage() stage instructions and a forwarded customer request yes
Writing another node’s state with graph.saveNodeState() yes, CoverageNode and QuoteNode
Separate history spaces yes, four spaces
A per-node model configuration with getLlmConfig() yes, QuoteNode
Session expiry with onRestoreSessionDoc() yes
A pinnable business clock yes
directTo() no; see the DecisionHotelGraph track
Decision nodes and Jev no; see the DecisionHotelGraph track
File attachments and JSON response mode no
Schema versions and migrations no; the graph uses the default schema version 1

The ten lessons

  1. A fifteen-turn live replay — the recorded quote, then the tools and transitions behind every turn.
  2. Graph, state, and ownership — the graph definition, the typed state registry, and who writes each value.
  3. Anatomy of a conversation turn — what the engine, the node, and the agent loop do between a customer message and a reply.
  4. Prompts and stage handoffs — direct Prompt.file() loading, Prompt.replace() templating, and three ways to start the next stage well.
  5. Validated collection — schemas as the interface and code as the policy, in the driver and history stages.
  6. Catalog lookup and disambiguation — resolve a vehicle before capturing how it is used.
  7. Time, sessions, and history spaces — a pinnable clock, idle expiry, and four separate conversations.
  8. Deterministic rating — coverage rules, the risk factor, and a worked premium from the replay.
  9. Revisions, direct responses, and acceptance — the quote loop: adjust, revise, and accept.
  10. Testing the whole quote — unit, graph, and session-policy tests, then the live semantic evaluation.

Running it

cd ezgraph-demo
npm run test:quote-graph
npm run test2:quote-graph

The first script runs the deterministic suite with a scripted chat model; the provider-backed E2E file it also matches is skipped. The second sets USE_ENV=1 KEEP_SESSION=1, runs the fifteen-turn semantic scenario against the configured model provider, and keeps the session for inspection.

Both tiers pin QUOTE_GRAPH_CURRENT_DATE to 2027-06-01, so ages, incident windows, start dates, and premiums are identical on every run.

Next

Start with 1. A fifteen-turn live replay.