Appendix A: Environment, Setup, and the Companion Repo
“Using the Code Examples” in the front matter covers the quick start: clone, uv sync, check out a tag, run it. This appendix is the reference version: the full repo structure, what each seeded backend actually simulates, and where to find what an individual chapter’s text doesn’t have room to print.
Repo structure
The atlas/ package accretes one module at a time, in the order the chapters introduce them. Nothing here is new information. It is the module map for code this book already built, in one place instead of scattered across 27 chapters, with every chapter that printed part of each file:
atlas/
├── naive.py # Ch1 - the while-loop baseline the book argues against
├── breaks.py # Ch1 - ScriptedModel and deterministic failure repros
├── hello.py # Ch2 - hello-world create_agent, naive.py's replacement
├── graph_sketch.py # Ch3 - node-shape skeletons, no wiring yet
├── helpers.py # Ch3, Ch6, Ch7, Ch13 - node-body adapters over the tools
├── graph.py # Ch4, Ch6-7, Ch9-13, Ch17, Ch23 - the support StateGraph
├── state.py # Ch5, Ch6, Ch10, Ch11, Ch13 - AtlasState and reducers
├── clobber_demo.py # Ch5 - the same-superstep clobber, minimized and fixed
├── tools.py # Ch7, Ch16, Ch27 - search_kb, tickets, web, SLA tools
├── agent.py # Ch7, Ch8, Ch12, Ch20, Ch23 - resolve_agent, middleware
├── triage.py # Ch7, Ch10 - structured-output triage, the refund route
├── mcp_server.py # Ch7 - the local stdio MCP server Atlas also consumes
├── middleware.py # Ch8, Ch11, Ch20 - PII, AuthorityGate, RecordingApproval
├── run.py # Ch9-11, Ch14, Ch17, Ch24 - run helpers, run_research
├── effects.py # Ch10, Ch20 - idempotency_key, charge_refund
├── context.py # Ch12 - Budget, select_docs, ContextBudget
├── memory.py # Ch13, Ch14 - profile store, recall, reflect and compact
├── multiagent_decision.py # Ch15 - should_split(), the dial as a function
├── research.py # Ch16, Ch17, Ch20, Ch24 - supervisor, fan-out, recall
├── resolve.py # Ch17 - the mounted resolve agent, build_resolved_graph
├── deep_research.py # Ch18-20 - the Deep Agents form (+ Appendix E's guard)
├── run_research.py # Ch18 - run_deep_research, the Deep Agent's runner
├── stream.py # Ch19 - the multiplexed stream_atlas() entry point
├── tracing.py # Ch20 - configure_tracing, trace_config, OTel export
├── alerts.py # Ch20 - what to page on: detection thresholds
├── planted.py # Ch20 - the planted regression
├── evals.py # Ch21, Ch27 - the eval suite, SLA Watch examples
├── monitor.py # Ch21 - the online quality monitor
├── replay.py # Ch21 - the checkpoint-replay harness
├── security.py # Ch23 - RoleAuthorityGate, InjectionGuard, screening
├── auth.py # Ch23 - server-side identity, DEV_IDENTITIES
├── audit.py # Ch23 - the append-only audit log
├── containment.py # Ch23 - RevocationGate, the ladder's second rung
├── cost.py # Ch23 - TenantBudgetGuard
├── erasure.py # Ch23 - erase_customer
├── stack_decision.py # Ch25 - recommend(), the ADR as a function
├── sla_watch.py # Ch27 - the capstone vertical
├── functional_variant.py # Appendix F - the functional API variant
├── retrieval.py # Appendix G - the optional embedding pipeline
└── deploy/
├── server.py # Ch22, Ch23, Ch27 - the four graphs langgraph.json serves
├── rollout.py # Ch22 - the drain-and-deploy script
├── schedule.py # Ch22, Ch27 - cron and webhook wiring
└── upgrade_check.py # Ch26 - the framework-upgrade regression check
scripts/
├── check_versions.py # Ch2 - the CI version-assertion gate
├── setup_checkpointer.py # Ch9 - the checkpointer schema migration
└── setup_store.py # Ch13 - the store schema migration
tests/ # the suite; conftest.py keeps every run offline
pyproject.toml, uv.lock # Ch2 - dependencies and the exact pins
requirements.txt # Ch2 - the same pins, for pip
langgraph.json # Ch22 - the served graphs
docker-compose.override.yml # Ch22 - N API replicas, one database
ERRATA.md # corrections and later library drift
The repo carries one git tag per chapter increment, named for the chapter’s own file stem (ch09-persistence-checkpointing, ch16-supervisor-pattern, and so on; git tag --list prints them all). The chapter tags mark each increment as the first printing built it. This printing’s listings match the code-v1.2 tag, which is also the tip of main at release; where a chapter’s code changed in this revision, check out code-v1.2, not the chapter tag. Later code accretes on earlier code the same way the atlas/ modules do, and nothing is torn out between chapters: Chapter 1’s naive.py stays as the baseline, and Chapter 2’s hello.py is its replacement.
Figure 1 shows the three ways into the package and where each seeded backend lives.
atlas package: the offline test suite, a script such as atlas/evals.py calling build_resolved_graph() on in-memory stores, and langgraph up or langgraph dev, whose Agent Server runs the four graphs in langgraph.json with its own checkpointer and store. Every seeded backend runs in-process in the module that owns it, except the MCP server, a stdio subprocess; only model calls leave the machine.
The seeded backends
Every external system Atlas talks to is a small, seeded stand-in, in-process except the MCP server, which runs as a local stdio subprocess: no external account and no network call for any of them, and the whole test suite runs offline. The model calls themselves are the exception. Triage, the resolve agent, and the research specialists are real model calls and need a provider key (see “Using the Code Examples” for the three places an account is genuinely required).
| Backend | Introduced | Simulates |
|---|---|---|
_KB |
Ch2 (stub), Ch7 (real tool) | A knowledge-base search index, seeded with two support articles; returns a “no match” string on a miss rather than raising |
_TICKETS |
Ch7 | The ticket system: lookup and status transitions |
_REFUNDS |
Ch1 (naive.py), Ch10 (effects.py) |
The charge record. Chapter 1’s is the baseline’s. Chapter 10’s provider keeps a per-ticket cumulative refunded total and refuses any refund that would exceed the original charge, on any thread |
_LEDGER |
Ch10 | An idempotency-keyed refund ledger, keyed by thread and ticket, modeling a real payment provider’s dedup behavior (Stripe’s Idempotency-Key header is the reference) |
service_status |
Ch7 | The local stdio MCP server’s fixed component statuses |
_WEB |
Ch16 | Web snippets for the web-research specialist; the doc-research specialist searches _KB |
_SOURCES, _THROTTLED |
Ch17, reused Ch18 | Fixed source documents for the map-reduce workers and the Deep Research Agent. A source missing from _SOURCES is unreachable; a throttled one raises a rate-limit error until its count runs out |
DEV_IDENTITIES |
Ch23 | Seeded bearer tokens mapped to an identity and a role (support_agent, support_lead, support_readonly); verify_token is the seam a real deployment replaces |
_SLA_TICKETS |
Ch27 | Ticket ages for SLA Watch: T-2001 (customer C-2, open 30 hours, at risk) and T-2002 (C-3, 10 hours). at_risk(threshold_hours) scans them; send_message(key, ticket_id, message) is idempotent by key and keeps a .sent record, with reset() for tests |
Three store namespaces hold what the runs write, not seed data. ("sla_watch", "flagged") holds SLA Watch’s claims: each names the thread that drafted the check-in and when, a declined draft is released from it, and a claim nobody acted on lapses after 24 hours. ("customer", customer_id, "findings-cache") holds Chapter 24’s cached research findings, one entry per query and set of sources. ("audit", customer_id) holds the append-only audit rows, which since Chapter 27 include its checkin and checkin_send rows.
Every seeded backend is deliberately simple enough to read in full. The point is a reproducible, offline fixture, not a realistic-looking mock that hides how thin it actually is.
Where the rest lives
Tests ship with every increment, tagged the same way the code is. uv run pytest at any chapter’s tag runs that increment’s own suite, not a moving target from a later chapter. They are the reference answer to “did I wire this the way the chapter did”: every named concept the book argues for has a test pinning it, from dedup_by_id’s merge behavior to the refund’s exactly-once guarantee across a retry.
tests/conftest.py keeps the suite offline: unless LANGSMITH_API_KEY is set, it turns tracing off and refuses any connection that leaves the machine, then reports how many it blocked. It also restores the seeded refund provider before every test, since the provider’s cap is cumulative per ticket and one test’s refund would otherwise count against the next.
Exercise solutions are deliberately not shipped. The exercises extend Atlas rather than repeat it, and each one is scoped so the chapter’s own code plus its tests tell you whether you got it right. Where an exercise has a single defensible answer, the chapter says so in the exercise itself.
Trace and eval artifacts are not committed either. A LangSmith trace export is tied to the project and run ids of the account that produced it, so a checked-in copy would be someone else’s data, not something you could open. Chapters 20 and 21 build the tracing and eval suites that generate your own.
Reproducing the environment exactly
Install uv first if you do not have it: curl -LsSf https://astral.sh/uv/install.sh | sh on macOS and Linux, powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" on Windows, or pip install uv if you would rather not run an installer script. Then:
REPO=building-real-world-agentic-ai-systems-with-langgraph-codebase
git clone https://github.com/ranjankumar-gh/$REPO.git
cd $REPO
uv sync # installs the exact pins in uv.lock
uv run python scripts/check_versions.py # Ch2's own CI gate - fails loudly on driftIf check_versions.py fails, the installed environment does not match the version matrix this book was verified against (“Using the Code Examples,” front matter) - resolve that before debugging anything else. A surprising number of “this doesn’t work like the book says” reports trace back to a stale or mixed-version environment, not a bug in the code.
Without uv, pip install -r requirements.txt installs the same pins. The file is exported from uv.lock with the command Chapter 2 prints (uv export --format requirements-txt --no-hashes --frozen --no-emit-project), and a test fails if the two drift.
Keys, and which ones you actually need
The front matter’s table names the three environment variables. This is the operational version: what breaks if a given key is missing, taken from the test suite’s own skip conditions rather than from a list someone maintained by hand. Run uv run pytest -rs and the suite tells you which external dependency each skipped test wanted.
| Missing | What stops working | What still works |
|---|---|---|
ANTHROPIC_API_KEY |
Any run that reaches a real model: the LLM-as-judge evaluator and the Deep Agents research run. | Everything driven by ScriptedModel, which is most of the book’s tests. |
OPENAI_API_KEY |
Semantic recall over the long-term store, and Appendix G’s embedding pipeline. | The in-memory dev store, and every retrieval test that passes explicit vectors. |
LANGSMITH_API_KEY |
Trace export, the hosted datasets, and the online evaluators. | The graph itself. Nothing crashes when tracing is off; Chapter 20 makes that point deliberately. |
ATLAS_POSTGRES_TEST_DSN |
The four live-Postgres tests: the durable checkpointer (Ch9), the production store’s namespace prefix and build_prod_store (Ch13; the second also needs OPENAI_API_KEY), and the store’s TTL sweep (Ch24). |
InMemorySaver and InMemoryStore, which exercise the same code paths. |
ATLAS_AGENT_SERVER_URL |
The scheduling test that needs a running langgraph up server. Note that langgraph up comes from LangGraph’s separate command-line package, which uv sync does not install, and it needs Docker running plus a LangSmith key for the server’s license check. See Chapter 22. |
Everything the compiled graph does in-process. |
ATLAS_UV_CANDIDATE_TEST |
An opt-in, not a key: set to 1, it runs Chapter 26’s upgrade check for real, offline, resolving a candidate’s own environment from the local uv cache. |
The upgrade check’s own logic, tested with each uv step stubbed. |
None of these is required to follow the book. The whole suite runs green offline, and the tests that need an external service skip with a message naming the service they wanted; none of them fails.