Setup
Accounts, keys, a local Temporal server, Postgres with pgvector, and the repo layout for both language tracks.
Four things run on your machine for the rest of this book: a key, a database, a server, and a repo with two of everything.
That list is short on purpose, and what is missing from it is an argument rather than an oversight. There is no LangGraph here, no Temporal SDK, no AI SDK. Each of those gets installed in the chapter that can say what it buys, because a dependency you installed during setup reads as a prerequisite, and none of them are.
What you need, and when
| First needed in | Why it exists | |
|---|---|---|
| An Anthropic API key | Part I | Everything else is downstream of one messages.create call |
| The repo | Part II | Atlas accumulates across twenty parts; it needs somewhere to live |
| Postgres with pgvector | Part IV | The warehouse and the policy corpus are the same database |
| A local Temporal server | Part X | You cannot demonstrate crash survival against a process you never crash |
Do all four now anyway. It is about twenty minutes, and the alternative is four interruptions spread across a book you were trying to read.
Version floors
| Minimum | Where the floor comes from | |
|---|---|---|
| Node | 20 | LangGraph.js requires it, and so does its TypeScript 5.4 floor |
| Python | 3.11 | Three things want it, and one is the book's own code; nothing needs newer |
| Docker | any current | Only used to run Postgres |
| Temporal CLI | any current | Ships the server and the Web UI in one binary |
Nothing here needs a specific patch version, and pinning one in a book is how you get a chapter that stops working in eight months.
The Python row is worth one more sentence, because the three reasons fail differently. The LangGraph CLI refuses to run; the plan schema is a syntax error on sight; and the Temporal LangGraph plugin loads anyway and emits a warning, then quietly does not honour interrupt(). Only the last one lets you get most of the way through the book before finding out.
1. A model key
Create one at platform.claude.com. console.anthropic.com redirects there. API Keys → Create Key. The full value starts with sk-ant-, and the console shows it exactly once, so paste it somewhere before closing the dialog.
Billing is prepaid credits; there is no free tier. Set a spend cap while you are in there. The API bills per token, and an agent is a loop around a billable function. That combination rewards a ceiling. Running all of Part II end to end against the twenty-ticket sample costs a couple of dollars. The figure is illustrative; Tokens shows how to do the arithmetic yourself rather than trusting a number in a book.
Then export it and install the SDK:
export ANTHROPIC_API_KEY='sk-ant-...'
npm install @anthropic-ai/sdkVerify with the smallest possible call:
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic(); // reads ANTHROPIC_API_KEY
const response = await client.messages.create({
model: 'claude-opus-5',
max_tokens: 64,
messages: [{ role: 'user', content: 'Reply with the single word: ready' }],
});
const block = response.content.find((b) => b.type === 'text');
console.log(block?.text);
console.log(response.usage);Print usage even here, on a call that does nothing. It is one extra line, and a number sitting in that field the whole time answers every cost question in the book: context growth, caching, cost accounting. The habit is cheaper to form now than to retrofit in Part XV.
The key is a payment instrument
It is organization-scoped and it bills whoever holds it. Keep it in a gitignored .env, never in .env.example, and never in a code sample you paste anywhere. A leaked key is not a security incident in the abstract. It is an invoice.
2. Postgres, with pgvector
One container, one volume:
services:
db:
image: pgvector/pgvector:pg17
environment:
POSTGRES_USER: atlas
POSTGRES_PASSWORD: atlas
POSTGRES_DB: atlas
ports:
- '5432:5432'
volumes:
- atlas-pgdata:/var/lib/postgresql/data
volumes:
atlas-pgdata:The pgvector/pgvector images are Postgres with the extension already compiled in; the tag names the Postgres major version. Bring it up and enable the extension. The image ships it, but each database still has to ask for it:
docker compose up -d
docker compose exec db psql -U atlas -d atlas \
-c 'CREATE EXTENSION IF NOT EXISTS vector;'Verify that vectors actually work, rather than that the container is running:
SELECT '[1,2,3]'::vector <=> '[1,2,4]'::vector AS cosine_distance;
-- ≈ 0.00854If that returns a number, Part IV will work. If it errors on the <=> operator, the extension is not installed in this database.
One database, two jobs. Meridian's forty-million-row warehouse and its twelve hundred policy documents both live here. That is a position rather than a convenience. The chapter on where the answer lives argues that splitting structured facts into a warehouse and unstructured text into a separate vector service is the most common and most expensive early architecture mistake. Running one Postgres from the start is what makes the alternative easy to try.
Your corpus survives `down`, not `down -v`
The volume is named, so docker compose down stops the container and keeps the data. docker compose down -v deletes the volume, which means re-embedding the corpus. The chapter that makes that expensive is Chunking.
3. A Temporal server you can crash
Install the CLI, one binary containing the server, the Web UI, and the client:
brew install temporalWithout Homebrew, download the archive for your platform from https://temporal.download/cli/archive/latest?platform=darwin&arch=arm64 (substituting linux/windows and amd64/arm64) and put the binary on your PATH.
Then start it:
temporal server start-dev --db-filename .temporal/atlas.dbgRPC on localhost:7233, Web UI on localhost:8233, and the default namespace created for you.
The --db-filename flag is not optional for this book. Without it, start-dev uses an in-memory database and every workflow history evaporates when you press Ctrl-C. That is fine for a tutorial and useless here, because Part X's entire claim is that a workflow outlives the process running it. Killing the worker is the experiment; killing the history along with it is cheating.
This is a dev server, and it says so
start-dev is one process backed by SQLite. Production Temporal is a cluster with a real database, separate frontend, history, and matching services, and its own failure modes. See Scale and QoS. Nothing in this chapter is a deployment recommendation.
4. The repo, and why it is two of everything
A companion repository, breim/atlas-from-agents-honestly, holds a runnable version of what follows: a small, provider-free kernel with shared TypeScript and Python fixtures, plus one exercise directory per chapter that has one. It is not a second copy of every listing below.
git clone https://github.com/breim/atlas-from-agents-honestly atlasStart there when you want executable checks immediately; grow the full project shape below as the chapters introduce each boundary. The lab environment chapter explains the contract between the companion and the production architecture.
atlas/
├── .env # gitignored
├── .env.example # variable names, never values
├── docker-compose.yml
├── data/
│ ├── policies/ # the policy corpus, sampled
│ ├── tickets.jsonl # the twenty-ticket evaluation sample
│ └── seed.sql # warehouse + CRM fixtures
├── ts/
│ ├── package.json
│ ├── tsconfig.json
│ ├── scripts/
│ └── src/
│ ├── atlas.ts # the loop
│ ├── tools/
│ ├── retrieval/
│ ├── workflows/ # Temporal, from Part X
│ └── eval/
└── py/
├── pyproject.toml
├── scripts/
└── atlas/
├── agent.py
├── tools/
├── retrieval/
├── workflows/
└── eval/The two tracks are siblings, not a primary and a port. They share .env and docker-compose.yml, and the load-bearing part is that they also share data/. Part XIV runs the same twenty tickets against whichever track you built, and an eval that cannot be pointed at two implementations of the same spec is measuring the harness rather than the agent.
The dependency manifests are short, and stay short until Part VII:
{
"type": "module",
"dependencies": {
"@anthropic-ai/sdk": "^0.110.0",
"pg": "^8.13.0",
"pgvector": "^0.2.0"
},
"devDependencies": {
"tsx": "^4.19.0",
"typescript": "^5.4.0"
}
}The pinned versions are illustrative; install current ones. Three packages and a type checker. Everything Part II builds is written against that list: the loop, the tools, the bounds, the outcome union.
What you deliberately did not install
| Arrives in | Because | |
|---|---|---|
@langchain/langgraph · langgraph | Part VII | Part II writes the loop by hand first, so that adopting a framework is a decision with a stated price |
@temporalio/* · temporalio | Part X | Durability is a property you should first feel the absence of |
ai · @ai-sdk/anthropic · @ai-sdk/react | Part XIII | There is no interface until there is something worth streaming |
OpenTelemetry · @opentelemetry/* | Part XV | Instrumenting a system you cannot yet describe produces spans nobody reads |
This ordering is the book's argument expressed as a dependency file. If LangGraph were installed here, you would reasonably conclude it is required. It is not. It is a trade, and What a Framework Buys You is where you get to make it with the hand-written version in front of you for comparison.
One command that checks all four
#!/usr/bin/env bash
set -uo pipefail
fail=0
ok() { printf ' ok %s\n' "$1"; }
bad() { printf ' FAIL %s\n' "$1"; fail=1; }
[ -n "${ANTHROPIC_API_KEY:-}" ] \
&& ok 'ANTHROPIC_API_KEY is set' \
|| bad 'ANTHROPIC_API_KEY is unset'
docker compose exec -T db psql -U atlas -d atlas -tAc \
"select 1 from pg_extension where extname='vector'" 2>/dev/null | grep -q 1 \
&& ok 'postgres up, pgvector installed' \
|| bad 'postgres unreachable or pgvector missing'
temporal operator cluster health --address localhost:7233 >/dev/null 2>&1 \
&& ok 'temporal responding on 7233' \
|| bad 'no temporal server on 7233'
exit $failFour checks, and each one tests the thing rather than a proxy for it: the key is exported, the extension is registered in this database, and the Temporal frontend answers a health RPC. A container that is Up and a database that can do vector math are different claims, and setup chapters that check the first one are why people lose an afternoon in Part IV.
Reading rather than building?
Every sample in this book is complete on the page. The companion lab exists so you can run the failure cases without reconstructing the surrounding harness, not to hide missing code. You can read the whole thing without running any of it. The two places where a running system genuinely changes what you learn are Part X, where the lesson is what a process dying does to an in-flight agent, and Part XIV, where the lesson is a number you have to produce yourself.
References
- Anthropic Console, where API keys are created and usage is visible.
- Temporal CLI setup, install paths and the local development server.
Next: Part I, What an Agent Actually Is, which spends its whole length on the one call you just made.
Takeaways
- Four things: a key, a Postgres with pgvector, a Temporal dev server, and a repo with both tracks. Twenty minutes now beats four interruptions later.
- Print
usagefrom the very first call. Every cost question later is answered by a field that was always there. - The warehouse and the policy corpus share one Postgres on purpose. Splitting them early is the mistake Part IV is about.
temporal server start-devwithout--db-filenameis in-memory. Part X needs a history that survives the process, or its central claim is untestable.- Both language tracks share
data/, so the same evaluation set can be pointed at either implementation. - The breim/atlas-from-agents-honestly companion repository exercises the deterministic failure contracts in both languages without a model key.
- LangGraph, Temporal's SDK, the AI SDK, and OpenTelemetry are absent by design. Each is installed by the chapter that can name what it buys.
- Verify the capability, not the container: check that
pg_extensionhasvector, not that Docker saysUp.