Dayward AI
Week 1 · D5About 4 hours

Automation and Scale: Headless -p Into CI, Parallel Sessions and Worktrees, Writer/Reviewer Dual Sessions, Adversarial Review, Common Failure Modes; a 20-Line Minimal Agent SDK Agent

Turn Claude Code from a terminal sidekick into one stage of a pipeline: run it headless with -p in CI and parse the JSON result, run parallel sessions with worktrees, use adversarial review as a backstop, then write a 20-line minimal agent with the Agent SDK.

Today's goals 0/3

Sign in to tick these off and save your progress.

Today's Goals

  1. Run an unattended task with claude -p, and parse the --output-format json result to judge success or failure
  2. Run multiple parallel sessions with worktrees, and design a Writer/Reviewer dual-session adversarial review
  3. Write a 20-line minimal agent with the Agent SDK, and name the fix for five common failure modes

For four days you have been sitting beside the teammate. Today you leave the chair: it works with nobody watching, several of them work at once, and they check each other's work. Once you have read this and finished the lab, scroll back up and tick off the three goals — and the course is done.

Plain-Language Walkthrough

Headless mode: claude -p turns the teammate into one command

A capable teammate eventually meets a request like this: "for every incoming PR, do a pass for spelling mistakes," or "every night, group today's error logs by cause." That work needs no conversation at your side, only a command a script can call.

claude -p "your prompt" is that command — headless mode (-p is short for print). It never enters the interactive interface: it runs the prompt, writes the result to standard output, and exits, with exit code 0 for success and non-zero for failure, so a shell script can branch on it directly. It also takes a pipe like any Unix tool:

BashBash
# a one-off question
claude -p "What does this project do?"
 
# pipe data in: feed it the build log, write the explanation to a file
cat build-error.txt | claude -p "Briefly explain the root cause of this build error" > explain.txt
 
# use it as a typo linter: it only sees the diff and needs no Bash permission
git diff main | claude -p "You are a spell checker. Report every spelling mistake in the diff, one per line as file:line, and output nothing else."

The third one deserves a second look: piping the diff in means Claude needs no tool permissions at all and answers purely from its input — the safest possible shape for an unattended job. Running in CI also wants --bare: it skips auto-discovery of hooks, skills, plugins, MCP, and CLAUDE.md, so results are identical on every machine and startup is faster, and it sidesteps the hazard at the end of D4 — somebody else's hooks from an unfamiliar repository executing on your CI runner. The documentation says plainly that --bare will become the default for -p in the future. Note that --bare does not read your subscription login, so ANTHROPIC_API_KEY must be set.

Parsing the JSON result: result, session_id, cost, and turns

A script judging whether something succeeded and what it cost needs more than a block of prose. Add --output-format json and the output becomes a JSON object with several key fields:

JSONJSON
{
  "type": "result",
  "subtype": "success",
  "is_error": false,
  "result": "Found 3 spelling mistakes: …",
  "session_id": "3f9c…",
  "num_turns": 4,
  "duration_ms": 18234,
  "total_cost_usd": 0.0421,
  "usage": { "input_tokens": 12034, "output_tokens": 812, "cache_read_input_tokens": 9800 }
}

result is the final answer; is_error and subtype tell you success or failure; num_turns is how many think-call-tool-read-result rounds it took; total_cost_usd is the estimated cost of this run (a client-side estimate that may differ from the bill, but good enough for budget control); and session_id lets you continue with --resume. There is a further step too: pass a JSON Schema with --json-schema and the result gains a structured_output field that strictly matches your schema — the structured output from D1, reappearing at the CLI layer.

When you need to handle events one at a time, use --output-format stream-json --verbose: one JSON event per line, with system/init first (carrying the model, the tools, and the status of loaded plugins and MCP servers — CI can use it to check that everything meant to load actually loaded) and a result of the same shape as above last. In a script, jq -r '.result' takes the text and jq '.total_cost_usd' the cost, or you write a 20-line TS / Python wrapper as in today's lab: call claude -p, parse the JSON, and exit non-zero on an error or a budget overrun.

Three locks before CI: permissions, budget, reproducibility

Before leaving the teammate alone in the office overnight, you lock three doors.

Lock one: permissions. Unattended, nobody is there to answer "allow?", so either state up front what is allowed or refuse everything that would ask. --allowedTools allowlists specific tools: "Read,Grep" is a read-only review; "Bash(git diff *),Bash(git log *)" allows only a couple of git commands — and mind the space before *, since git diff* without it would also admit git diff-index. --permission-mode sets the baseline: dontAsk is the strictest CI mode, refusing anything off the allowlist; acceptEdits permits file edits while commands stay restricted; auto lets the classifier model review on your behalf. The starting mode for -p is Manual on every plan, so you must pass it explicitly. Pair it with --permission-prompts none so anything that would have asked a human is refused outright, with the model told not to retry.

Lock two: budget. --max-turns N caps turns and --max-budget-usd 0.50 caps spend, stopping with an error when either is reached. Without those two, one task stuck in a loop can burn a month's quota.

Lock three: reproducibility. --bare turns off auto-discovery of local configuration; --no-session-persistence keeps nothing on disk; and the model, the prompt, and any system prompt appendix (--append-system-prompt) all live in the script under version control. Put together, the command looks like this:

BashBash
gh pr diff "$PR" | claude --bare -p \
  --append-system-prompt "You are a security reviewer. Report vulnerabilities and risks only; do not comment on style." \
  --permission-mode dontAsk --permission-prompts none \
  --max-turns 6 --max-budget-usd 0.50 \
  --output-format json > review.json
 
jq -r '.result' review.json | gh pr comment "$PR" --body-file -

Parallel sessions and worktrees: several jobs at once without stepping on each other

One teammate is no longer enough and you want three at once: one fixing a bug, one writing a feature, one tidying docs. The problem is that three of them editing files in the same directory will overwrite each other.

Git worktrees solve this: one repository, several independent working directories, each on its own branch. Claude Code turns it into a flag: claude --worktree feature-auth (or -w) creates a worktree under .claude/worktrees/feature-auth/, checks out the worktree-feature-auth branch, and starts a session inside it. Open another terminal, run claude --worktree fix-login, and the two sessions work in directories that cannot disturb each other. When a session ends it checks that worktree for uncommitted changes: clean means it is removed automatically, and if there is work in progress it asks whether to keep or delete it.

Two practical details: add .claude/worktrees/ to .gitignore; and a worktree is a fresh checkout, so gitignored files such as .env do not come along — put a .worktreeinclude file in the project root listing the file names to copy. Subagents can use worktrees for isolation too: write isolation: worktree in the frontmatter of .claude/agents/<name>.md and that subagent always edits files inside its own temporary worktree.

The other shape of parallelism is not several different jobs but the same job done by several parties who then read each other's work — which is the next section.

Writer / Reviewer and adversarial review: let another context find the flaws

Having the person who wrote the code review their own code usually works poorly — not out of bad faith, but because their head is still full of every reason they wrote it that way, which is hard to step outside of. The same is true for Claude: a session that just finished an implementation has its whole chain of reasoning in context, and asked to review itself it tends to confirm rather than question.

The fix is to review from a context that has none of those memories. The simplest shape is two terminals:

Session A (Writer)Session B (Reviewer)
"Add input validation and tests to POST /todos"
"Review the validation implementation in @src/routes/todos.ts. Find edge cases, inconsistencies with the existing middleware style, and missing tests. Report only problems that affect correctness."
"Here is the review: [output of session B]. Work through it item by item."

Session B reads the code from scratch and sees only the diff and the standard you gave it, with no idea why A wrote it that way — so what it finds are flaws in the code itself. The same idea works for tests: one session writes the tests, another writes the implementation that has to pass them.

If you would rather not run two terminals, use the subagent from D4 for an adversarial review: "use a subagent to review this diff against PLAN.md: is each requirement implemented, does every listed edge case have a test, and does anything go beyond the task's scope. Report gaps only; do not comment on style." A subagent's separate context is that reviewer without memories by construction. Claude Code also ships /code-review, which reviews the current diff for bugs in a fresh subagent.

One side effect you must know about: ask a reviewer to find problems and it will definitely find problems — even flawless code gets a few reported, because that is the job it was given. Accepting all of it uncritically leads to over-engineering: superfluous abstraction layers, code defending against situations that cannot arise, tests for impossible cases. So the review prompt should say explicitly to report only gaps that affect correctness or an explicit requirement and treat everything else as optional, and then you decide what is worth changing.

Five common failure modes and their fixes

Five days in, the potholes you have hit almost certainly fall into these five. The official best practices page lists them, and here they are again by how to recognize and how to solve each:

  1. The grab-bag session. You asked about B while fixing A, then went back to A, and the window is full of unrelated debris while answer quality visibly drops. Fix: /clear between tasks.
  2. Repeated correction. The same mistake survives two corrections, because every failed attempt stays in the context and keeps polluting it. Fix: after two misses, /clear and restart with a better prompt that absorbs the lesson.
  3. An over-long CLAUDE.md. Too many rules, the important ones drowned, and it stops "listening." Fix: trim until you cannot; delete what it already does by default, and convert what must hold 100% of the time into a hook.
  4. Trust without verification. It produces a plausible-looking implementation that misses an edge case, and you merge without noticing. Fix: always give it a verifiable check — tests, a script, a screenshot; never ship what you cannot verify.
  5. Unbounded exploration. "Go investigate X" has no scope, so it reads hundreds of files and fills the window. Fix: state the scope of the investigation concretely, or hand it to a subagent with its own context.

Notice that three of the five are the same point: the context window is the scarcest resource. That is the sentence this course has been repeating since D2.

The Agent SDK: the same loop as Claude Code in 20 lines

The last topic connects the course back to D2. claude -p already looks a lot like a function call, but it is a command line — you assemble the arguments, parse the JSON, and manage the process yourself. If you want Claude Code's full set of capabilities (reading and writing files, running commands, searching code, hooks, subagents, permissions, sessions) inside your own program, there is a proper entry point: the Claude Agent SDK.

It is a different thing from the @anthropic-ai/sdk / anthropic package used on D2. The D2 SDK is a client for the Messages API: you send messages and it replies, with tools for you to define and the loop for you to write. The Agent SDK is Claude Code packaged as a library: file and Bash tools built in, the whole agent loop, context management, and the permission system, with you supplying one task and a set of options. Twenty lines gets you an agent that edits code:

agent.ts
import { query } from '@anthropic-ai/claude-agent-sdk'
 
// query returns an async iterator: each message is a piece of reasoning, a tool call, or the final result
for await (const message of query({
  prompt:
    'Add zod input validation to POST /todos in src/routes/todos.ts, write matching vitest cases under test/, and run until green.',
  options: {
    allowedTools: ['Read', 'Edit', 'Glob', 'Grep', 'Bash'], // pre-authorized tools
    permissionMode: 'acceptEdits', // file edits go unasked; Bash is still bound by allowedTools
    maxTurns: 20, // budget: 20 turns at most
    systemPrompt: 'You are a senior Node.js backend engineer. Edit only src/ and test/.', // the D1 business card
  },
})) {
  if (message.type === 'assistant') {
    for (const block of message.message.content) {
      if ('text' in block) console.log(block.text) // its reasoning
      else if ('name' in block) console.log(`-> tool: ${block.name}`) // which tool it is calling
    }
  } else if (message.type === 'result') {
    console.log(`finished: ${message.subtype}`) // success / error_max_turns …
  }
}

The division of labor is now clear: for a question-answering, extraction, or define-your-own-tools model call, use the Messages API (D2); for an agent that works inside a file system, use the Agent SDK (today); to call it from a shell script, use claude -p. The same model sits underneath all three, and the difference is who provides the loop and the tools.

That is the end of the course. You can now brief it (D1), feed it material (D2), write the handbook and work through a plan (D3), install gates and procedures (D4), and let it run unattended while the parties check each other (D5). Two directions from here. To see how the same things are done on the OpenAI side — how Codex and the Agents SDK complete the same TODO API task and where the two differ — take the companion course Using Codex and the OpenAI Agents SDK Effectively, whose D5 runs a head-to-head comparison on today's task. To go deeper, the two things D4 touched briefly each have a seven-day course: mcp-7days (wiring tools into any agent) and agent-skills-7days (turning experience into reusable capabilities), both coming soon.

Source Reading

Hands-On Lab

🧪 D5 lab: a claude -p task script that runs in CI, with JSON result parsing

Code location: labs/claude-mastery/day-05-headless-ci

Acceptance criteria:

  1. MOCK=1 pnpm start runs even on a machine without the claude command: it prints a parsed fixed JSON result — success or failure, turns, cost, result summary — and exits 0.
  2. MOCK=1 MOCK_SCENARIO=over-budget pnpm start exits non-zero and prints the budget-overrun reason; MOCK_SCENARIO=error likewise prints the error message.
  3. With claude installed and logged in, pnpm start really invokes claude -p with --bare --output-format json --permission-mode --max-turns --max-budget-usd on the command line, and writes the result to review.json.
  4. The repository holds a .github/workflows/claude-review.yml that runs this script on the pull_request event and posts result back as a PR comment, with the key read from secrets.
  5. When the script is cut off by --max-turns or by the budget, the exit code is non-zero and the log shows which lock fired.

The lab is a TS wrapper: it takes a diff (git diff main by default), assembles a claude -p command carrying the three locks, parses the JSON, and exits non-zero on an overrun or an error. Under MOCK=1 it does not really call claude but returns several fixed JSON scenarios, so readers without Claude Code installed can still finish and run the parsing and decision logic. solution/ci.py is the same thing in Python.

  1. Run pnpm install in the starter directory, then MOCK=1 pnpm start, and see it print a not-yet-parsed placeholder output, confirming the skeleton runs.
  2. Finish exercise 1: assemble the claude -p arguments in buildArgs — bare, output-format json, permission-mode dontAsk, max-turns, max-budget-usd, append-system-prompt.
  3. Finish exercise 2: in parseResult, read is_error, subtype, num_turns, total_cost_usd, and result out of the JSON, and decide success or failure and whether the budget was exceeded.
  4. Finish exercise 3: make all three MOCK_SCENARIO values (success / over-budget / error) produce the right exit code and log, then set the budget very low on purpose to exercise the over-budget branch.
  5. If you have the claude command, drop MOCK and run it for real, inspecting the fields in review.json; then read .github/workflows/claude-review.yml and confirm the key comes from secrets and permissions grant only pull-requests: write.

Interview Questions

Today's 3 questions are in the question bank below, weighted toward permission and cost control for headless mode in CI, why adversarial review works, and the division of labor between the Agent SDK and calling the API directly. Expand each one and read the analysis before the key points — practicing the derivation beats memorizing bullets. The high-frequency labels for the domestic and overseas markets are there so you can pick by target market.

Checklist and Tomorrow

  • Run an unattended task with claude -p, and parse the --output-format json result to judge success or failure
  • Run multiple parallel sessions with worktrees, and design a Writer/Reviewer dual-session adversarial review
  • Write a 20-line minimal agent with the Agent SDK, and name the fix for five common failure modes
  • Explain the division of labor between the Messages API, the Agent SDK, and claude -p
  • All 5 acceptance criteria of the lab pass
  • Answer at least 2 of the 3 interview questions without looking at the key points

There is no tomorrow for this course, but there is a next course. Take the same example task to Using Codex and the OpenAI Agents SDK Effectively and see how it is done on the OpenAI side and how the two ways of working differ — not which is smarter, but how each is best managed. To turn the MCP and skills from D4 into crafts of their own, mcp-7days and agent-skills-7days are coming soon. Take with you the sentence these five days kept returning to: the context window is the scarcest resource, and a verifiable check is the watershed for using an agent well.

Interview questions

  • What three things must you control when running claude -p in CI, with which flags, and why is --bare recommended?把 claude -p 放进 CI 时要控制哪三件事?具体用哪些参数?为什么推荐加 --bare?
    Common in ChinaCommon overseasIntermediate#headless#ci#permissions

    How to reason about it · think before answering

    1. This tests awareness of unattended risk. 'Add an API key and run it' reads as no production experience; the interviewer wants the three locks — permissions, budget, reproducibility — each with its flags.
    2. Permissions: nobody answers 'allow?' unattended, so either allowlist tools (--allowedTools "Read,Grep" or "Bash(git diff *)", mind the space before *) or set a baseline (--permission-mode dontAsk denies anything outside the allowlist; acceptEdits permits file edits), plus --permission-prompts none to deny anything that would have prompted. -p starts in Manual on every plan, so pass the mode explicitly.
    3. Budget: --max-turns caps turns, --max-budget-usd caps spend; both stop with an error. Without them a looping task can drain your quota; with a Stop hook, allow enough turns or the run ends on 'max turns' rather than 'tests pass'.
    4. Reproducibility: --bare skips auto-discovery of hooks, skills, plugins, MCP, and CLAUDE.md so every runner behaves the same and starts faster — and it is a security measure, since a cloned repo's hooks would otherwise run silently under -p (no trust dialog). Add --no-session-persistence and keep the prompt and --append-system-prompt in version control.
    5. Follow-ups: authentication under --bare — it ignores subscription login, so set ANTHROPIC_API_KEY. Judging success — is_error, subtype, and total_cost_usd from --output-format json; fail the job on a non-zero exit.

    分析过程 · 先想清楚再作答

    1. 这题考无人值守的风险意识。答「加个 API key 就能跑」会被判没上过线;面试官想听权限、预算、可复现三道锁,以及每道锁对应的参数。
    2. 权限:无人值守时没人回答「允许吗」,所以要么白名单放行(--allowedTools "Read,Grep" 或 "Bash(git diff *)",注意 * 前的空格),要么定基线(--permission-mode dontAsk 一律拒绝白名单外的动作;acceptEdits 允许改文件),再加 --permission-prompts none 把本来要问人的动作直接拒掉。-p 模式的起始档位是 Manual,必须显式传。
    3. 预算:--max-turns 限轮数、--max-budget-usd 限花费,到了就停并报错。没有它们,一个卡在循环里的任务能耗尽额度;有 Stop hook 时要给足轮数,否则会以「轮数耗尽」而不是「测试通过」结束。
    4. 可复现:--bare 跳过 hooks、skills、插件、MCP、CLAUDE.md 的自动发现,让每台 runner 结果一致、启动更快;同时也是安全措施——不加它,clone 下来的陌生仓库里别人写的 hook 会在 -p 下无提示地执行(无头模式没有信任对话框)。配合 --no-session-persistence 不落盘,提示词与 --append-system-prompt 进版本控制。
    5. 可预期的追问:--bare 之后怎么认证?它不读订阅登录,必须设 ANTHROPIC_API_KEY;再追问怎么判断成败——--output-format json 的 is_error / subtype / total_cost_usd,退出码非零脚本就 fail。

    Key points

    • Permissions: --allowedTools allowlist plus --permission-mode dontAsk or acceptEdits and --permission-prompts none; -p defaults to Manual
    • Budget: --max-turns and --max-budget-usd stop the run; leave headroom for Stop hooks
    • Reproducibility: --bare skips local auto-discovery and keeps a cloned repo's hooks from running in CI; --no-session-persistence
    • --bare requires ANTHROPIC_API_KEY; judge success from is_error in the JSON and the exit code

    答题要点

    • 权限:--allowedTools 白名单 + --permission-mode dontAsk / acceptEdits + --permission-prompts none;-p 默认 Manual 必须显式传
    • 预算:--max-turns 与 --max-budget-usd,到了就停;有 Stop hook 时给足轮数
    • 可复现:--bare 跳过本机配置自动发现,也防陌生仓库的 hook 在 CI 上跑;--no-session-persistence
    • --bare 需要 ANTHROPIC_API_KEY;成败看 --output-format json 的 is_error 与退出码
  • Why is a Writer / Reviewer two-session review more effective than self-review in one session, and should you fix everything the reviewer reports?为什么 Writer / Reviewer 双会话的审查比同一个会话自查更有效?审查者报出来的问题要全改吗?
    Common in ChinaCommon overseasIntermediate#review#subagents

    How to reason about it · think before answering

    1. The point is the why and the second half. 'A second pair of eyes' is common sense; explain the role of context and the side effect of review.
    2. Chain: the session that wrote the code has a context full of its own reasoning; asked to review, it tends to confirm rather than challenge — a context bias, not an attitude problem. A Reviewer in a fresh context sees only the diff and your criteria, not the Writer's reasons, so it critiques the code itself. Same principle as non-author code review among humans.
    3. Three shapes: two terminals passing output by hand; a subagent doing adversarial review (its isolated context is the memoryless reviewer, and findings land back in the main session for immediate fixing); the built-in /code-review that reviews the current diff in a fresh subagent. The idea also inverts: one session writes tests, another writes the implementation to pass them.
    4. The second half separates candidates: don't fix everything. A reviewer told to find gaps will report some even in sound code; accepting all of it leads to over-engineering — extra abstraction, defensive code for impossible cases, tests for unreachable paths. Tell it to flag only gaps affecting correctness or stated requirements, and let a human decide.
    5. Follow-ups: what does the Reviewer need? The diff, the plan or requirements, explicit criteria; feeding it the Writer's reasoning weakens independence. Can it be automated? Yes — run the Reviewer via -p and post results to the PR.

    分析过程 · 先想清楚再作答

    1. 题眼是「为什么」和后半句。答「多一双眼睛」是常识;要说清上下文在这里扮演的角色,以及审查的副作用。
    2. 推导:写完实现的会话,上下文里装满了「我为什么这么写」的推理;让它自审,它倾向于确认而不是质疑——这不是态度问题,是上下文偏置。Reviewer 换一个全新的上下文,只看到 diff 和你给的标准,不知道 Writer 的理由,所以挑的是代码本身的毛病。这和人类 code review 要求「非作者审」是同一个道理。
    3. 形态有三种:两个终端手动传递输出;一个 subagent 做对抗式审查(独立上下文天然就是无记忆的审查者,而且结果直接回到主会话可以立刻修);内置的 /code-review 在新 subagent 里审当前 diff。同样的思路可以反过来用:一个会话写测试,另一个写实现去通过。
    4. 后半句是区分度:不要全改。被要求找问题的审查者一定会报出问题来,哪怕代码没毛病;照单全收会导致过度工程——多余抽象、防御不存在情况的代码、测不可能发生的用例。审查提示词里要写「只报告影响正确性或明确需求的差距,其余视为可选」,最终由人判断。
    5. 可预期的追问:Reviewer 需要什么输入?diff、计划或需求(PLAN.md)、明确的判据;给它 Writer 的推理过程反而会削弱独立性。再追问「能不能自动化」——能,-p 模式里一条命令跑 Reviewer,结果贴回 PR。

    Key points

    • Self-review suffers context bias: a session full of its own reasoning confirms rather than challenges
    • A Reviewer in a fresh context sees only the diff and criteria, so it critiques the code itself
    • Shapes: two terminals, an adversarial subagent, built-in /code-review; invert for test-first
    • Don't fix everything: reviewers always report something; limit findings to correctness and stated requirements

    答题要点

    • 自审受上下文偏置:装满自己推理的会话倾向于确认而非质疑
    • Reviewer 用全新上下文,只看 diff 与判据,挑的是代码本身的毛病
    • 形态:双终端、subagent 对抗式审查、内置 /code-review;反向可用于测试先行
    • 不要全改:审查者必报问题,照单全收导致过度工程;限定只报影响正确性的差距
  • When do you use the Claude Agent SDK versus the Messages API directly, and how do both relate to claude -p?Agent SDK 和直接调 Messages API 各适合什么场景?它们和 claude -p 是什么关系?
    Common in ChinaCommon overseasBasic#agent-sdk#messages-api

    How to reason about it · think before answering

    1. This tests layered understanding: all three entry points share one model; the difference is who supplies the loop and the tools. 'The SDK is higher level' says nothing.
    2. Messages API (@anthropic-ai/sdk / anthropic): one request, one response; you define tools, write the loop, manage context. Fits Q&A, extraction, classification, structured output, cited document Q&A, and custom agents where you want full control of the loop.
    3. Agent SDK (@anthropic-ai/claude-agent-sdk / claude-agent-sdk): Claude Code packaged as a library — built-in Read/Edit/Bash/Glob/Grep, the full agent loop, context management, permissions, hooks, subagents, sessions. You pass a task and options (allowedTools, permissionMode, maxTurns, systemPrompt) and it works in the filesystem. Fits embedding a code-editing agent in your own program.
    4. claude -p: the CLI form of the same Claude Code capabilities, for shell scripts and CI; the Agent SDK is its library form and the docs present them together. One-line rule: model call → API; filesystem agent → Agent SDK; quick scripted call → -p.
    5. Production nuance: with the Agent SDK you still own deployment (it supplies the harness, not hosting); auth is ANTHROPIC_API_KEY, and claude.ai subscription login can't be offered to third-party products. Follow-up: is the Agent SDK the same as the Messages API tool runner? No — the tool runner loops over tools you define and has no built-in file tools.

    分析过程 · 先想清楚再作答

    1. 这题考的是分层认知:三个入口底下是同一个模型,差别在于「谁提供循环和工具」。答成「SDK 更高级」没有信息量。
    2. Messages API(@anthropic-ai/sdk / anthropic):一次请求一次响应,工具由你定义、循环由你写、上下文由你管。适合问答、抽取、分类、结构化输出、带引用的文档问答,以及你想完全掌控循环的自定义 Agent。
    3. Agent SDK(@anthropic-ai/claude-agent-sdk / claude-agent-sdk):把 Claude Code 打包成库——内置 Read / Edit / Bash / Glob / Grep 等工具、完整的 agent 循环、上下文管理、权限系统、hooks、subagent、会话。你给一句任务和一组选项(allowedTools、permissionMode、maxTurns、systemPrompt),它在文件系统里干活。适合「在自己的程序里嵌一个会改代码的 agent」。
    4. claude -p:同一套 Claude Code 能力的命令行形态,适合 shell 脚本与 CI;Agent SDK 就是它的库形态,官方文档把两者放在同一页讲。判据一句话:要模型调用用 API,要文件系统里的 agent 用 Agent SDK,只想在脚本里调一下用 -p。
    5. 生产视角:Agent SDK 的部署仍是你自己的(它只提供循环,不提供托管),密钥走 ANTHROPIC_API_KEY,不能复用 claude.ai 的订阅登录给第三方产品。可预期的追问:Agent SDK 和 Messages API 里的 tool runner 是不是一回事?不是——tool runner 只帮你跑「你自己定义的工具」的循环,没有内置文件工具。

    Key points

    • Messages API: request/response, you write tools and the loop; for Q&A, extraction, structured output, custom agents
    • Agent SDK: Claude Code as a library with built-in file/Bash tools, loop, permissions, hooks; for embedding a code-editing agent
    • claude -p is the CLI form of the same capabilities, for scripts and CI
    • You still own deployment; auth via ANTHROPIC_API_KEY; the tool runner is not the Agent SDK

    答题要点

    • Messages API:一问一答,工具与循环自己写;适合问答、抽取、结构化输出、自定义 Agent
    • Agent SDK:Claude Code 的库形态,内置文件与 Bash 工具、循环、权限、hooks;适合嵌入会改代码的 agent
    • claude -p 是同一能力的命令行形态,适合脚本与 CI
    • 部署仍归自己,认证用 ANTHROPIC_API_KEY;tool runner 不是 Agent SDK

Comments