Posts Claude Agent SDK 完整指南:从零开始构建 AI Agent
Post
Cancel

Claude Agent SDK 完整指南:从零开始构建 AI Agent

引言

如果你使用过 Claude Code,你一定见识过 AI 代理的强大能力:读取文件、执行命令、编辑代码、自主规划任务步骤。它不仅仅是帮你写代码,而是像一位有思考能力的工程师一样,主动接手问题并系统性地解决它们。

现在,支撑 Claude Code 的核心引擎——Claude Agent SDK——已经开放给所有开发者。你可以用它来构建自己的 AI 代理,解决各种实际问题。

本指南将带你从零开始,学习如何使用 Claude Agent SDK 构建一个完整的代码审查代理。更重要的是,你将深入理解 SDK 的工作原理,从而能够构建任何你需要的代理应用。

什么是 Claude Agent SDK?

Claude Agent SDK 是 Claude Code 背后的基础设施,以库的形式对外开放。它为你提供了:

  • 🔄 代理循环(Agent Loop):自动管理与 AI 的多轮交互

  • 🛠️ 内置工具:文件操作、命令执行、代码搜索等开箱即用

  • 💾 上下文管理:自动处理对话历史和工作状态

  • 📦 完整的代理框架:你本来需要从头实现的所有功能

简单来说,你不需要重新发明轮子,SDK 已经把构建代理所需的所有基础设施都准备好了。

为什么使用 Agent SDK?

如果你曾经用原始 API 构建过代理,你一定知道那个繁琐的流程:调用模型 → 检查是否需要工具 → 执行工具 → 将结果反馈给模型 → 重复直到完成。对于复杂任务来说,这很快就会变得难以维护。

SDK 为你管理这个循环:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 不使用 SDK:你需要手动管理循环
let response = await client.messages.create({...});
while (response.stop_reason === "tool_use") {
  const result = yourToolExecutor(response.tool_use);
  response = await client.messages.create({
    tool_result: result,
    ...
  });
}

// 使用 SDK:Claude 自动管理
for await (const message of query({
  prompt: "Fix the bug in auth.py"
})) {
  console.log(message); // Claude 会自动读取文件、定位 bug、编辑代码
}

内置工具,开箱即用:

  • 📖 Read:读取工作目录中的任何文件

  • ✍️ Write:创建新文件

  • ✏️ Edit:对现有文件进行精确编辑

  • 💻 Bash:运行终端命令

  • 🔍 Glob:按模式查找文件

  • 🔎 Grep:用正则表达式搜索文件内容

  • 🌐 WebSearch:网络搜索

  • 📄 WebFetch:获取和解析网页

所有这些工具都不需要你自己实现。

准备工作

环境要求

安装步骤

步骤 1:安装 Claude Code CLI

Agent SDK 使用 Claude Code 作为运行时环境:

1
npm install -g @anthropic-ai/claude-code

安装完成后,在终端运行 claude 并按提示进行身份验证。

步骤 2:创建项目

1
2
3
4
mkdir code-review-agent && cd code-review-agent
npm init -y
npm install @anthropic-ai/claude-agent-sdk
npm install -D typescript @types/node tsx

步骤 3:设置 API 密钥

1
export ANTHROPIC_API_KEY=your-api-key

快速开始

让我们从一个简单的示例开始。创建 agent.ts 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import { query } from "@anthropic-ai/claude-agent-sdk";

async function main() {
  for await (const message of query({
    prompt: "What files are in this directory?",
    options: {
      model: "opus",
      allowedTools: ["Glob", "Read"],
      maxTurns: 250
    }
  })) {
    if (message.type === "assistant") {
      for (const block of message.message.content) {
        if ("text" in block) {
          console.log(block.text);
        }
      }
    }
    
    if (message.type === "result") {
      console.log("
Done:", message.subtype);
    }
  }
}

main();

运行它:

1
npx tsx agent.ts

Claude 会使用 Glob 工具列出文件并告诉你发现了什么。就这么简单!

核心概念:理解消息流

query() 函数返回一个异步生成器,在 Claude 工作时流式传输消息。以下是关键的消息类型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
for await (const message of query({ prompt: "..." })) {
  switch (message.type) {
    case "system":
      // 会话初始化信息
      if (message.subtype === "init") {
        console.log("Session ID:", message.session_id);
        console.log("Available tools:", message.tools);
      }
      break;
      
    case "assistant":
      // Claude 的响应和工具调用
      for (const block of message.message.content) {
        if ("text" in block) {
          console.log("Claude:", block.text);
        } else if ("name" in block) {
          console.log("Tool call:", block.name);
        }
      }
      break;
      
    case "result":
      // 最终结果
      console.log("Status:", message.subtype); // "success" 或错误类型
      console.log("Cost:", message.total_cost_usd);
      break;
  }
}

这个消息流机制让你能够:

  • 实时监控代理的工作进度

  • 记录工具调用日志

  • 处理错误和异常

  • 追踪 API 成本

实战项目:构建代码审查代理

现在让我们构建一个真正有用的应用。创建 review-agent.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import { query } from "@anthropic-ai/claude-agent-sdk";

async function reviewCode(directory: string) {
  console.log(`
🔍 Starting code review for: ${directory}
`);
  
  for await (const message of query({
    prompt: `Review the code in ${directory} for:
1. Bugs and potential crashes
2. Security vulnerabilities
3. Performance issues
4. Code quality improvements

Be specific about file names and line numbers.`,
    options: {
      model: "opus",
      allowedTools: ["Read", "Glob", "Grep"],
      permissionMode: "bypassPermissions", // 自动批准读取操作
      maxTurns: 250
    }
  })) {
    // 实时显示 Claude 的分析过程
    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(`
📁 Using ${block.name}...`);
        }
      }
    }
    
    // 显示完成状态
    if (message.type === "result") {
      if (message.subtype === "success") {
        console.log(`
✅ Review complete! Cost: $${message.total_cost_usd.toFixed(4)}`);
      } else {
        console.log(`
❌ Review failed: ${message.subtype}`);
      }
    }
  }
}

// 审查当前目录
reviewCode(".");

测试代理

创建一个包含一些故意错误的测试文件 example.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function processUsers(users: any) {
  for (let i = 0; i <= users.length; i++) { // 边界错误
    console.log(users[i].name.toUpperCase()); // 没有空值检查
  }
}

function connectToDb(password: string) {
  const connectionString = `postgres://admin:${password}@localhost/db`;
  console.log("Connecting with:", connectionString); // 记录敏感数据
}

async function fetchData(url) { // 缺少类型注解
  const response = await fetch(url);
  return response.json(); // 没有错误处理
}

运行审查:

1
npx tsx review-agent.ts

Claude 会识别出这些 bug、安全问题,并提出修复建议。

结构化输出:获取可编程数据

对于需要程序化处理的场景,SDK 支持 JSON Schema 输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import { query } from "@anthropic-ai/claude-agent-sdk";

const reviewSchema = {
  type: "object",
  properties: {
    issues: {
      type: "array",
      items: {
        type: "object",
        properties: {
          severity: {
            type: "string",
            enum: ["low", "medium", "high", "critical"]
          },
          category: {
            type: "string",
            enum: ["bug", "security", "performance", "style"]
          },
          file: { type: "string" },
          line: { type: "number" },
          description: { type: "string" },
          suggestion: { type: "string" }
        },
        required: ["severity", "category", "file", "description"]
      }
    },
    summary: { type: "string" },
    overallScore: { type: "number" }
  },
  required: ["issues", "summary", "overallScore"]
};

async function reviewCodeStructured(directory: string) {
  for await (const message of query({
    prompt: `Review the code in ${directory}. Identify all issues.`,
    options: {
      model: "opus",
      allowedTools: ["Read", "Glob", "Grep"],
      permissionMode: "bypassPermissions",
      maxTurns: 250,
      outputFormat: {
        type: "json_schema",
        schema: reviewSchema
      }
    }
  })) {
    if (message.type === "result" && message.subtype === "success") {
      const review = message.structured_output as {
        issues: Array<{
          severity: string;
          category: string;
          file: string;
          line?: number;
          description: string;
          suggestion?: string;
        }>;
        summary: string;
        overallScore: number;
      };
      
      console.log(`
📊 Code Review Results
`);
      console.log(`Score: ${review.overallScore}/100`);
      console.log(`Summary: ${review.summary}
`);
      
      for (const issue of review.issues) {
        const icon = issue.severity === "critical" ? "🔴" :
                     issue.severity === "high" ? "🟠" :
                     issue.severity === "medium" ? "🟡" : "🟢";
        
        console.log(`${icon} [${issue.category.toUpperCase()}] ${issue.file}${issue.line ? `:${issue.line}` : ""}`);
        console.log(`  ${issue.description}`);
        if (issue.suggestion) {
          console.log(`  💡 ${issue.suggestion}`);
        }
        console.log();
      }
    }
  }
}

reviewCodeStructured(".");

有了结构化输出,你可以:

  • 将结果存入数据库

  • 生成报告和图表

  • 与其他系统集成

  • 实现自动化工作流

权限管理

默认情况下,SDK 在执行工具前会请求批准。你可以自定义这个行为:

权限模式

1
2
3
4
5
6
7
8
9
10
options: {
  // 标准模式 - 提示批准
  permissionMode: "default",
  
  // 自动批准文件编辑
  permissionMode: "acceptEdits",
  
  // 无提示(谨慎使用)
  permissionMode: "bypassPermissions"
}

自定义权限处理器

对于细粒度控制,使用 canUseTool

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
options: {
  canUseTool: async (toolName, input) => {
    // 允许所有读取操作
    if (["Read", "Glob", "Grep"].includes(toolName)) {
      return { behavior: "allow", updatedInput: input };
    }
    
    // 阻止写入特定文件
    if (toolName === "Write" && input.file_path?.includes(".env")) {
      return {
        behavior: "deny",
        message: "Cannot modify .env files"
      };
    }
    
    // 允许其他一切
    return { behavior: "allow", updatedInput: input };
  }
}

高级功能

子代理:专业分工

对于复杂任务,你可以创建专门的子代理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import { query, AgentDefinition } from "@anthropic-ai/claude-agent-sdk";

async function comprehensiveReview(directory: string) {
  for await (const message of query({
    prompt: `Perform a comprehensive code review of ${directory}.
Use the security-reviewer for security issues and test-analyzer for test coverage.`,
    options: {
      model: "opus",
      allowedTools: ["Read", "Glob", "Grep", "Task"],
      permissionMode: "bypassPermissions",
      maxTurns: 250,
      agents: {
        "security-reviewer": {
          description: "Security specialist for vulnerability detection",
          prompt: `You are a security expert. Focus on:
- SQL injection, XSS, CSRF vulnerabilities
- Exposed credentials and secrets
- Insecure data handling
- Authentication/authorization issues`,
          tools: ["Read", "Grep", "Glob"],
          model: "sonnet"
        } as AgentDefinition,
        
        "test-analyzer": {
          description: "Test coverage and quality analyzer",
          prompt: `You are a testing expert. Analyze:
- Test coverage gaps
- Missing edge cases
- Test quality and reliability
- Suggestions for additional tests`,
          tools: ["Read", "Grep", "Glob"],
          model: "haiku" // 对简单分析使用更快的模型
        } as AgentDefinition
      }
    }
  })) {
    if (message.type === "assistant") {
      for (const block of message.message.content) {
        if ("text" in block) {
          console.log(block.text);
        } else if ("name" in block && block.name === "Task") {
          console.log(`
🤖 Delegating to: ${(block.input as any).subagent_type}`);
        }
      }
    }
  }
}

会话管理:多轮对话

捕获并恢复会话以实现连续对话:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
async function interactiveReview() {
  let sessionId: string | undefined;
  
  // 初始审查
  for await (const message of query({
    prompt: "Review this codebase and identify the top 3 issues",
    options: {
      model: "opus",
      allowedTools: ["Read", "Glob", "Grep"],
      permissionMode: "bypassPermissions",
      maxTurns: 250
    }
  })) {
    if (message.type === "system" && message.subtype === "init") {
      sessionId = message.session_id;
    }
    // ... 处理消息
  }
  
  // 使用相同会话进行后续问题
  if (sessionId) {
    for await (const message of query({
      prompt: "Now show me how to fix the most critical issue",
      options: {
        resume: sessionId, // 继续对话
        allowedTools: ["Read", "Glob", "Grep"],
        maxTurns: 250
      }
    })) {
      // Claude 会记住之前的上下文
    }
  }
}

Hooks:拦截和自定义行为

Hooks 让你能够拦截和自定义代理行为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import { query, HookCallback, PreToolUseHookInput } from "@anthropic-ai/claude-agent-sdk";

// 审计日志记录器
const auditLogger: HookCallback = async (input, toolUseId, { signal }) => {
  if (input.hook_event_name === "PreToolUse") {
    const preInput = input as PreToolUseHookInput;
    console.log(`[AUDIT] ${new Date().toISOString()} - ${preInput.tool_name}`);
  }
  return {};
};

// 阻止危险命令
const blockDangerousCommands: HookCallback = async (input, toolUseId, { signal }) => {
  if (input.hook_event_name === "PreToolUse") {
    const preInput = input as PreToolUseHookInput;
    if (preInput.tool_name === "Bash") {
      const command = (preInput.tool_input as any).command || "";
      if (command.includes("rm -rf") || command.includes("sudo")) {
        return {
          hookSpecificOutput: {
            hookEventName: "PreToolUse",
            permissionDecision: "deny",
            permissionDecisionReason: "Dangerous command blocked"
          }
        };
      }
    }
  }
  return {};
};

for await (const message of query({
  prompt: "Clean up temporary files",
  options: {
    model: "opus",
    allowedTools: ["Bash", "Glob"],
    maxTurns: 250,
    hooks: {
      PreToolUse: [
        { hooks: [auditLogger] },
        { matcher: "Bash", hooks: [blockDangerousCommands] }
      ]
    }
  }
})) {
  // ...
}

MCP 扩展:自定义工具

使用 Model Context Protocol 扩展 Claude 的能力:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import { query, tool, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
import { z } from "zod";

// 创建自定义工具
const customServer = createSdkMcpServer({
  name: "code-metrics",
  version: "1.0.0",
  tools: [
    tool(
      "analyze_complexity",
      "Calculate cyclomatic complexity for a file",
      {
        filePath: z.string().describe("Path to the file to analyze")
      },
      async (args) => {
        // 你的复杂度分析逻辑
        const complexity = Math.floor(Math.random() * 20) + 1;
        return {
          content: [{
            type: "text",
            text: `Cyclomatic complexity for ${args.filePath}: ${complexity}`
          }]
        };
      }
    )
  ]
});

// 在代理中使用
for await (const message of query({
  prompt: "Analyze the complexity of main.ts",
  options: {
    model: "opus",
    mcpServers: {
      "code-metrics": customServer
    },
    allowedTools: ["Read", "mcp__code-metrics__analyze_complexity"],
    maxTurns: 250
  }
})) {
  // ...
}

生产环境建议

成本追踪

1
2
3
4
5
6
7
8
9
10
11
for await (const message of query({ prompt: "..." })) {
  if (message.type === "result" && message.subtype === "success") {
    console.log("Total cost:", message.total_cost_usd);
    console.log("Token usage:", message.usage);
    
    // 每个模型的详细分析(在使用子代理时很有用)
    for (const [model, usage] of Object.entries(message.modelUsage)) {
      console.log(`${model}: $${usage.costUSD.toFixed(4)}`);
    }
  }
}

错误处理

1
2
3
4
5
6
7
8
9
10
try {
  for await (const message of query({ ... })) {
    if (message.type === "result" && message.subtype !== "success") {
      console.error("Agent failed:", message.subtype);
      // 处理特定错误类型
    }
  }
} catch (error) {
  console.error("Unexpected error:", error);
}

超时控制

1
2
3
4
options: {
  maxTurns: 250, // 限制最大迭代次数
  // 设置合理的超时时间
}

总结

Claude Agent SDK 让构建 AI 代理变得简单而强大。关键要点:

开箱即用的工具:不需要重新实现文件操作、命令执行等基础功能

自动化的代理循环:SDK 处理与模型的复杂交互,你只需关注业务逻辑

灵活的架构:从简单脚本到复杂的多代理系统都能轻松实现

生产就绪:内置权限管理、成本追踪、错误处理等企业级特性

现在你已经掌握了基础知识,可以开始构建自己的 AI 代理了。无论是代码审查、文档生成、数据分析还是自动化测试,Claude Agent SDK 都能帮你实现。

参考资源


本文基于 Nader Dabit 的原创教程整理而成,感谢他的精彩分享。


真诚邀请您走进我的知识小宇宙,关注我个人的公众号,在这里,我将不时为您献上独家原创且极具价值的技术内容分享。每一次推送,都倾注了我对技术领域的独特见解与实战心得,旨在与您共享成长过程中的每一份收获和感悟。您的关注和支持,是我持续提供优质内容的最大动力,让我们在学习的道路上并肩同行,共同进步,一起书写精彩的成长篇章!

This post is licensed under CC BY 4.0 by the author.

Claude Code 实战指南:从入门到精通

如何使用 Claude Code 开始每一个项目

Trending Tags