~15–20 hrs
Requires: Projects 0508
Project 09 of 9 · Capstone

Personal Learning OS

The whole course, assembled into one system — a single front door that routes each request to the right specialist, with a trail you can trust

📖 Read the lesson ✍ Fill in understanding 🛠 Build the project 🚫 Break it 📊 Evaluate it

Learning Objectives

By the end of this capstone, you will be able to:

  • Describe a multi-capability AI app as an augmented LLM assembled into a system (retrieval + tools + memory), and see the eight prior projects as subsystems of one OS.
  • Implement query routing — classify a request and "direct it to a specialized followup task" — and explain why that buys "separation of concerns."
  • Justify a routing precedence and a safe default: order the checks so a high-stakes intent (save) is never shadowed by a generic one, and fall back to the cheapest safe route.
  • Build an orchestrator that routes, dispatches to one subsystem, and synthesizes a response with provenance — which route handled it and which items it used.
  • Build a lightweight personal knowledge graph that links saved items by shared tags and surfaces related ones.
  • Evaluate the system, not just a part: measure routing accuracy overall and per route, and explain why a mean hides a silently-broken route.
  • Apply "use the simplest thing that works" at the system level: route a simple lookup to a single retrieval, reserve the agent for the genuinely open-ended request.
  • Name the major failure modes of an orchestrated system (a dropped save, everything-to-the-agent, no provenance, a router that regresses unseen) and the decision that prevents each.

1. Motivation

Why This Exists

By Project 08 you have eight working capabilities: a chatbot (P01), embeddings (P02), semantic search (P03), retrieval with citations (P04), a memory system (P05), a tool-using copilot (P06), an evaluation harness (P07), and a reliable autonomous agent (P08). Each runs on its own. But a person doesn't think in projects — they say "remember this," "what did I note about X," "summarize everything I've saved on Y," or just "explain this to me." A Personal Learning OS is the front door that takes any of those and sends it to the right capability. The new problem is no longer how to build a retriever or an agent — you've done that. It's how to compose them.

The Core Problem

Without a router you have two bad options. One giant prompt that tries to save, recall, reason, and act in a single call is unreliable (it conflates "remember this" with "answer this"), unauditable, and expensive (you pay for the agent's machinery on a trivial lookup). Making the user pick the tool — a "save" button, a "search" tab — pushes your system's complexity onto the user and defeats the single front door. Routing is the third option: the system classifies the request and dispatches it to a specialized subsystem.

What Breaks Without It

The cost of routing wrong is concrete: mis-route a "remember my doctor's appointment" to small-talk chat and the note is silently lost; mis-route a one-line lookup to the agent and you've spent ten steps and real money on something a single retrieval would have answered. A system with brilliant specialists and a bad front door feels broken even when every individual subsystem works perfectly.

Real-World Stakes

This is the shape of every "AI assistant" product: a single conversational surface backed by many specialized capabilities. ChatGPT routes between chat, browsing, code execution, and image generation. A personal-knowledge tool routes between capture, recall, and synthesis. The product is not any single capability — those are commodities. The product is the orchestration: the right specialist for the request, every time, with a trail you can inspect.

Startup Lens

This is StarcallOS in miniature. People pay for the integration — one interface that quietly does the right thing — not for yet another chatbot. The capabilities are table stakes; the seamless routing and the trustworthy, auditable answers are the moat. And the discipline that protects the bill is P08's, lifted to the system: route the simple request to the cheap subsystem, reserve the expensive agent for the request that genuinely needs it.

2. Mental Model

Explain Like I'm 12

Imagine a big help desk with one friendly person at the front and four expert rooms behind them. You walk up and say anything. The front-desk person's only job is to figure out which room you need: the Filing Room if you're handing them something to keep ("remember this"), the Library if you're asking for something you stored before ("what did I write about my trip?"), the Workshop for a big multi-step job ("go through all my notes about France and make me a summary"), or the Chat Couch if you just want to talk. If they guess wrong, bad things happen: hand a note to the Couch and it gets thrown away; send a one-second question to the Workshop and you wait an hour for what the Library could've handed you instantly. So they follow simple rules — "if they're handing me something to keep, that's always the Filing Room first" — and when they truly can't tell, they default to the Couch, which is safe and cheap. This project is you building that front desk.

Explain Like I'm a Software Engineer

  • The OS is the augmented LLM as a system: retrieval (P03/P05), tools/agent (P06/P08), and memory (P05), wired behind one entrypoint. The subsystems are provided (you built them); the learning target is the composition.
  • route_query(query) -> Route is a classifier. Deterministic and signal-based so it's offline-testable: match intent markers, score them, return the highest-precedence route above a confidence threshold, else the safe default (CHAT). Production routing "can be handled by an LLM or a more traditional classification model."
  • Precedence is correctness, not style. SAVE is checked before CHAT because a dropped save is a data-loss failure; TASK (the agent) is gated so only genuinely multi-step requests reach it.
  • LearningOS.handle(query) is the orchestrator: route → look up the subsystem in a dispatch table → call it → wrap the result in a Response carrying route, reason, and provenance.
  • KnowledgeGraph links saved items by shared tags; related(id) returns neighbors ranked by shared-tag count — the reflection idea at engineering scale.
  • evaluate_routing(cases, route_fn) scores the router on a frozen labeled set: overall accuracy and per-route accuracy, plus the misroutes.

Real-World Analogy

Analogy

The OS is a hospital triage nurse. Every patient comes through one door and describes their problem in their own words. The nurse doesn't treat anyone — their single, high-stakes skill is routing: chest pain to cardiology now, a sprained wrist to orthopedics, a question about results to records, and "I just feel off" to general intake (the safe default). Triage has strict precedence — life-threatening symptoms are checked first, never shadowed by a minor complaint — because the cost of mis-triaging the emergency is catastrophic. And every patient gets a chart: which department, why, what was done — provenance. A hospital with brilliant specialists and a bad triage nurse is a dangerous hospital. The OS is the nurse; P01–P08 are the departments.

How It Works (Diagram)

 REQUEST: "remember that my StarcallOS demo is on June 20"
   │  route_query → matches SAVE markers ("remember that") → Route(SAVE)
   ▼  handle → store.save(item, tags=[...]) → graph.add(id, tags)
   ▼  Response(answer="Saved.", route="SAVE", provenance=[item#42])

 REQUEST: "what did I save about StarcallOS?"
   │  route_query → matches RECALL markers ("what did I save") → Route(RECALL)
   ▼  handle → store.recall("StarcallOS") → [#42, #17]
   ▼  Response(answer="You noted: demo on June 20; …", route="RECALL", provenance=[#42,#17])

 REQUEST: "go through everything I know about StarcallOS and draft a status summary"
   ▼  Route(TASK) → bounded agent over the store (P08) → multi-step synthesis

 REQUEST: "what's the difference between recall and precision?"   (no personal data)
   ▼  no strong signal → Route(CHAT, safe default) → single LLM call

 evaluate_routing(labeled_cases, route_query)
   ─► {accuracy: 0.92, per_route: {SAVE:1.0, RECALL:0.9, TASK:0.8, CHAT:0.95}, misroutes:[…]}

3. Technical Explanation

Formal Definition

Routing is the workflow where the system "classifies an input and directs it to a specialized followup task." It "allows for separation of concerns, and building more specialized prompts." A route is one of a fixed, small set {SAVE, RECALL, TASK, CHAT}, each bound to exactly one subsystem; route_query returns the chosen route plus a reason and a confidence. The orchestrator follows the orchestrator-workers pattern: a central component that "dynamically breaks down tasks, delegates them to worker [subsystems], and synthesizes their results." Provenance is the set of item ids / source pointers that produced the answer. A knowledge graph here is an undirected weighted graph where an edge's weight is the number of tags two saved items share.

How It Works Step by Step

  1. Classify the request (routing). route_query scans the text for intent markers per route, scores each, and selects the highest-precedence route whose confidence clears the threshold; if none does, return the safe default CHAT. Precedence — SAVERECALLTASKCHAT — ranks routes by the cost of mis-routing.
  2. Dispatch to one subsystem. handle looks the route up in a dispatch table and calls exactly one subsystem. One request → one specialist — the "separation of concerns" routing buys.
  3. Synthesize with provenance. Each subsystem returns a SubsystemResult(answer, sources). The orchestrator wraps it into a Response(answer, route, reason, provenance=sources) — what makes the system auditable.
  4. Grow the graph on save. When the route is SAVE, the save worker records the item and links it into the graph by shared tags. Later, recall can surface connected notes.
  5. Evaluate the router. evaluate_routing runs over a frozen labeled set and computes overall accuracy, per-route accuracy, and the explicit misroute list — the only way to catch a route that's silently at 0%.

Key Concepts

ConceptDefinitionWhy It Matters
Augmented LLM as a systemAn LLM enhanced with retrieval, tools, and memory — the eight prior projects wired into one appThe capstone is the realization that P01–P08 were always parts of one system
Query routing"Classifies an input and directs it to a specialized followup task"One front door, many specialists: each gets a narrower job and a focused prompt
Precedence + safe defaultAn ordered set of route checks with a fallback to the cheapest safe routeThe order is a correctness decision — a mis-ordered router silently drops a "remember this"
Orchestrator (orchestrator-workers)Routes, delegates to a worker subsystem, and synthesizes the resultThis is the OS: route → dispatch → assemble, with provenance attached at synthesis
ProvenanceThe response carries which route handled it and which items it usedAn orchestrated answer with no trail is an unauditable black box
Personal knowledge graphSaved items linked by shared tags; "related" = neighbors by shared-tag weightTurns a flat list into a navigable structure — reflection at engineering scale
System-level evaluationRouting accuracy overall and per route on a frozen setA 90%-overall router can be 0% on save; only per-route numbers expose it
Common Misconception

Routing order is not cosmetic. Precedence encodes the asymmetric cost of mistakes: SAVE first because a dropped save is silent data loss; CHAT last because it's the cheap, safe catch-all. Reordering the checks changes the system's behavior even with identical markers. And the safe default must be the cheapest, least-destructive route (CHAT) — never TASK (which burns agent cost) and never silently SAVE (which stores junk).

4. Guided Examples

The lab stack: the provided subsystem kernel (MemoryStore, the dispatch table, an injected chat), a deterministic signal-based router, a tiny pure-Python graph, and a pure-logic evaluator. Examples mirror the guiding tests; all run offline.

Example 1: Simplest Case — classify a request

from router import route_query

route_query("remember that my StarcallOS demo is on June 20").name   # -> "SAVE"
route_query("what did I save about StarcallOS?").name                # -> "RECALL"
route_query("go through all my notes on France and draft a summary").name  # -> "TASK"
route_query("explain the difference between recall and precision").name    # -> "CHAT"  (safe default)

r = route_query("remember to email Sam")
print(r.name, "|", r.reason)   # SAVE | matched SAVE markers: ['remember']
What to Observe

The router maps free-text intent to a small fixed set of routes, and returns why (reason) — not just a label. The fourth request has no save/recall/task signal, so it falls to the safe default CHAT. The classification is the entire front door of the system.

Example 2: Real-World Case — orchestrate a request end to end

from learning_os import LearningOS
from subsystems import MemoryStore, make_subsystems
from knowledge import KnowledgeGraph

store, graph = MemoryStore(), KnowledgeGraph()
# fake chat fn so this is offline; the real app injects a LiteLLM-backed one
os_ = LearningOS(make_subsystems(store, graph, chat=lambda msgs: "(chat answer)"), graph)

r1 = os_.handle("remember that StarcallOS uses a routing front door")   # SAVE
print(r1.route, r1.provenance)        # 'SAVE' [<id of the new item>]

r2 = os_.handle("what did I save about StarcallOS?")                    # RECALL
print(r2.route, r2.provenance)        # 'RECALL' [<id of item saved above>]
What to Observe

One entrypoint (handle) routed two different requests to two different subsystems, and every response carries route and provenance. The save flowed into the store and the graph; the recall pulled it back out. The orchestrator never did any retrieval or saving itself — it routed and synthesized.

Example 3: When It Fails — the per-route number a mean hides

from evaluate_os import evaluate_routing
from router import route_query

cases = [
    {"query": "remember to call mom", "expected_route": "SAVE"},
    {"query": "note: buy milk", "expected_route": "SAVE"},
    {"query": "what did I note about milk?", "expected_route": "RECALL"},
    {"query": "summarize everything I saved this week", "expected_route": "TASK"},
    {"query": "what is a vector database?", "expected_route": "CHAT"},
]
report = evaluate_routing(cases, route_query)
print(report["accuracy"])     # e.g. 0.8  (overall — looks fine)
print(report["per_route"])    # e.g. {'SAVE': 1.0, 'RECALL': 1.0, 'TASK': 0.0, 'CHAT': 1.0}
print(report["misroutes"])    # [{'query': 'summarize everything I saved this week', ...}]
Why This "Fails"

Overall accuracy of 0.8 looks fine — but per_route reveals TASK is 0%: every multi-step request is being mis-routed. The mean hid a completely broken route. This is the P07/P08 lesson (measure per case, not just the average) applied to the system's front door, and it's how you'd find that your router needs better TASK markers.

5. Reflection Before Building

Stop Here

Before writing any code, fill in UNDERSTANDING.md in your own words. No copy-pasting from the lesson. No AI assistance for writing — only for checking. If you can't explain it simply, go back and re-read.

Knowledge Check — Answer These in UNDERSTANDING.md

  1. In your own words, what is query routing, and why does "classify then dispatch to a specialist" give a more reliable system than one giant prompt that tries to do everything?
  2. Routing precedence is a correctness decision. Why must SAVE be checked before CHAT, and why must the safe default be CHAT rather than TASK or SAVE? Name the concrete failure each rule prevents.
  3. The orchestrator returns route, reason, and provenance on every response. Why is that part of the contract and not just logging — who needs to read them, and what breaks if handle only printed them?
  4. Predict the four failure modes of: (a) mis-routing a SAVE to CHAT, (b) routing every request to TASK, (c) returning answers with no provenance, (d) shipping a router change with no evaluation. Which design decision prevents each?
  5. Why does evaluate_routing report per-route accuracy and not just an overall mean? Describe a router that scores 90% overall but is dangerous.
  6. The knowledge graph links saved items by shared tags. Why link incrementally on each save instead of rebuilding all pairs, and why must a node never be related to itself?
  7. Give one request you would route to a single retrieval (RECALL) and one you would route to the agent (TASK), and justify why the first does not need the agent.
  8. The one thing you still don't fully understand about composing subsystems into one system.

After filling in UNDERSTANDING.md, use the AI mentor pattern in docs/meta/learning-flow.md to get feedback. Record it in UNDERSTANDING_FEEDBACK.md.

6. Project Assignment

See PROJECT.md and source/project.md for the full specification including file structure and extended requirements.

Core Requirement

Build the composition layer that turns eight separate capabilities into one Personal Learning OS, in code/:

  • router.pyroute_query (M1) is the learner core: the deterministic, precedence-ordered, safe-default classifier that is the system's front door.
  • knowledge.pyKnowledgeGraph.add / .related (M2) is the learner core: link saved items by shared tags and surface related ones, incrementally.
  • learning_os.pyLearningOS.handle (M3) is the learner core: the orchestrator — route → dispatch to one subsystem → synthesize a Response with provenance.
  • evaluate_os.pyevaluate_routing (M4) is the learner core: score the router overall and per route on a frozen set, and list the misroutes.
  • subsystems.py — the provided kernel: MemoryStore, make_subsystems, and the four workers. (Provided — they stand in for P01/P03/P05/P08.)
  • os_app.py — the orchestrator app: a real LiteLLM chat, the subsystems, a REPL that prints route + reason + answer + provenance. (Provided.)

Extended: an LLM-backed router compared against the deterministic one with evaluate_routing; provenance passed into the prompt for inline citations; graph-aware recall that expands hits with related(id); a reflection job that summarizes recent items; threshold tuning for routing precision/recall.

Definition of Done

route_query classifies by precedence with a safe default and never sends an unsure request to TASK/SAVE; handle dispatches to exactly one subsystem and returns a Response with route + provenance; saves flow into the store and the graph; KnowledgeGraph is incremental, symmetric, self-free; evaluate_routing reports overall + per-route + misroutes; the guiding tests pass; UNDERSTANDING.md done before any code; FAILURE_ANALYSIS.md has ≥3 experiments (incl. mis-ordered precedence and everything-to-TASK); EVALUATION.md is per-route; STARCALLOS_REFLECTION.md names ≥1 concrete pattern.

Start building

Open code/README.md for setup, the milestone build order, and the file roles (which files are provided vs. learner-owned). Run python -m pytest to see the failing guiding tests, then implement the learner-owned functions in milestone order until they pass.

7. Project Milestones

Work through these in order. Each milestone should produce runnable code before moving on.

1

M1 — Query router

router.route_query(query, threshold) — classify into {SAVE, RECALL, TASK, CHAT} by precedence, with a safe default. Validation: save/recall/task phrasings route correctly; an unsignaled request → CHAT (offline test).

2

M2 — Knowledge graph

knowledge.KnowledgeGraph.add(id, tags) + .related(id) — link by shared tags, incrementally; rank neighbors. Validation: items sharing tags become neighbors ranked by shared-tag count; no self-edge; symmetric (offline test).

3

M3 — Orchestrator

learning_os.LearningOS.handle(query) — route → dispatch → Response(answer, route, reason, provenance). Validation: a save then a recall round-trips through the store; every response carries route + provenance; exactly one subsystem runs (offline test with fake subsystems).

4

M4 — Evaluate routing

evaluate_os.evaluate_routing(cases, route_fn) — overall + per-route accuracy + misroutes. Validation: a labeled set yields correct numbers; a broken route shows as 0% per-route while overall stays high (offline test).

5

M5 — OS end-to-end

os_app.py runs the REPL on a real provider, routing live requests through the subsystems. Validation: type "remember …", then "what did I save about …", then a synthesis request; see distinct routes + provenance printed.

6

M6 — Break / Evaluate

Mis-order precedence (CHAT first), drop the safe default, route everything to TASK, and strip provenance. Validation: a dropped/lost save / nonsense routes / cost+latency blow-up / unauditable answers — each recorded in FAILURE_ANALYSIS.md.

8. Self-Evaluation

After building, honestly evaluate your implementation against these criteria. Record your answers in EVALUATION.md.

CriterionDoes your implementation...Pass?
Routing precedencecheck high-stakes intents (SAVE) before generic ones, so a "remember this" is never shadowed by CHAT?
Safe defaultfall back to the cheapest, non-destructive route (CHAT) when no signal is strong — never to TASK or SAVE?
One specialist per requestdispatch each request to exactly one subsystem via the table — not run several or inline their logic in handle?
Provenance returnedput route, reason, and the used item ids/sources in the returned Response, not just print them?
Graph incremental + correctlink a new item to existing items by shared tags in one pass, with no self-edge and symmetric edges?
System-level evalreport routing accuracy per route, not only the overall mean, and surface the misroutes?
Right specialist for the jobroute a simple lookup to RECALL and reserve TASK for genuinely multi-step requests — and can you name one of each?
Red Flags

Your implementation may have problems if:

  • CHAT is checked first or is the highest-precedence match, so saves and recalls leak into small talk.
  • Your safe default is TASK (every unsure request spins up the expensive agent) or SAVE (you store junk).
  • handle retrieves or saves itself instead of dispatching to a subsystem — the orchestrator is doing a worker's job.
  • Response has no route/provenance, so a caller can't tell what happened or audit the answer.
  • KnowledgeGraph.add rebuilds every pair each call (O(N²)) or links a node to itself.
  • Your evaluation reports a single accuracy number, so a route that's silently 0% looks fine.

9. Common Mistakes

MistakeWhy It HappensConsequenceFix
Checking CHAT (or the broadest route) first"Most requests are chat"Saves/recalls get swallowed as small talk and silently lostOrder checks by the cost of mistakes: SAVERECALLTASKCHAT
Safe default = TASK"When unsure, let the agent figure it out"Every ambiguous request costs agent steps + moneyDefault to CHAT; gate TASK behind clear multi-step signal
handle does retrieval/saving itself"It's just one line, I'll inline it"Orchestrator and subsystems blur; no separation of concerns; untestableDispatch through the table to exactly one subsystem; handle only routes + synthesizes
Provenance printed, not returned"I can see it in the logs"Callers/tests/evaluators can't inspect the decision; not auditablePut route, reason, provenance in the Response
Graph rebuilt every save"Recompute all pairs to be safe"O(N²) per save; quadratic blow-up; slows every captureLink the new node to current members in one pass; keep edges incremental
Node related to itselfforgot to skip id == other"Related notes" always lists the note you're onSkip self when adding edges and when returning related
One overall accuracy number"90% — good enough"A route silently at 0% is invisible; the system looks healthy and isn'tReport per-route accuracy + the misroute list
Routing everything through the agent"The agent can do anything"Slow, costly, less reliable than a single retrieval for simple asksRoute by need; "add complexity only when it demonstrably improves outcomes"

10. Connections

Builds On

This is the whole course assembled into one system. CHAT is Project 01 (a single completion). RECALL is Projects 03 and 05 (retrieval over a memory store). SAVE is Project 05 plus the new knowledge graph. TASK is Project 08's reliable agent (and through it, Project 06's tools). The provenance the orchestrator attaches is Project 04's citation discipline. The evaluation of the router is Project 07/08's "numbers, per case" discipline pointed at the front door. Nothing here re-teaches a capability — every subsystem is provided precisely because you already built it. The new work is the one thing the prior projects deliberately left out: how to compose them.

Enables

This is the terminal project of the core curriculum — but it's the first project of building a real product. Everything beyond here is depth on a subsystem (better retrieval, a smarter router, more tools, richer evaluation) or breadth (more routes, more capabilities behind the same front door). The pattern you build — one entrypoint, a router, a dispatch table, provenance, and a system-level eval — is the skeleton every multi-capability AI app grows on.

One concrete next step is the MCP Interface Layer elective. Here the subsystems behind route_query are wired in-process; the elective shows how each (memory, retrieval, the agent) could instead be re-exposed as a Model Context Protocol server and the OS could consume them — and third-party servers — through one client. That turns the dispatch table from a hard-coded map into a registry of interchangeable, separately-deployable capabilities: the provider/consumer split applied to the very system you just composed. Routing and orchestration stay here in the host; the capabilities move behind a standard protocol surface.

Production Patterns

Real assistant systems are this skeleton plus production engineering: a router (rules, a small classifier, or an LLM) with a confidence threshold and a safe fallback; a capability/dispatch registry; per-capability prompts and budgets (P08's reliability layer on the TASK route); provenance and citations on every answer (P04); a frozen evaluation set for the router and each subsystem (P07); and observability — a trace of which route handled what. Anthropic's guidance frames the spectrum: a single augmented LLM call, then workflows (prompt chaining, routing, orchestrator-workers, evaluator-optimizer), then a full agent — reach for the simplest that works, and compose the named patterns rather than building one monolith.

StarcallOS Relevance

StarcallOS Connection

Project 09 is the smallest complete StarcallOS. StarcallOS is a personal OS with one conversational surface over many capabilities — capture, recall, research, action — and its core engineering problem is exactly this lesson's: route each request to the right capability, do it with a trail the user can trust, link what the user saves into a navigable structure, and reserve the expensive autonomous machinery for the requests that truly need it. The router is StarcallOS's front door; the dispatch table is its capability registry; the provenance is its trust layer; the system-level eval is how StarcallOS knows a change to the front door didn't quietly break the "remember this" path. Build this project well and you have prototyped the spine of StarcallOS.

Sources

See source/resources.md for the complete annotated source list.

Tier 1 — Official Documentation / Engineering Guidance

  • sources/articles/building-effective-agents.md — the augmented LLM (retrieval + tools + memory); routing ("classifies an input and directs it to a specialized followup task"; "separation of concerns"); orchestrator-workers ("breaks down tasks, delegates … and synthesizes their results"); and "add complexity only when it demonstrably improves outcomes" as a routing rule. The spine of the capstone.
  • sources/official-docs/anthropic-citations.md — claim → source location; the production form of the provenance the orchestrator attaches (carried from P04).
  • sources/official-docs/anthropic-tool-use.md — the agentic loop behind the TASK route (carried from P06/P08).
  • sources/official-docs/litellm-completion.md — the single-call interface behind the CHAT route and the optional LLM router (carried from P01).

Tier 2 — Foundational Papers

  • sources/papers/rag-paper.md — Lewis et al. 2020: provenance — an answer should carry a verifiable pointer to what produced it (applied to the orchestrator's Response).
  • sources/papers/generative-agents.md — Park et al. 2023: reflection — linking memories into higher-level structure — the basis for the personal knowledge graph and graph-aware recall.
  • sources/papers/mt-bench.md — Zheng et al. 2023: evaluate with numbers, per case — applied to the router (per-route accuracy, not just the mean).
  • sources/papers/knowledge-graphs-survey.md — Hogan et al. 2021: grounds the term knowledge graph — entities and relations as a first-class, traversable data model. The capstone's tag-linked personal graph stays a modest educational construct (not RDF/SPARQL/KG-embedding).

Tier 3 — Engineering Guides

  • None specific to this lesson beyond the Anthropic engineering guidance in Tier 1 ("Building Effective Agents" is itself the primary source for the routing and orchestrator-workers patterns).

Tier 4 — Educational Sources

  • None specific to this lesson. The prior projects (P01–P08) are the conceptual prerequisites — each subsystem the OS routes to is one you already built.
  • Scope note: the lightweight tag-linked graph is grounded in the knowledge-graphs survey (Hogan et al. 2021) and Generative Agents' reflection. It stays a modest educational construct — not a full RDF/SPARQL/ontology or KG-embedding system (see source/resources.md).

Optional — Going Deeper

Read this after the OS routes and grades. The capstone is a multi-route system; once it works, the real-world question is how to see inside it when a route misbehaves. Not required to finish the project.

  • sources/official-docs/opentelemetry-genai-semconv.md (optional — depth) — standard GenAI telemetry (spans/attributes per model call): the production form of the per-route logging here. Trace a request across its route, attach token/cost/latency, and make a routing regression a queryable event rather than a guess.