diff --git a/.github/workflows/weekly-smoke.yml b/.github/workflows/weekly-smoke.yml new file mode 100644 index 0000000..121ffcf --- /dev/null +++ b/.github/workflows/weekly-smoke.yml @@ -0,0 +1,65 @@ +name: Weekly Smoke + +on: + schedule: + # Every Monday 06:00 UTC. + - cron: "0 6 * * 1" + workflow_dispatch: + +jobs: + python-smoke: + runs-on: ubuntu-latest + timeout-minutes: 45 + + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Set up uv + uses: astral-sh/setup-uv@v3 + + - name: Run Python demo smoke (basic mode) + run: bash scripts/run_demos_smoke.sh --mode basic + + - name: Upload smoke logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: python-smoke-logs + path: .demo-smoke-logs/ + if-no-files-found: ignore + retention-days: 14 + + typescript-smoke: + runs-on: ubuntu-latest + timeout-minutes: 30 + + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Set up Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + + - name: Install TypeScript workspace dependencies + working-directory: typescript_base + run: bun install + + - name: Run TypeScript demo smoke (basic mode) + run: bash scripts/run_demos_smoke_typescript.sh --mode basic + + - name: Upload smoke logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: typescript-smoke-logs + path: .demo-smoke-logs-ts/ + if-no-files-found: ignore + retention-days: 14 diff --git a/README.md b/README.md index dd20941..9179088 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,17 @@ > **Transform your AI applications from simple prompts to sophisticated intelligent systems.** +## 🧭 Principles + +This repo is built around four commitments. They explain what stays in and what gets cut. + +1. **Lean, not exhaustive.** This is *not* a catalog of hundreds of patterns that no human will ever read, understand, or remember. It is a **lean catalog meant to be understood and memorized**. Long patterns lists are not features; they are noise. +2. **Hard cap: at most 24 patterns.** If a pattern is not necessary, we remove it. If something new is added, something else gets dropped. The ceiling is a forcing function, not an aspiration. +3. **Demos must actually work.** Every demo runs in an **automated weekly smoke test, for both Python *and* TypeScript** — and it must pass. (See [`.github/workflows/weekly-smoke.yml`](./.github/workflows/weekly-smoke.yml).) Educational code that doesn't run is educational code that lies. +4. **Concrete relevance, not just papers.** For each pattern we measure how it shows up in **real coding agents** — currently [Pi](https://github.com/earendil-works/pi) — and write it down in a `pi.md` inside each pattern folder, plus a [repo-wide roll-up with a coverage heat map](./pi.md). We also maintain [`diff.md`](./diff.md) to disambiguate commonly-confused pattern pairs: **if two patterns can't be cleanly told apart, one of them probably doesn't belong here**. A pattern that only exists in a paper somewhere is a signal it may not belong either. + +--- + AI evolves too quickly for traditional books to stay current, especially in fast-moving areas like agentic systems. That’s why this is one of the best “living books” on agentic AI: a comprehensive, hands-on collection of design patterns for building robust AI agents, continuously updated with real-world implementations, practical examples, and detailed architectural guidance for scalable, maintainable AI applications. ## Table of Contents diff --git a/README.zh-CN.md b/README.zh-CN.md index f9d2cb5..d60695f 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -14,6 +14,17 @@ > **把你的 AI 应用从简单提示词进化为成熟的智能系统。** +## 🧭 原则 + +本仓库围绕四条承诺构建。它们决定了什么留下、什么被删除。 + +1. **精炼,不求大而全。** 这**不是**一个包含成百上千个、没人会真正读懂或记得住的模式的目录。它是一份**面向人类理解与记忆的精炼目录**。冗长的模式清单不是优点,而是噪音。 +2. **硬上限:最多 24 个模式。** 如果某个模式并非必需,就把它移除。新增一个,就要删掉另一个。这个上限是一种强制约束,而不是远期目标。 +3. **示例必须真的能跑起来。** 每个示例都会在**自动化的每周冒烟测试**中运行,同时覆盖 **Python 与 TypeScript**,并且必须通过。(见 [`.github/workflows/weekly-smoke.yml`](./.github/workflows/weekly-smoke.yml)。)跑不起来的教学代码就是在说谎的教学代码。 +4. **要看具体相关性,而不只是论文。** 对每一个模式,我们都会衡量它在**真实编码 Agent**中的呈现方式 —— 目前对标的是 [Pi](https://github.com/earendil-works/pi) —— 并把分析结果写入每个模式目录下的 `pi.md`,同时提供一份[包含覆盖度热力图的仓库级汇总](./pi.md)。我们还维护一份 [`diff.md`](./diff.md) 来澄清那些常被混淆的模式对:**如果两个模式无法被清晰地区分开来,那么其中一个大概率不该留在这里**。一个只存在于某篇论文里的模式,同样是它可能不属于这里的信号。 + +--- + AI 演进的速度太快,传统书籍很难保持时效,尤其是在智能体(agentic)系统这种快速变化的领域。这正是本仓库被定位为关于智能体 AI 最好的“活书(living book)”之一的原因:它是一个全面、动手实践的设计模式合集,用于构建健壮的 AI 智能体,并持续更新真实世界的实现、可运行的示例,以及为可扩展、可维护 AI 应用提供的详细架构指引。 ## 目录 @@ -42,6 +53,8 @@ AI 演进的速度太快,传统书籍很难保持时效,尤其是在智能 > 本仓库现在包含面向实现层面的分析,说明这些模式如何映射到 [Pi](https://github.com/earendil-works/pi)。这些分析基于 Pi 的真实代码库,附带 package/module 引用、带行号的代码片段,以及对架构权衡或局限性的说明。 > > 在各模式目录下查找 `pi.md`。这些文字保持保守的态度:如果 Pi 并没有有意义地实现某个模式,分析会直接说明这一点,而不是强行套用。 +> +> 想看 28 个模式的整体覆盖情况?参见仓库根目录的 [**Pi 汇总(`pi.md`)**](./pi.md):覆盖度热力图、按分数排序的总表,以及每个模式的一句话结论与最具代表性的代码引用。 **当前已提供的 Pi 分析:** - 基础(Foundational):[Prompt Chaining](./foundational_design_patterns/1_prompt_chain/pi.md)、[Routing](./foundational_design_patterns/2_routing/pi.md)、[Parallelization](./foundational_design_patterns/3_parallelization/pi.md)、[Reflection](./foundational_design_patterns/4_reflection/pi.md)、[Tool Use](./foundational_design_patterns/5_tool_use/pi.md)、[Planning](./foundational_design_patterns/6_planning/pi.md)、[Multi-Agent Collaboration](./foundational_design_patterns/7_multi_agent_collaboration/pi.md)、[ReAct](./foundational_design_patterns/8_react/pi.md)、[HITL](./foundational_design_patterns/10_hitl/pi.md)、[Structured Outputs](./foundational_design_patterns/11_structured_outputs/pi.md)、[Computer Use](./foundational_design_patterns/12_computer_use/pi.md) diff --git a/diff.md b/diff.md new file mode 100644 index 0000000..700ba50 --- /dev/null +++ b/diff.md @@ -0,0 +1,198 @@ +# Pattern Differences + +Several patterns in this catalog overlap visibly in their demos and can blur together on first read. This document **disambiguates the commonly-conflated pairs**: what they share, the actual axis of difference, and how to choose between them in practice. + +Where a useful framing exists: **one pattern is the *mechanism*, the other is the *shape* built on top of it** — or — **they look similar but operate on different *axes*** (context vs goal, persistence vs window, tree vs graph). + +--- + +## Index + +- [ReAct vs Tool Use](#react-vs-tool-use) — *loop shape* vs *single-turn primitive* +- [Subagents vs Parallelization](#subagents-vs-parallelization) — *isolated contexts* vs *one-context concurrency* +- [Tree of Thoughts vs Graph of Thoughts](#tree-of-thoughts-vs-graph-of-thoughts) — *branches don't merge* vs *branches recombine* +- [Deep Research vs ReAct](#deep-research-vs-react) — *typed research pipeline* vs *generic act-observe loop* +- [Goal Management vs Resource Optimization](#goal-management-vs-resource-optimization) — *what to do* vs *how much capacity you have* +- [Memory Management vs Context Management](#memory-management-vs-context-management) — *across sessions* vs *within this turn* + +--- + +## ReAct vs Tool Use + +[ReAct →](./foundational_design_patterns/8_react/) · [Tool Use →](./foundational_design_patterns/5_tool_use/) + +**One-liner.** Tool Use is the *primitive*; ReAct is the *loop pattern* built on top of it. + +**What they share.** Both involve the model calling out to external functions and consuming results. + +**Axis of difference.** + +| Aspect | Tool Use | ReAct | +|---|---|---| +| Granularity | A single turn: emit a call → execute → return result | A multi-turn loop: Reason → Act → Observe → repeat | +| What it defines | The *mechanism* by which a model invokes a function | The *shape* of an agent that keeps invoking functions until done | +| Stop condition | n/a — one call per turn | Agent decides "no more actions needed" (or hits an iteration cap) | +| Typical demo | "Model calls `get_weather(location)` and replies" | "Model writes a thought, calls a search, reads the result, writes another thought, calls another tool…" | +| Maps onto | OpenAI function calling, Anthropic tool use, MCP tools | Any agent loop that alternates assistant text + tool calls | + +**How to choose.** If your task is "model needs to call one function and answer," it's Tool Use. If your task is "model needs to think, act, observe, and keep going until it solves the problem," it's ReAct. **Modern agent loops are almost always implicit ReAct loops driven by tool calling** — the two are intertwined, not competing. + +**Common confusion.** "Doesn't every framework with `tools=[...]` already do ReAct?" Yes, *implicitly*. Many frameworks bundle them. Tool Use is the lower-level capability; ReAct is the conventional way it gets used at scale. + +--- + +## Subagents vs Parallelization + +[Subagents →](./orchestration/subagents/) · [Parallelization →](./foundational_design_patterns/3_parallelization/) + +**One-liner.** Parallelization fans work out **within one context**; subagents fan work out **across isolated contexts**. + +**What they share.** Both produce N results from N concurrent operations and synthesize them. + +**Axis of difference: who owns the context window.** + +| Aspect | Parallelization | Subagents | +|---|---|---| +| Context | Single — all N operations run in the same agent's prompt scope | One per worker — each subagent has its own isolated context | +| Isolation level | Message-array isolation at best | Process / container / session isolation (much stronger) | +| Result interface | All raw outputs flow back into the parent prompt | Only a **structured summary** crosses back; raw work stays in the worker | +| Context cost | Sum of all N outputs hits the parent context | Workers absorb their own reads/thoughts; parent stays lean | +| Latency overhead | Minimal — concurrent function calls | Per-worker spawn cost (~100ms+ for separate processes) | +| Failure blast radius | One bad output pollutes the parent transcript | One worker failing doesn't corrupt the parent's reasoning | + +**How to choose.** + +- Need to call 5 search APIs concurrently and synthesize? **Parallelization.** +- Need 5 workers to each summarize a different 50-file directory and return a paragraph each? **Subagents** — you'd blow the parent's context if you tried this with parallelization. + +**Common confusion.** "Subagents are just parallelization with extra steps." False. The structural commitment subagents make — **summary-not-transcript** — is what makes them scale. Parallelization with 5 outputs of 20k tokens each is unworkable; subagents with 5 outputs of 200 tokens each fits. + +--- + +## Tree of Thoughts vs Graph of Thoughts + +[Tree of Thoughts →](./reasoning/tree_of_thoughts/) · [Graph of Thoughts →](./reasoning/graph_of_thoughts/) + +**One-liner.** Both explore many partial solutions and score them. **ToT keeps the explorations as a tree; GoT lets them merge into a graph.** + +**What they share.** Candidate generation + state scoring + pruning of bad branches. Both come from a research lineage that treats reasoning as classical search over thought states. + +**Axis of difference: topology of the reasoning state.** + +| Aspect | Tree of Thoughts | Graph of Thoughts | +|---|---|---| +| State topology | Rooted tree — each node has one parent | DAG / graph — nodes can have multiple parents (merges allowed) | +| Operations | Expand, score, prune, backtrack (classical search) | Above + **aggregate** (combine multiple partial results) and **refine** (improve via merge) | +| Algorithmic analogue | BFS / DFS / beam search | Evolutionary / genetic operators + search | +| Best when | Solution space decomposes cleanly into mutually-exclusive paths | Subproblems share structure or partial solutions can be productively recombined | +| Example | "Game of 24" — each branch is a distinct arithmetic path | "Summarize many documents" — sub-summaries can be merged pairwise | + +**How to choose.** If branches in your problem are *genuinely independent* — try one, fail, try another — **ToT** is enough and simpler. If partial solutions *combine into better partial solutions* — sub-summaries that aggregate, sub-proofs that compose — you want **GoT**'s merge nodes. + +**Common confusion.** "ToT branches must eventually merge anyway when the agent picks one." No — ToT's *winning path* is selected from the tree, but other branches are *discarded*. GoT explicitly **recombines** branches rather than picking one. + +--- + +## Deep Research vs ReAct + +[Deep Research →](./reasoning/deep_research/) · [ReAct →](./foundational_design_patterns/8_react/) + +**One-liner.** ReAct is a generic act-observe loop the agent steers freely; Deep Research is a **typed pipeline with prescribed phases and citation semantics**. + +**What they share.** Both are multi-round loops where the agent gathers information and then produces output. + +**Axis of difference: prescribed structure vs free-form.** + +| Aspect | ReAct | Deep Research | +|---|---|---| +| Loop shape | Reason → Act → Observe → repeat, agent decides | Plan → Search → Reflect → Follow-up → Synthesize (typed phases) | +| Termination | Agent decides "done" | Coverage / depth / claim-confidence criteria | +| Output | Whatever the task asks for | **Cited synthesis** — claims linked to source documents | +| Gap-handling | Implicit ("I should look harder") | Explicit gap-analysis step between rounds | +| Memory of sources | Implicit in transcript | Explicit evidence store with stable handles for citation | +| Substrate | Agent-level pattern | Often *implemented on top of* a ReAct loop | + +**How to choose.** "Build a customer-support agent that calls our tools" — **ReAct.** "Build a competitive-analysis agent that produces a cited report on a market" — **Deep Research** (its phase structure and citation tracking are load-bearing). + +**Common confusion.** "Deep Research is just ReAct with web search." False — the *loop's structure* differs. ReAct lets the model choose what to do each turn; Deep Research's controller decides which **phase** to run (plan vs search vs reflect vs synthesize) and enforces citation tracking between rounds. + +--- + +## Goal Management vs Resource Optimization + +[Goal Management →](./orchestration/goal_management/) · [Resource Optimization →](./observability/resource_optimization/) + +**One-liner.** Goal Management tracks **what** the agent is doing. Resource Optimization tracks **how much capacity** it has to do anything. + +**What they share.** Both surface in the same agent run and both inform decisions — but on totally different axes. + +**Axis of difference: goal-space vs resource-space.** + +| Aspect | Goal Management | Resource Optimization | +|---|---|---| +| Domain | Goals, tasks, todos, milestones, "what's next?" | Tokens, cost, context window, latency, API quota, "how much budget left?" | +| Question it answers | *What should the agent attempt now?* | *Can the agent afford to attempt this now?* | +| Failure mode if missing | Agent thrashes between objectives or forgets what it was doing | Agent runs out of context mid-task, exhausts budget, or stalls | +| Typical artifacts | Plan steps, todo list, current focus, completion criteria | Token counts, cost meters, compaction triggers, cache hit rates | +| Operates over | The *workflow* | The *runtime constraints* of the workflow | + +**How to choose.** Different concern entirely — most production agents need **both**. They compose: + +- Goal Manager: "the next thing to do is summarize all 50 docs." +- Resource Optimizer: "but the context window only has room for 12 of them — paginate, or send each to a subagent." + +**Common confusion.** "Aren't todos a form of resource tracking?" No — a todo records *what to do*, not *how much capacity remains*. Conversely, a token counter says nothing about *which* goal you're pursuing. The two are orthogonal and you typically want both wired together. + +--- + +## Memory Management vs Context Management + +[Memory Management →](./memory/memory_management/) · [Context Management →](./memory/context_management/) + +**One-liner.** Memory Management is **across sessions** (persistent). Context Management is **within this turn** (the prompt window). + +**What they share.** Both decide what information the agent has access to. They're in the same category directory for a reason — but they answer different questions. + +**Axis of difference: time horizon and persistence.** + +| Aspect | Memory Management | Context Management | +|---|---|---| +| Time horizon | Long-lived — persists across sessions | Short-lived — this conversation, this turn | +| Storage | Vector store, episodic memory, session forks, sidecar files | The prompt itself: system prompt + history + injected context | +| Question it answers | *What does the agent remember next week?* | *What does the agent see in this turn?* | +| Typical mechanisms | Embeddings + retrieval, durable JSONL session repos, memory-as-tool | Compaction, project-context loading (`AGENTS.md`/`CLAUDE.md` walk), system-prompt assembly | +| Failure mode | Agent forgets you discussed X two weeks ago | Agent's context overflows mid-conversation | +| Granularity | Records / chunks / episodes | Tokens | + +**How they relate.** Memory **feeds** context. A retrieved memory enters context when relevant; a compacted conversation is summarized *into* a memory record. They flow into each other: + +``` + ┌─────────────────────────┐ + │ Memory (durable) │ ← long-term, across sessions + └────┬────────────────▲───┘ + │ retrieve │ persist + ▼ │ + ┌─────────────────────────┐ + │ Context (this turn) │ ← short-term, within prompt window + └─────────────────────────┘ +``` + +**How to choose.** + +- Need agent to recall the user's preferences from last week? **Memory.** +- Need agent to fit a 200k-token conversation into a 100k window without losing thread? **Context.** +- Building a long-running personal assistant? **Both** — memory for facts the agent should never forget; context engineering for the working set this turn. + +**Common confusion.** "Compaction is memory." No — compaction shrinks context to fit a window. If you also persist the compacted summary across sessions, *that part* is memory. Compaction is context engineering; the durable summary is memory. + +--- + +## When in doubt + +If you're squinting at two patterns and can't tell which to use, ask: + +- **"Is one the mechanism and the other the loop?"** → ReAct vs Tool Use; Deep Research vs ReAct. +- **"Are they on different axes?"** → Goal vs Resource; Memory vs Context. +- **"Is one a stricter / topology-different version of the other?"** → ToT vs GoT (tree vs graph); Subagents vs Parallelization (isolated vs shared context). + +In all three framings, the answer is rarely "use one *instead of* the other" — production agents usually compose them.