Skip to content

Chapter 12 · Capstone: evidence-grounded local QA ​

Combine retrieval, no-evidence routing, and answering. A fixed in-memory corpus and deterministic response template make the workflow verifiable offline. Replace the retriever or answer node independently later.

Mechanics and design choices ​

The flow is retrieve → route → answer/refuse. State explicitly carries evidence and answer, instead of trusting a model’s claim that it searched. Empty evidence causes refusal. Real RAG also needs source IDs, access controls, retrieval evaluation, and citation validation. This fixture lookup uses exact course keys, not semantic search or a production vector system.

Example ​

python
from typing import TypedDict
from langgraph.graph import StateGraph, START, END

CORPUS = {"langgraph": "LangGraph orchestrates stateful workflows.",
          "deepagents": "Deep Agents adds an agent harness on LangGraph."}

class State(TypedDict):
    question: str
    evidence: str
    answer: str

def retrieve(state: State):
    return {"evidence": CORPUS.get(state["question"].strip().lower(), "")}

def route(state: State):
    return "answer" if state["evidence"] else "refuse"

def answer(state: State):
    return {"answer": state["evidence"] + " [source: local-course-corpus]"}

def refuse(state: State):
    return {"answer": "No evidence found. Please choose a known course."}

builder = StateGraph(State)
for name, function in [("retrieve", retrieve), ("answer", answer), ("refuse", refuse)]:
    builder.add_node(name, function)
builder.add_edge(START, "retrieve")
builder.add_conditional_edges("retrieve", route, {"answer": "answer", "refuse": "refuse"})
builder.add_edge("answer", END)
builder.add_edge("refuse", END)
graph = builder.compile()
for question in ["langgraph", "unknown"]:
    result = graph.invoke({"question": question, "evidence": "", "answer": ""})
    assert bool(result["evidence"]) == (question == "langgraph")
    print(result["answer"])

Run and verify ​

Run known and unknown queries to obtain a sourced answer and a refusal. Inspect evidence and answer together rather than checking only that text exists. Continue with Agent Engineering in Production; this chapter performs no cloud deployment.

Pitfalls ​

Wrapping invoke in HTTP is not sufficient for production. Add validation, tenant isolation, timeouts, cancellation, redacted logs, persistence, and regression fixtures. Re-run empty-result and authorization tests when replacing retrieval.

🧪 随堂测验

点击你认为正确的选项。答错时会展示正确答案与原因解析。

1. What happens without evidence?

2. Is this semantic search?

3. Should retrieval replacement trigger tests?

4. Is an HTTP wrapper sufficient for production?

Hands-on exercises ​

  1. Give each evidence record an ID and require matching citations.
  2. Replace retrieval while retaining the no-evidence refusal test.
  3. Add human review before exporting a local report.

Official references ​

Verified on: 2026-09-17.