- 软件开发行业的 AI 范式演进:从辅助工具到工程智能体
- Claude Code 全景入门:装好、看懂、跑起来
- 上下文注入:用 @ 和 ! 精准喂给 Claude 它需要的信息
- 记忆系统:用 CLAUDE.md 告别每次对话都要"重新认识你"
- 斜杠命令:把你的重复操作变成一个单词
- Hooks 机制:让 AI 的每一步都在你的规则里
- MCP:给 Claude Code 接上"外设"
- Skills:让 Claude 按需加载你的领域知识
- Sub-agents:给 Claude 分身,让专家各司其职
- Agent Teams:组建你的 AI 开发小队
- 安全与回退:给 AI 戴上"安全带"
- SDK 与 Headless:把 Claude 变成你的自动化引擎
- 上下文工程:从记忆文件到分层知识架构
- 模型选择与成本控制:把每一分钱花在刀刃上
前面一直在讲怎么在终端里和 Claude Code 交互——打字、确认、看结果。这个模式适合探索性的开发工作,但软件工程里还有大量需要无人值守、重复执行的任务:
- 每次提 PR 自动跑一遍代码审查
- 每天凌晨分析前一天的错误日志
- 构建流水线里自动检查安全漏洞
- 批量处理几十个文件的格式统一
这些场景不需要人坐在终端前一问一答。需要的是把 Claude Code 的能力当成一个可编程的函数来调用——给输入,拿输出,自动退出。
Claude Code 提供了两种方式实现这个目标:Headless 模式(通过 CLI 的 -p 参数)适合脚本和 CI/CD 集成;Claude Agent SDK(TypeScript / Python 库)适合在你的应用程序里编程调用。
名称变更说明:Anthropic 已将 "Claude Code SDK" 正式更名为 Claude Agent SDK(包名
@anthropic-ai/claude-agent-sdk/claude-agent-sdk)。如果你之前用的是旧包名,参考官方的 Migration Guide 迁移。
Headless 模式:让 CLI 变成自动化工具
-p 参数:一切的起点
加上 -p(或 --print),Claude Code 就从"交互式对话"变成了"执行任务然后退出":
claude -p "分析这个项目的目录结构,列出主要模块"
Claude 执行任务,把结果打印到 stdout,然后退出。没有交互式界面,没有等待输入——就像 grep 或 jq 一样,是一个标准的命令行工具。
管道输入:处理大规模上下文
当输入内容很大时(日志文件、代码片段、测试结果),通过管道传入:
# 分析错误日志
cat /var/log/app/error.log | claude -p "总结主要的错误类型和可能的根因"
# 审查一个 PR 的变更
git diff main...HEAD | claude -p "审查这些代码变更,找出潜在问题"
# 分析测试覆盖率报告
go test -coverprofile=coverage.out ./... && \
go tool cover -func=coverage.out | claude -p "分析覆盖率报告,指出覆盖不足的模块"
管道传入的内容成为 Claude 的上下文,结合你的 prompt 一起处理。这让 Claude Code 像 awk、sed 一样嵌入你的 shell 工具链——只是这个"过滤器"具备语义理解能力。
结构化输出:--output-format
纯文本输出对人友好,但对程序不友好。--output-format 解决这个问题:
text(默认):纯文本,直接给人看。
json:任务完成后输出一个完整的 JSON 对象,包含结果、执行时间、token 消耗、成本等元数据。
claude -p "检查 internal/customer/ 目录有没有安全隐患" \
--output-format json > report.json
输出的 JSON 结构:
{
"type": "result",
"subtype": "success",
"is_error": false,
"duration_ms": 15230,
"num_turns": 3,
"result": "未发现严重安全隐患。有两处建议改进...",
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"total_cost_usd": 0.08,
"usage": {
"input_tokens": 12500,
"output_tokens": 890
}
}
在脚本里用 jq 提取你要的字段:
# 拿结果文本
jq -r '.result' report.json
# 检查是否成功
jq -r '.subtype' report.json
# 看成本
jq '.total_cost_usd' report.json
stream-json:实时流式输出,每一步都立即输出一个 JSON 对象(JSONL 格式)。适合需要实时反馈的场景——比如 CI 日志里想看到 Claude 执行到了哪一步。
claude -p "审查代码" --output-format stream-json --verbose
权限控制
Headless 模式下没有人在终端前点"确认",所以权限控制尤其重要。
推荐做法:通过 --allowedTools 精确指定允许的工具,配合 --permission-mode:
# 只读分析——只给读权限
claude -p "分析代码结构" \
--allowedTools "Read" "Grep" "Glob" \
--permission-mode default
# 需要跑测试——精确授权
claude -p "运行所有单元测试并分析失败原因" \
--allowedTools "Bash(go test *)" "Read" "Grep" \
--permission-mode acceptEdits
如果在严格沙箱环境(容器/VM)里运行,可以用 --dangerously-skip-permissions 跳过所有权限检查,让 Claude 全速自动工作。但只在你确定环境隔离的情况下使用。
更多有用的参数
--max-turns:限制 Agent 的执行轮次。防止 Claude 在某个任务上无限循环。
claude -p "修复 lint 错误" --max-turns 10
--max-budget-usd:设置花费上限。到了就停。
claude -p "全面代码审查" --max-budget-usd 5.00
--model:指定模型。简单任务用 haiku 省钱,复杂任务用 opus。
claude -p "格式化这些文件" --model haiku
--json-schema:让输出严格匹配指定的 JSON Schema。适合需要机器解析的场景。
claude -p "列出所有 API 端点" \
--json-schema '{"type":"object","properties":{"endpoints":{"type":"array","items":{"type":"object","properties":{"method":{"type":"string"},"path":{"type":"string"},"description":{"type":"string"}}}}}}'
--append-system-prompt:在默认 system prompt 基础上追加指令,保留 Claude Code 的默认能力。
claude -p "审查代码" --append-system-prompt "所有输出用中文"
-c / --resume:继续之前的会话。-c 继续最近一次,--resume 指定会话 ID。
# 第一次运行
claude -p "分析项目架构" --output-format json > step1.json
# 基于前一次继续
SESSION_ID=$(jq -r '.session_id' step1.json)
claude -p "基于刚才的分析,生成重构方案" --resume "$SESSION_ID"
实战:CI 中的自动代码审查
把 Headless 模式用在最典型的场景——GitHub Actions 里的 PR 自动审查。
name: AI Code Review
on:
pull_request:
types: [opened, synchronize]
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Claude Code
run: npm install -g @anthropic-ai/claude-code
- name: Run AI Review
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
git diff origin/main...HEAD | claude -p \
"审查这些 Go 代码变更。重点关注:
1. 是否有安全隐患(SQL 注入、XSS、敏感数据泄露)
2. 错误处理是否完善
3. 并发安全性
输出格式:先列高风险问题,再列建议改进。" \
--allowedTools "Read" "Grep" "Glob" \
--output-format json \
--max-budget-usd 2.00 > review.json
- name: Post Review Comment
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const report = JSON.parse(fs.readFileSync('review.json', 'utf8'));
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `## AI Code Review\n\n${report.result}\n\n---\n_Cost: $${report.total_cost_usd.toFixed(4)} | Turns: ${report.num_turns}_`
});
这个流水线的关键:
git diff通过管道把增量代码传给 Claude——精确的上下文--allowedTools只给读权限——CI 里不需要 Claude 改文件--output-format json拿到结构化结果——可以提取字段、判断是否有高风险问题--max-budget-usd设置花费上限——防止意外的高成本
你还可以更进一步:用 --json-schema 让 Claude 输出结构化的审查结果,然后在脚本里判断是否有高风险问题——有的话让 CI 流水线失败,强制修复后才能合入。
Claude Agent SDK:在你的程序里编程调用
Headless 模式通过 CLI 调用,适合脚本和 CI。但如果你在开发一个应用程序——比如一个内部的代码审查平台、一个自动化运维工具——需要在代码里直接调用 Claude 的能力,就需要 Agent SDK。
Agent SDK 和 Anthropic 的 Client SDK(直接调 API 的 @anthropic-ai/sdk)不是同一个东西。Client SDK 给你原始的 API 调用——你自己实现 tool loop。Agent SDK 给你完整的 Agent 引擎——内置工具执行、上下文管理、会话持久化,Claude 自己决定怎么用工具完成任务。
# Client SDK:你自己实现 tool loop
response = client.messages.create(...)
while response.stop_reason == "tool_use":
result = your_tool_executor(response.tool_use)
response = client.messages.create(tool_result=result, **params)
# Agent SDK:Claude 自己处理工具调用
async for message in query(prompt="修复 auth.py 的 bug"):
print(message) # Claude 自己读文件、找 bug、改代码
安装
# TypeScript
npm install @anthropic-ai/claude-agent-sdk
# Python
pip install claude-agent-sdk
需要 Node.js 18+(TypeScript)或 Python 3.10+(Python)。认证方式:ANTHROPIC_API_KEY 环境变量,也支持 AWS Bedrock(CLAUDE_CODE_USE_BEDROCK=1)、Google Vertex AI(CLAUDE_CODE_USE_VERTEX=1)和 Azure AI Foundry(CLAUDE_CODE_USE_FOUNDRY=1)。
内置工具
Agent SDK 自带一套开箱即用的工具,不需要你自己实现:
| 工具 | 能力 |
|---|---|
| Read | 读取工作目录下的任何文件 |
| Write | 创建新文件 |
| Edit | 精确编辑已有文件 |
| Bash | 执行终端命令、脚本、git 操作 |
| Glob | 按模式查找文件 |
| Grep | 正则搜索文件内容 |
| WebSearch | 搜索网页获取最新信息 |
| WebFetch | 抓取并解析网页内容 |
| AskUserQuestion | 向用户提问澄清问题 |
通过 allowedTools 控制 Agent 能用哪些工具——权限最小化原则。
query():一次性任务
给一个 prompt,Claude 自主决定使用工具完成任务,流式返回中间过程和最终结果。
TypeScript:
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "分析 internal/customer/ 目录的代码质量",
options: {
allowedTools: ["Read", "Grep", "Glob"],
permissionMode: "acceptEdits",
},
})) {
if (message.type === "assistant") {
for (const block of message.message.content) {
if ("text" in block) console.log(block.text);
else if ("name" in block) console.log(`工具: ${block.name}`);
}
} else if (message.type === "result") {
console.log("结果:", message.result);
console.log("成本:", message.total_cost_usd);
}
}
Python:
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, ResultMessage
async def main():
async for message in query(
prompt="分析 internal/customer/ 目录的代码质量",
options=ClaudeAgentOptions(
allowed_tools=["Read", "Grep", "Glob"],
permission_mode="acceptEdits",
),
):
if isinstance(message, AssistantMessage):
for block in message.content:
if hasattr(block, "text"):
print(block.text)
elif hasattr(block, "name"):
print(f"工具: {block.name}")
elif isinstance(message, ResultMessage):
print(f"结果: {message.result}")
print(f"成本: {message.total_cost_usd}")
asyncio.run(main())
query() 返回一个 async generator(TS)或 async iterator(Python),流式 yield 消息。消息类型包括:
assistant:Claude 的推理和工具调用result:最终结果,包含result、total_cost_usd、session_id等
ClaudeSDKClient:多轮对话
维护会话状态,支持多次来回。适合交互式应用、需要上下文延续的场景。
Python(推荐用法——async context manager):
import asyncio
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions, ResultMessage
async def main():
options = ClaudeAgentOptions(
allowed_tools=["Read", "Edit", "Glob", "Grep"],
)
async with ClaudeSDKClient(options=options) as client:
# 第一轮:client 自动保存 session ID
await client.query("分析 auth 模块的架构")
async for message in client.receive_response():
if isinstance(message, ResultMessage):
print(message.result)
# 第二轮:自动延续同一个 session
await client.query("基于刚才的分析,重构为 JWT 方案")
async for message in client.receive_response():
if isinstance(message, ResultMessage):
print(message.result)
asyncio.run(main())
TypeScript(使用 continue: true):
import { query } from "@anthropic-ai/claude-agent-sdk";
// 第一轮:创建新 session
for await (const message of query({
prompt: "分析 auth 模块的架构",
options: { allowedTools: ["Read", "Glob", "Grep"] },
})) {
if (message.type === "result") console.log(message.result);
}
// 第二轮:continue: true 自动找到最近的 session 继续
for await (const message of query({
prompt: "基于刚才的分析,重构为 JWT 方案",
options: {
continue: true,
allowedTools: ["Read", "Edit", "Write", "Glob", "Grep"],
},
})) {
if (message.type === "result") console.log(message.result);
}
会话管理:continue / resume / fork
SDK 的会话管理比 CLI 的 --resume 更完整,提供三种模式:
| 模式 | 场景 | 说明 |
|---|---|---|
| continue | 单进程多轮对话 | 自动续接当前目录最近的 session,不需要 ID |
| resume | 跨进程恢复指定会话 | 通过 session ID 恢复,适合多用户 / 后台任务 |
| fork | 保留原始线索、探索新方向 | 复制原始会话历史并分叉,两个 session 独立演进 |
Fork 是个特别有用的模式。比如 SCRM 里分析了一个客户转化漏斗,想同时尝试两种优化策略——fork 出一个新 session 试 A 方案,原始 session 继续 B 方案,两边互不影响:
# 原始分析
session_id = None
async for message in query(
prompt="分析客户转化漏斗的瓶颈",
options=ClaudeAgentOptions(allowed_tools=["Read", "Grep"]),
):
if isinstance(message, ResultMessage):
session_id = message.session_id
# Fork:基于同样的分析上下文,尝试不同方案
async for message in query(
prompt="尝试用标签体系重构方案优化转化率",
options=ClaudeAgentOptions(resume=session_id, fork_session=True),
):
if isinstance(message, ResultMessage):
forked_id = message.session_id # 新的 session ID
# 原始 session 不受影响,继续另一个方向
async for message in query(
prompt="尝试用客户生命周期分层方案优化",
options=ClaudeAgentOptions(resume=session_id),
):
pass
Session 文件存在
~/.claude/projects/<编码后的cwd>/<session-id>.jsonl。跨机器恢复需要把这个文件迁移过去,且 cwd 路径要一致。
权限模式
SDK 支持四种权限模式,和 CLI 的权限体系对应:
| 模式 | 行为 | 适用场景 |
|---|---|---|
acceptEdits | 自动批准文件编辑,其他操作需确认 | 可信的开发工作流 |
dontAsk(仅 TS) | 不在 allowedTools 里的直接拒绝 | 无人值守的锁定 Agent |
bypassPermissions | 所有工具无需确认直接执行 | 沙箱/CI 环境 |
default | 通过 canUseTool 回调自定义审批 | 需要精细控制的场景 |
SDK Hooks:Agent 生命周期拦截
SDK 的 Hooks 和 CLI 的 shell 命令 Hooks 不同——它是回调函数,直接在你的代码里定义,可以拦截、阻止、修改 Agent 的行为。
可用的 Hook 事件:
| 事件 | 触发时机 | 典型用途 |
|---|---|---|
PreToolUse | 工具调用前 | 阻止危险操作、修改输入 |
PostToolUse | 工具执行后 | 记录审计日志、追加上下文 |
Stop | Agent 停止时 | 保存状态、发通知 |
Notification | Agent 状态消息 | 转发到 Slack/钉钉 |
SubagentStart/Stop | Sub-agent 启停 | 追踪并行任务 |
PermissionRequest | 权限确认前 | 自定义审批逻辑 |
一个实际的例子——SCRM 系统里保护敏感文件:
from claude_agent_sdk import query, ClaudeAgentOptions, HookMatcher
async def protect_sensitive_files(input_data, tool_use_id, context):
"""阻止修改 .env 和客户数据配置文件"""
file_path = input_data["tool_input"].get("file_path", "")
blocked_patterns = [".env", "secrets", "credentials", "customer_keys"]
if any(p in file_path for p in blocked_patterns):
return {
"hookSpecificOutput": {
"hookEventName": input_data["hook_event_name"],
"permissionDecision": "deny",
"permissionDecisionReason": f"禁止修改敏感文件: {file_path}",
}
}
return {} # 空对象 = 放行
async def audit_logger(input_data, tool_use_id, context):
"""记录所有工具调用到审计日志"""
with open("./agent_audit.log", "a") as f:
f.write(f"{input_data['tool_name']}: {input_data['tool_input']}\n")
return {}
async def main():
async for message in query(
prompt="重构客户管理模块",
options=ClaudeAgentOptions(
allowed_tools=["Read", "Edit", "Write", "Glob", "Grep"],
permission_mode="acceptEdits",
hooks={
"PreToolUse": [
HookMatcher(matcher="Write|Edit", hooks=[protect_sensitive_files]),
HookMatcher(hooks=[audit_logger]), # 无 matcher = 匹配所有工具
],
},
),
):
pass
Hook 回调的返回值决定 Agent 的行为:
{}空对象:放行,不干预permissionDecision: "deny":阻止这次工具调用permissionDecision: "allow":自动批准(跳过权限确认)updatedInput:修改工具输入参数(必须同时返回permissionDecision: "allow")systemMessage:注入一条消息到对话上下文(Agent 能看到)
优先级:deny > ask > allow。多个 Hook 只要有一个返回 deny,操作就被阻止。
自定义工具和 MCP
SDK 支持连接外部 MCP 服务器,给 Agent 注入额外能力:
# Python:连接 Playwright MCP 让 Agent 能操作浏览器
async for message in query(
prompt="打开 example.com 并描述页面内容",
options=ClaudeAgentOptions(
mcp_servers={
"playwright": {"command": "npx", "args": ["@playwright/mcp@latest"]}
}
),
):
if hasattr(message, "result"):
print(message.result)
// TypeScript:同样的 MCP 连接
for await (const message of query({
prompt: "打开 example.com 并描述页面内容",
options: {
mcpServers: {
playwright: { command: "npx", args: ["@playwright/mcp@latest"] }
}
}
})) {
if ("result" in message) console.log(message.result);
}
你还可以把自己的业务 API 包装成 MCP 工具。比如在 SCRM 系统里,把客户数据查询暴露给 Agent:
import { query, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
const scrmTools = createSdkMcpServer({
tools: {
get_customer_data: {
description: "查询 SCRM 系统的客户数据",
parameters: {
customer_id: { type: "string", description: "客户 ID" },
},
handler: async ({ customer_id }) => {
const data = await fetchCustomer(customer_id);
return JSON.stringify(data);
},
},
},
});
for await (const message of query({
prompt: "查询客户 C001 的跟进记录,分析最近的互动趋势",
options: { mcpServers: [scrmTools] },
})) {
if ("result" in message) console.log(message.result);
}
Sub-agents:Agent 里的 Agent
SDK 支持定义专门化的 Sub-agents,由主 Agent 按需委派任务。注意 allowedTools 必须包含 Agent 才能触发 Sub-agent 调用:
from claude_agent_sdk import query, ClaudeAgentOptions, AgentDefinition
async for message in query(
prompt="用 code-reviewer 审查这个项目",
options=ClaudeAgentOptions(
allowed_tools=["Read", "Glob", "Grep", "Agent"],
agents={
"code-reviewer": AgentDefinition(
description="资深代码审查员,关注质量和安全。",
prompt="分析代码质量并提出改进建议。",
tools=["Read", "Glob", "Grep"],
)
},
),
):
if hasattr(message, "result"):
print(message.result)
Sub-agent 内部的消息会带有 parent_tool_use_id 字段,方便追踪哪些消息属于哪个 Sub-agent 的执行上下文。
加载项目配置
SDK 默认不加载 CLAUDE.md、Skills、斜杠命令等项目级配置。需要显式指定 settingSources:
const messages = query({
prompt: "审查代码",
options: {
settingSources: ["project"], // 加载 CLAUDE.md、.claude/skills/、.claude/commands/
},
});
options = ClaudeAgentOptions(
setting_sources=["project"], # 同样效果
)
结构化输出
SDK 支持 JSON Schema 约束输出格式,确保结果可以直接被程序解析:
for await (const message of query({
prompt: "列出这个项目的所有 API 端点",
options: {
jsonSchema: {
type: "object",
properties: {
endpoints: {
type: "array",
items: {
type: "object",
properties: {
method: { type: "string" },
path: { type: "string" },
description: { type: "string" },
},
},
},
},
},
},
})) {
if (message.type === "result") console.log(JSON.parse(message.result));
}
Headless vs SDK:怎么选
Headless (-p) | Agent SDK | |
|---|---|---|
| 调用方式 | CLI 命令 | TypeScript / Python 函数 |
| 适合 | Shell 脚本、CI/CD、一次性任务 | 应用程序集成、复杂工作流 |
| 会话管理 | --resume / -c | continue / resume / fork |
| Hooks | shell 命令(settings.json) | 回调函数(可拦截、修改、阻止) |
| 自定义工具 | 通过 MCP config 文件 | createSdkMcpServer 编程定义 |
| 输出处理 | jq 解析 JSON | 直接在代码里处理对象 |
| 项目配置 | 自动加载 CLAUDE.md | 需要 settingSources: ["project"] |
| 部署复杂度 | 低(只要装了 Claude Code) | 中(需要 Node.js/Python 项目) |
简单规则:能用 CLI 解决的用 Headless,需要嵌入应用程序的用 SDK。 两者底层引擎完全相同,SDK 额外提供了编程级的 Hooks 拦截和会话 fork 能力。
几条实践建议
从只读开始。 自动化任务的第一版,只给 Read, Grep, Glob 权限。确认效果后再逐步开放写权限。SDK 里用 allowedTools,CLI 里用 --allowedTools。
设置花费上限。 无人值守的任务一定要设 --max-budget-usd(CLI)或 maxBudgetUsd(SDK)。CI 里一个 PR 审查 2-5 美元通常够了。忘了设上限可能因为死循环烧掉大量预算。
设置轮次上限。 --max-turns / maxTurns 防止 Agent 无限循环。大多数任务 10-20 轮足够。
用结构化输出做决策。 在 CI 里不要只打印文本——用 --output-format json 或 --json-schema 拿到结构化结果,程序判断是通过还是失败。
会话续接省成本。 多步骤的自动化流程,用 --resume 或 SDK 的 continue 复用前一步的会话,避免重新加载上下文。
用 Hooks 做审计。 SDK 的 PostToolUse Hook 天然适合记录审计日志——每次工具调用都能拿到工具名、参数、结果。比在 CLI 的 json 输出里事后分析更实时。
敏感文件加 PreToolUse 守护。 在 SDK 里用 PreToolUse Hook 拦截对 .env、credentials、secrets 的写操作。这比只靠 allowedTools 更精细——你可以只阻止特定路径,而不是完全禁用 Write 工具。
项目配置别忘了显式加载。 SDK 默认不加载 CLAUDE.md 和 Skills。如果你的项目依赖这些配置,记得加 settingSources: ["project"]。
到这里,系列的核心内容全部覆盖了。从第一篇的 CLAUDE.md 记忆系统,到这一篇的 SDK 和自动化集成——Claude Code 从一个交互式工具变成了一个完整的 AI 工程平台。
回顾整个体系:CLAUDE.md 管记忆,斜杠命令管流程复用,Hooks 管硬约束,MCP 管能力扩展,Skills 管按需知识,Sub-agents 管上下文隔离,Agent Teams 管多实例协作,权限 + 沙箱 + Checkpointing 管安全,Headless + SDK 管自动化集成。
不需要全部用上。从你的实际痛点出发——上下文被塞满了?用 Sub-agents。规范老是被遗忘?用 Skills。CI 里想加 AI 审查?用 Headless。按需取用,逐步深入。
下篇见。