第14章:Agent SDK 开发实战
概述
Claude Agent SDK 是 Anthropic 提供的官方开发工具包,它让你能够构建自定义的 AI Agent,将 Claude 的能力嵌入到自己的应用和工作流中。与直接调用 Claude API 不同,Agent SDK 提供了工具定义、对话管理、上下文维护等高级抽象,让你可以专注于业务逻辑而非基础设施。本章将从基础概念到实战项目,全面讲解 Agent SDK 的使用。
Claude Agent SDK 核心概念
Agent 架构模型
Agent SDK 的核心是一个事件驱动的循环架构,Agent 接收用户输入,决定使用哪些工具,执行工具调用,并将结果整合到回复中。
用户输入 → Agent 推理 → 工具选择 → 工具执行 → 结果整合 → 输出
↑ │
└────────── 循环直到完成 ──────────────┘
核心组件
| 组件 | 职责 | 类比 |
|---|---|---|
| Agent | 顶层协调器,管理整个交互流程 | 项目经理 |
| Tool | 可执行的功能单元,Agent 可以调用 | 团队成员 |
| Context | 对话状态和上下文存储 | 项目白板 |
| Middleware | 请求/响应处理中间件 | 流程审批 |
| Memory | 长期记忆存储和管理 | 档案室 |
SDK 安装与初始化
环境准备
# 创建项目目录
mkdir my-code-review-agent
cd my-code-review-agent
# 初始化项目
npm init -y
# 安装 Claude Agent SDK
npm install @anthropic-ai/agent-sdk
# 安装 TypeScript 支持
npm install -D typescript @types/node ts-node
# 创建 tsconfig.json
npx tsc --init --target ES2022 --module NodeNext --moduleResolution NodeNext
基础初始化代码
// src/index.ts
import { Agent } from "@anthropic-ai/agent-sdk";
// 初始化 Agent 实例
const agent = new Agent({
name: "code-reviewer",
model: "claude-sonnet-4-20250514",
apiKey: process.env.ANTHROPIC_API_KEY,
systemPrompt: `你是一个专业的代码审查助手。
你的职责是:
1. 检查代码质量和安全性
2. 发现潜在的性能问题
3. 提供改进建议
4. 确保代码风格一致性
请使用中文输出审查结果,并在每个问题上标注严重级别。`,
});
// 启动交互会话
async function main() {
const response = await agent.run(
"请审查下面的 React 组件代码..."
);
console.log(response.text);
}
main().catch(console.error);
构建自定义 Agent
定义工具
工具是 Agent 能力的核心,它让 Agent 能够与外部系统交互。
// src/tools.ts
import { Tool } from "@anthropic-ai/agent-sdk";
import fs from "fs/promises";
// 工具一:文件读取工具
const readFileTool: Tool = {
name: "read_file",
description: "读取项目中的源代码文件",
parameters: {
type: "object",
properties: {
filePath: {
type: "string",
description: "文件路径,相对于项目根目录",
},
},
required: ["filePath"],
},
execute: async ({ filePath }: { filePath: string }) => {
try {
const content = await fs.readFile(filePath, "utf-8");
return { success: true, content };
} catch (error) {
return { success: false, error: `无法读取文件: ${error}` };
}
},
};
// 工具二:代码分析工具
const analyzeCodeTool: Tool = {
name: "analyze_complexity",
description: "分析代码的圈复杂度",
parameters: {
type: "object",
properties: {
code: {
type: "string",
description: "要分析的源代码",
},
},
required: ["code"],
},
execute: async ({ code }: { code: string }) => {
const patterns = [
/ifs*(/g, /elses/g, /fors*(/g,
/whiles*(/g, /switchs*(/g, /&&/g,
/||/g, /?/g, /catchs*(/g,
];
let score = 0;
const details: Record<string, number> = {};
for (const pattern of patterns) {
const matches = code.match(pattern);
if (matches) {
const key = pattern.source;
details[key] = matches.length;
score += matches.length;
}
}
return {
complexity_score: score,
details,
risk_level: score > 20 ? "high" : score > 10 ? "medium" : "low",
suggestion:
score > 20
? "建议将复杂函数拆分为多个小函数"
: "代码复杂度在可接受范围内",
};
},
};
// 工具三:Git 历史查询工具
const gitHistoryTool: Tool = {
name: "git_history",
description: "查询指定文件的 Git 提交历史",
parameters: {
type: "object",
properties: {
filePath: {
type: "string",
description: "文件路径",
},
maxCount: {
type: "number",
description: "最大返回提交数",
default: 10,
},
},
required: ["filePath"],
},
execute: async ({
filePath,
maxCount = 10,
}: {
filePath: string;
maxCount: number;
}) => {
const { execSync } = await import("child_process");
try {
const output = execSync(
`git log --oneline -n ${maxCount} -- "${filePath}"`,
{ encoding: "utf-8" }
);
const commits = output
.trim()
.split("\n")
.filter(Boolean)
.map((line) => {
const [hash, ...msg] = line.split(" ");
return { hash, message: msg.join(" ") };
});
return { success: true, commits };
} catch (error) {
return { success: false, error: `Git 命令执行失败: ${error}` };
}
},
};
组装完整的 Agent
// src/agent.ts
import { Agent } from "@anthropic-ai/agent-sdk";
import {
readFileTool,
analyzeCodeTool,
gitHistoryTool,
} from "./tools.js";
export function createCodeReviewAgent(): Agent {
return new Agent({
name: "code-review-bot",
model: "claude-sonnet-4-20250514",
apiKey: process.env.ANTHROPIC_API_KEY,
maxTokens: 4096,
temperature: 0.3, // 低温度确保审查结果稳定
tools: [readFileTool, analyzeCodeTool, gitHistoryTool],
systemPrompt: `你是一个专业的代码审查机器人。
工作流程:
1. 首先使用 read_file 读取目标文件
2. 使用 analyze_complexity 分析代码复杂度
3. 使用 git_history 查看文件的修改历史
4. 综合以上信息,给出全面的审查报告
审查报告格式:
- 🔴 严重问题:安全漏洞、数据泄露风险等
- 🟡 警告:性能问题、代码异味
- 🔵 建议:代码风格、可读性改进
- ✅ 亮点:值得表扬的优秀实现
输出要求:
- 每个问题标注行号
- 给出具体的修改建议和示例代码
- 按严重程度排序
- 使用中文输出`,
// 对话管理配置
conversation: {
maxTurns: 50,
persistence: true,
storage: "file",
storagePath: "./data/conversations",
},
});
}
Agent 与 API 直接调用的差异
了解 Agent SDK 和直接 API 调用的区别,有助于在项目中做出正确的技术选型。
| 对比维度 | Agent SDK | 直接 API 调用 |
|---|---|---|
| 工具调用 | 内置工具定义和自动执行 | 需要手动解析 tool_use |
| 对话管理 | 自动维护上下文窗口 | 手动管理消息历史 |
| 重试逻辑 | 内置指数退避重试 | 需要自行实现 |
| 流式输出 | 原生支持 | 需要额外配置 |
| 中间件 | 支持请求/响应拦截 | 无内置支持 |
| 记忆管理 | 内置短期/长期记忆 | 需自行实现向量存储 |
| 并发控制 | 内置请求队列 | 需自行实现限流 |
| 调试工具 | 内置日志和追踪 | 无 |
| 定制灵活度 | 中等(符合最佳实践) | 最高(完全控制) |
| 开发效率 | 高 | 低 |
实战:用 SDK 构建一个代码审查机器人
完整实现
// src/main.ts
import { createCodeReviewAgent } from "./agent.js";
import fs from "fs/promises";
interface ReviewRequest {
targetDir: string;
filePattern?: string;
strictMode?: boolean;
}
interface ReviewReport {
summary: {
filesReviewed: number;
criticalIssues: number;
warnings: number;
suggestions: number;
};
details: Array<{
file: string;
issues: Array<{
type: "critical" | "warning" | "suggestion";
line?: number;
message: string;
suggestion?: string;
}>;
highlights: string[];
}>;
score: number;
}
class CodeReviewBot {
private agent;
private report: ReviewReport = {
summary: { filesReviewed: 0, criticalIssues: 0, warnings: 0, suggestions: 0 },
details: [],
score: 100,
};
constructor() {
this.agent = createCodeReviewAgent();
}
async reviewProject(request: ReviewRequest): Promise<ReviewReport> {
const pattern = request.filePattern || "**/*.{ts,tsx,js,jsx}";
const { globSync } = await import("glob");
const files = globSync(pattern, { cwd: request.targetDir });
console.log(`📁 发现 ${files.length} 个待审查文件`);
for (const file of files.slice(0, 20)) {
// 限制最多审查 20 个文件
console.log(`🔍 正在审查: ${file}`);
const fileReview = await this.reviewFile(file, request.targetDir);
this.report.details.push(fileReview);
this.report.summary.filesReviewed++;
for (const issue of fileReview.issues) {
if (issue.type === "critical") this.report.summary.criticalIssues++;
else if (issue.type === "warning") this.report.summary.warnings++;
else this.report.summary.suggestions++;
}
}
// 计算总体评分
this.report.score = Math.max(
0,
100 -
this.report.summary.criticalIssues * 10 -
this.report.summary.warnings * 3 -
this.report.summary.suggestions * 1
);
await this.saveReport();
return this.report;
}
private async reviewFile(
file: string,
targetDir: string
): Promise<ReviewReport["details"][0]> {
const filePath = `${targetDir}/${file}`;
const content = await fs.readFile(filePath, "utf-8");
const response = await this.agent.run(
`请审查以下文件,关注安全性、性能、代码质量:\n\n${content}`
);
return {
file: filePath,
issues: response.text.match(/🔴|🟡|🔵/g)?.map((marker) => ({
type: marker === "🔴" ? "critical" : marker === "🟡" ? "warning" : "suggestion",
message: "请查看完整审查报告",
})) || [],
highlights: [],
};
}
private async saveReport(): Promise<void> {
await fs.mkdir("./reports", { recursive: true });
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
await fs.writeFile(
`./reports/review-${timestamp}.json`,
JSON.stringify(this.report, null, 2)
);
console.log(`📊 报告已保存: reports/review-${timestamp}.json`);
}
}
// 启动审查机器人
async function main() {
const bot = new CodeReviewBot();
const report = await bot.reviewProject({
targetDir: process.argv[2] || ".",
filePattern: "src/**/*.{ts,tsx}",
strictMode: true,
});
console.log(`
╔═══════════════════════════╗
║ 代码审查报告摘要 ║
╠═══════════════════════════╣
║ 审查文件: ${report.summary.filesReviewed.toString().padEnd(12)} ║
║ 严重问题: ${report.summary.criticalIssues.toString().padEnd(12)} ║
║ 警告: ${report.summary.warnings.toString().padEnd(12)} ║
║ 建议: ${report.summary.suggestions.toString().padEnd(12)} ║
║ 综合评分: ${report.score.toString().padEnd(12)} ║
╚═══════════════════════════╝
`);
}
main().catch(console.error);
SDK 配置优化
模型选择策略
// src/config.ts
import { AgentConfig } from "@anthropic-ai/agent-sdk";
export function getOptimizedConfig(taskType: string): Partial<AgentConfig> {
const configs: Record<string, Partial<AgentConfig>> = {
// 代码审查:需要高准确性,使用 Sonnet
"code-review": {
model: "claude-sonnet-4-20250514",
temperature: 0.2,
maxTokens: 8192,
systemPrompt: "你是一个严谨的代码审查员...",
},
// 创意任务:需要多样性,使用 Sonnet 较高温度
"creative": {
model: "claude-sonnet-4-20250514",
temperature: 0.8,
maxTokens: 4096,
},
// 批量处理:使用 Haiku 降低成本
"batch-processing": {
model: "claude-haiku-4-20250514",
temperature: 0.1,
maxTokens: 2048,
},
// 复杂推理:使用 Opus 应对高难度任务
"complex-reasoning": {
model: "claude-opus-4-20250514",
temperature: 0.3,
maxTokens: 16384,
thinking: {
type: "enabled",
budgetTokens: 8192,
},
},
};
return configs[taskType] || configs["code-review"];
}
Token 管理策略
// Token 预算管理
const tokenBudgets = {
// 每个会话的 Token 预算
perSession: {
maxInputTokens: 64000,
maxOutputTokens: 16384,
warningThreshold: 0.8, // 达到 80% 时发出警告
},
// 上下文窗口压缩策略
compression: {
enabled: true,
strategy: "summarize_oldest",
keepRecentTurns: 10,
summaryInterval: 20, // 每 20 轮对话压缩一次
},
};
本章小结
通过本章的学习,你掌握了 Claude Agent SDK 的核心概念和完整开发流程:
- 理解 Agent 架构中各个组件的职责
- 学会安装 SDK 并完成初始化配置
- 掌握工具定义的最佳实践
- 了解 Agent SDK 与直接 API 调用的适用场景
- 能够构建具备复杂交互能力的自定义 Agent
- 学会根据任务类型优化模型和 Token 配置
Agent SDK 将 AI 能力从"单次问答"提升到了"持续协作"的层次,让 Claude 能够在复杂的业务场景中发挥更大的价值。