首页 › tutorials › Agent SDK实战:编程式AI代理开发

Agent SDK实战:编程式AI代理开发

概述

Claude Agent SDK 是 Anthropic 官方提供的编程式 AI 代理开发框架,它将 Claude Code 的完整能力——文件读写、命令执行、代码编辑、MCP 工具调用——封装为 TypeScript 和 Python SDK。本教程面向有一定编程基础的开发者,从零构建一个具备自定义工具、子代理编排和 Hook 拦截能力的生产级 AI 代理。学完可独立开发代码审查机器人、自动化运维代理、文档生成流水线等实际项目。

适用人群:有 TypeScript/Python 基础的后端开发者、DevOps 工程师、AI 应用开发者。

前置条件

项目 要求
Node.js v18+
TypeScript v5+
Anthropic API Key 需要有效的 API 密钥
Claude Code 已安装并配置(推荐最新版)
基础知识 异步编程、JSON Schema、命令行操作
graph TD
    A[Agent SDK 核心架构] --> B[Agent Loop 代理循环]
    A --> C[Tool System 工具系统]
    A --> D[Hook System 钩子系统]
    A --> E[Subagent 子代理]

    B --> B1[消息发送]
    B --> B2[工具调用决策]
    B --> B3[结果处理]
    B --> B4[循环终止判断]

    C --> C1[内置工具: Read/Write/Bash]
    C --> C2[自定义工具: MCP In-Process]
    C --> C3[外部MCP服务器]

    D --> D1[PreToolUse: 工具调用前]
    D --> D2[PostToolUse: 工具调用后]
    D --> D3[Notification: 通知]

    E --> E1[Task Dispatch]
    E --> E2[Parallel Execution]
    E --> E3[Result Aggregation]

第一步:安装与初始化

1.1 创建项目

mkdir my-claude-agent && cd my-claude-agent
npm init -y
npm install @anthropic-ai/claude-agent-sdk
npm install -D typescript @types/node tsx
npx tsc --init

tsconfig.json 关键配置:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "outDir": "./dist",
    "strict": true,
    "esModuleInterop": true
  }
}

1.2 配置 API 密钥

export ANTHROPIC_API_KEY="sk-ant-xxxxx"

或在项目根目录创建 .env 文件(不要提交到版本控制):

ANTHROPIC_API_KEY=sk-ant-xxxxx

1.3 验证安装

// verify.ts
import { query } from "@anthropic-ai/claude-agent-sdk";

const result = await query({
  prompt: "回复'Agent SDK 连接成功',不要执行其他操作",
});

console.log(result);

运行:

npx tsx verify.ts

预期输出:终端打印 Agent 的文本回复,包含"Agent SDK 连接成功"。

常见问题:

错误 原因 解决方案
MODULE_NOT_FOUND SDK 未安装或路径错误 检查 node_modules 中是否存在包
401 Unauthorized API Key 无效 确认密钥正确且未过期
ECONNREFUSED 网络问题 检查代理设置或防火墙

第二步:核心 API 详解

2.1 query() —— 单次代理调用

query() 是 Agent SDK 的核心入口函数,它启动一个完整的代理循环:

import { query } from "@anthropic-ai/claude-agent-sdk";

const result = await query({
  prompt: "读取当前目录的 package.json,列出所有依赖项",
  options: {
    model: "claude-sonnet-4-20250514",
    maxTurns: 10,
    allowedTools: ["Read", "Bash"],
    cwd: process.cwd(),
  },
});

关键参数:

参数 类型 说明
prompt string 给代理的指令
options.model string 模型选择,默认 claude-sonnet-4-20250514
options.maxTurns number 最大代理循环轮次,防止无限循环
options.allowedTools string[] 白名单工具,未列出的工具不可用
options.cwd string 工作目录,影响文件操作和命令执行的根路径
options.systemPrompt string 自定义系统提示词
options.outputFormat "text" \| "json" 输出格式

2.2 处理流式响应

对于长时间运行的任务,使用 stream 模式实时获取输出:

import { query } from "@anthropic-ai/claude-agent-sdk";

const stream = query({
  prompt: "分析 src/ 目录下所有 TypeScript 文件的代码质量",
  options: {
    outputFormat: "stream-json",
    allowedTools: ["Read", "Glob", "Grep"],
  },
});

for await (const event of stream) {
  switch (event.type) {
    case "assistant_message":
      process.stdout.write(event.content);
      break;
    case "tool_use":
      console.log(`\n[工具调用] ${event.toolName}: ${JSON.stringify(event.input)}`);
      break;
    case "tool_result":
      console.log(`[工具结果] 长度: ${event.output.length} 字符`);
      break;
    case "result":
      console.log("\n--- 代理执行完成 ---");
      console.log(`总轮次: ${event.totalTurns}`);
      console.log(`总Token: ${event.totalTokenUsage}`);
      break;
  }
}
sequenceDiagram
    participant Dev as 开发者代码
    participant SDK as Agent SDK
    participant Claude as Claude API
    participant Tools as 工具层

    Dev->>SDK: query(prompt, options)
    SDK->>Claude: 发送消息 + 工具定义
    Claude->>SDK: 返回响应(含工具调用)

    loop Agent Loop
        SDK->>Tools: 执行工具调用
        Tools->>SDK: 返回工具结果
        SDK->>Claude: 发送工具结果
        Claude->>SDK: 继续响应或完成
    end

    SDK->>Dev: 返回最终结果 / 流式事件

2.3 内置工具清单

Agent SDK 继承了 Claude Code 的全部内置工具能力:

工具名 能力 典型用途
Read 读取文件内容 代码审查、配置检查
Write 写入/创建文件 代码生成、文档输出
Edit 精确编辑文件片段 代码修改、重构
Bash 执行Shell命令 构建、测试、部署
Glob 文件名模式匹配 项目结构扫描
Grep 内容搜索 依赖追踪、模式查找
WebSearch 网络搜索 资料查询
WebFetch 抓取网页内容 文档获取

第三步:自定义工具开发

这是 Agent SDK 最强大的能力——为 Claude 添加你自己的业务工具。

3.1 基础工具定义

// tools/database-query.ts
import { defineTool } from "@anthropic-ai/claude-agent-sdk";

export const databaseQueryTool = defineTool({
  name: "database_query",
  description: "查询 PostgreSQL 数据库,执行只读 SQL 查询。仅支持 SELECT 语句。",
  inputSchema: {
    type: "object" as const,
    properties: {
      sql: {
        type: "string",
        description: "要执行的 SQL SELECT 查询语句",
      },
      database: {
        type: "string",
        description: "数据库名称,默认为 'main'",
        enum: ["main", "analytics", "logs"],
      },
      limit: {
        type: "number",
        description: "返回结果的最大行数,默认 100",
      },
    },
    required: ["sql"],
  },
  handler: async (input) => {
    // 安全校验:只允许 SELECT
    const normalizedSql = input.sql.trim().toUpperCase();
    if (!normalizedSql.startsWith("SELECT")) {
      return {
        isError: true,
        content: "安全限制:仅支持 SELECT 查询",
      };
    }

    const limit = input.limit ?? 100;
    const sqlWithLimit = normalizedSql.includes("LIMIT")
      ? input.sql
      : `${input.sql.replace(/;$/, "")} LIMIT ${limit}`;

    // 这里接入实际的数据库客户端
    const results = await executeQuery(input.database ?? "main", sqlWithLimit);

    return {
      content: JSON.stringify(results, null, 2),
    };
  },
});

3.2 带副作用的工具

// tools/slack-notify.ts
import { defineTool } from "@anthropic-ai/claude-agent-sdk";

export const slackNotifyTool = defineTool({
  name: "slack_notify",
  description: "向指定 Slack 频道发送通知消息。用于在关键操作完成后通知团队。",
  inputSchema: {
    type: "object" as const,
    properties: {
      channel: {
        type: "string",
        description: "Slack 频道名称,如 '#deployments'",
      },
      message: {
        type: "string",
        description: "要发送的消息内容",
      },
      severity: {
        type: "string",
        description: "消息严重级别",
        enum: ["info", "warning", "critical"],
      },
    },
    required: ["channel", "message"],
  },
  handler: async (input) => {
    const colorMap = { info: "#36a64f", warning: "#f2c744", critical: "#e01e5a" };

    const payload = {
      channel: input.channel,
      attachments: [{
        color: colorMap[input.severity ?? "info"],
        text: input.message,
        ts: Math.floor(Date.now() / 1000).toString(),
      }],
    };

    const response = await fetch(process.env.SLACK_WEBHOOK_URL!, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(payload),
    });

    return {
      content: response.ok
        ? `消息已发送到 ${input.channel}`
        : `发送失败: ${response.status} ${response.statusText}`,
    };
  },
});

3.3 组合工具到代理

// agent.ts
import { query } from "@anthropic-ai/claude-agent-sdk";
import { databaseQueryTool } from "./tools/database-query";
import { slackNotifyTool } from "./tools/slack-notify";

const result = await query({
  prompt: "检查过去 24 小时的错误日志数量,如果超过 100 条则通知 #ops 频道",
  options: {
    model: "claude-sonnet-4-20250514",
    maxTurns: 15,
    customTools: [databaseQueryTool, slackNotifyTool],
    allowedTools: ["Read", "Bash", "database_query", "slack_notify"],
    systemPrompt: "你是一个运维监控助手。先查询数据,再根据结果决定是否需要告警。",
  },
});

console.log(result);
flowchart LR
    subgraph 自定义工具层
        A[database_query<br/>SQL只读查询]
        B[slack_notify<br/>Slack消息推送]
        C[jira_create<br/>Jira工单创建]
        D[metric_fetch<br/>监控指标拉取]
    end

    subgraph Agent SDK 核心
        E[Agent Loop<br/>推理-决策-执行]
    end

    subgraph 内置工具层
        F[Read/Write/Edit]
        G[Bash]
        H[Glob/Grep]
    end

    I[用户 Prompt] --> E
    E --> A & B & C & D & F & G & H
    A & B & C & D & F & G & H --> E

    style A fill:#4a9eff,color:#fff
    style B fill:#e01e5a,color:#fff
    style C fill:#0052cc,color:#fff
    style D fill:#f4a261,color:#000

第四步:Hook 系统——拦截与增强

Hook 允许你在代理执行的关键节点注入自定义逻辑,实现审计、限流、安全校验等功能。

4.1 Pre-Tool-Use Hook:工具调用前拦截

// hooks/pre-tool-security.ts
import { Hook } from "@anthropic-ai/claude-agent-sdk";

export const securityHook: Hook = {
  name: "security-gate",
  events: ["PreToolUse"],
  handler: async (event) => {
    // 阻止对生产环境文件的写入
    if (event.toolName === "Write" || event.toolName === "Edit") {
      const filePath = event.input.file_path ?? "";
      const blockedPaths = [
        "/etc/",
        "/var/www/production/",
        "/opt/deploy/",
      ];

      if (blockedPaths.some((p) => filePath.startsWith(p))) {
        return {
          decision: "block" as const,
          reason: `安全策略禁止修改生产路径: ${filePath}`,
        };
      }
    }

    // 审计所有 Bash 命令
    if (event.toolName === "Bash") {
      const command = event.input.command ?? "";
      const dangerousPatterns = [
        /rm\s+-rf\s+\//,
        /DROP\s+TABLE/i,
        /DELETE\s+FROM/i,
        />\s*\/dev\//,
        /curl.*\|\s*sh/,
      ];

      for (const pattern of dangerousPatterns) {
        if (pattern.test(command)) {
          return {
            decision: "block" as const,
            reason: `危险命令被安全策略拦截: ${command.substring(0, 80)}...`,
          };
        }
      }

      // 记录审计日志
      await logAudit({
        tool: event.toolName,
        input: event.input,
        timestamp: new Date().toISOString(),
      });
    }

    return { decision: "allow" as const };
  },
};

4.2 Post-Tool-Use Hook:结果后处理

// hooks/post-tool-metrics.ts
import { Hook } from "@anthropic-ai/claude-agent-sdk";

export const metricsHook: Hook = {
  name: "execution-metrics",
  events: ["PostToolUse"],
  handler: async (event) => {
    const metrics = {
      tool: event.toolName,
      duration: event.duration,
      success: !event.isError,
      tokenCost: event.tokenUsage,
      timestamp: new Date().toISOString(),
    };

    // 推送到监控系统
    await pushToMetrics(metrics);

    // 如果执行失败超过阈值,自动告警
    if (event.isError) {
      console.error(`[工具失败] ${event.toolName}: ${event.error}`);
    }

    return { decision: "allow" as const };
  },
};

4.3 注册 Hook 到代理

import { query } from "@anthropic-ai/claude-agent-sdk";
import { securityHook } from "./hooks/pre-tool-security";
import { metricsHook } from "./hooks/post-tool-metrics";

const result = await query({
  prompt: "重构 src/utils/ 下的所有工具函数,添加 JSDoc 注释",
  options: {
    hooks: [securityHook, metricsHook],
    maxTurns: 30,
  },
});
flowchart TD
    A[Claude 决定调用工具] --> B{PreToolUse Hook}
    B -->|block| C[返回拒绝原因<br/>代理重新规划]
    B -->|allow| D[执行工具]
    D --> E{PostToolUse Hook}
    E -->|block| F[丢弃结果<br/>代理重新规划]
    E -->|allow| G[结果返回代理<br/>继续推理]

    H[代理启动] --> I{Notification Hook}
    I --> J[记录启动事件]

    style B fill:#ff6b6b,color:#fff
    style E fill:#4ecdc4,color:#fff
    style C fill:#ffe66d,color:#000
    style F fill:#ffe66d,color:#000

第五步:子代理编排——并行处理复杂任务

当单一代理处理不过来时,可以派生子代理并行工作。Agent SDK 提供了子代理调度能力。

5.1 并行文件处理

// multi-file-review.ts
import { query } from "@anthropic-ai/claude-agent-sdk";
import * as path from "path";
import * as fs from "fs/promises";

async function reviewFile(filePath: string) {
  return query({
    prompt: `审查以下文件的代码质量,关注:安全性、性能、可维护性。

文件路径: ${filePath}

请输出结构化的审查报告,包含问题列表和改进建议。`,
    options: {
      model: "claude-sonnet-4-20250514",
      maxTurns: 5,
      allowedTools: ["Read"],
      outputFormat: "json",
      systemPrompt: "你是一位高级代码审查工程师。输出 JSON 格式的审查报告。",
    },
  });
}

async function parallelReview(directory: string) {
  // 1. 扫描目标文件
  const files = await fs.readdir(directory, { recursive: true });
  const tsFiles = files
    .filter((f) => f.toString().endsWith(".ts"))
    .map((f) => path.join(directory, f.toString()));

  console.log(`发现 ${tsFiles.length} 个 TypeScript 文件`);

  // 2. 并行启动子代理(限制并发数)
  const CONCURRENCY = 5;
  const results: Map<string, any> = new Map();

  for (let i = 0; i < tsFiles.length; i += CONCURRENCY) {
    const batch = tsFiles.slice(i, i + CONCURRENCY);
    const batchResults = await Promise.all(
      batch.map(async (file) => {
        const result = await reviewFile(file);
        return { file, result };
      })
    );
    batchResults.forEach((r) => results.set(r.file, r.result));
    console.log(`已完成 ${Math.min(i + CONCURRENCY, tsFiles.length)}/${tsFiles.length}`);
  }

  // 3. 汇总报告
  return Object.fromEntries(results);
}

// 执行
const report = await parallelReview("./src");
console.log(JSON.stringify(report, null, 2));

5.2 管道式多阶段代理

// pipeline.ts — 代码迁移流水线
import { query } from "@anthropic-ai/claude-agent-sdk";

// 阶段1: 分析旧代码结构
const analysis = await query({
  prompt: "分析 src/ 目录的代码结构,识别所有需要从 JavaScript 迁移到 TypeScript 的文件",
  options: {
    allowedTools: ["Read", "Glob", "Grep"],
    maxTurns: 10,
    outputFormat: "json",
  },
});

// 阶段2: 生成迁移计划
const migrationPlan = await query({
  prompt: `基于以下分析结果,生成迁移计划。按依赖顺序排列文件。

分析结果:
${JSON.stringify(analysis)}

输出 JSON 数组,每个元素包含: file, priority, dependencies, estimated_complexity`,
  options: {
    maxTurns: 3,
    outputFormat: "json",
  },
});

// 阶段3: 逐文件执行迁移
const plan = JSON.parse(migrationPlan);
for (const item of plan) {
  console.log(`迁移: ${item.file} (优先级: ${item.priority})`);

  await query({
    prompt: `将 ${item.file} 从 JavaScript 迁移到 TypeScript。
要求:
1. 添加完整的类型注解
2. 修复所有类型错误
3. 保持原有功能不变
4. 添加必要的 interface 和 type 定义`,
    options: {
      allowedTools: ["Read", "Write", "Edit", "Bash"],
      maxTurns: 20,
      systemPrompt: "你是一个 TypeScript 迁移专家。严格保持功能等价。",
    },
  });
}

// 阶段4: 验证
const validation = await query({
  prompt: "运行 TypeScript 编译检查,确认所有文件无类型错误。如果有错误,修复它们。",
  options: {
    allowedTools: ["Bash", "Read", "Edit"],
    maxTurns: 15,
  },
});
flowchart TD
    A[主代理: 分析阶段] -->|JSON 输出| B[主代理: 规划阶段]
    B -->|迁移计划| C{文件列表}

    C --> D1[子代理: 迁移 file1.ts]
    C --> D2[子代理: 迁移 file2.ts]
    C --> D3[子代理: 迁移 file3.ts]
    C --> D4[子代理: 迁移 fileN.ts]

    D1 --> E[主代理: 验证阶段]
    D2 --> E
    D3 --> E
    D4 --> E

    E -->|编译检查| F{有错误?}
    F -->|是| G[子代理: 修复错误]
    G --> E
    F -->|否| H[迁移完成 ✓]

    style A fill:#6c5ce7,color:#fff
    style B fill:#0984e3,color:#fff
    style E fill:#00b894,color:#fff
    style H fill:#00b894,color:#fff

第六步:实战项目——自动化代码审查机器人

将以上所有知识整合为一个可运行的代码审查机器人。

6.1 项目结构

code-review-bot/
├── src/
│   ├── index.ts          # 入口文件
│   ├── tools/
│   │   ├── git-diff.ts   # Git 差异工具
│   │   └── comment.ts    # PR 评论工具
│   ├── hooks/
│   │   └── audit.ts      # 审计 Hook
│   └── prompts/
│       └── review.ts     # 审查提示词模板
├── package.json
└── tsconfig.json

6.2 自定义工具:获取 Git 差异

// src/tools/git-diff.ts
import { defineTool } from "@anthropic-ai/claude-agent-sdk";

export const gitDiffTool = defineTool({
  name: "git_diff",
  description: "获取 Git 仓库中指定提交范围的代码差异。用于代码审查。",
  inputSchema: {
    type: "object" as const,
    properties: {
      base: {
        type: "string",
        description: "基准分支或提交,默认为 'main'",
      },
      head: {
        type: "string",
        description: "目标分支或提交,默认为 'HEAD'",
      },
      stat: {
        type: "boolean",
        description: "是否只返回统计信息而非完整差异",
      },
    },
    required: [],
  },
  handler: async (input) => {
    const { execSync } = await import("child_process");

    const base = input.base ?? "main";
    const head = input.head ?? "HEAD";

    try {
      let command: string;
      if (input.stat) {
        command = `git diff --stat ${base}...${head}`;
      } else {
        command = `git diff ${base}...${head} --diff-filter=ACMR`;
      }

      const output = execSync(command, {
        maxBuffer: 10 * 1024 * 1024, // 10MB
        encoding: "utf-8",
      });

      return { content: output || "没有发现差异" };
    } catch (error: any) {
      return {
        isError: true,
        content: `Git 命令执行失败: ${error.message}`,
      };
    }
  },
});

6.3 自定义工具:发布审查评论

// src/tools/comment.ts
import { defineTool } from "@anthropic-ai/claude-agent-sdk";

interface ReviewComment {
  file: string;
  line: number;
  severity: "info" | "warning" | "critical";
  message: string;
  suggestion?: string;
}

export const postCommentTool = defineTool({
  name: "post_review_comment",
  description: "发布代码审查评论。支持对特定文件行添加审查意见。",
  inputSchema: {
    type: "object" as const,
    properties: {
      summary: {
        type: "string",
        description: "整体审查摘要",
      },
      comments: {
        type: "array",
        items: {
          type: "object",
          properties: {
            file: { type: "string" },
            line: { type: "number" },
            severity: { type: "string", enum: ["info", "warning", "critical"] },
            message: { type: "string" },
            suggestion: { type: "string" },
          },
          required: ["file", "line", "severity", "message"],
        },
        description: "具体审查评论列表",
      },
      approved: {
        type: "boolean",
        description: "是否批准此 PR",
      },
    },
    required: ["summary", "comments", "approved"],
  },
  handler: async (input) => {
    const { summary, comments, approved } = input;

    // 构建审查报告
    const emoji = { info: "ℹ️", warning: "⚠️", critical: "🔴" };
    let report = `## 代码审查报告\n\n`;
    report += `**结论**: ${approved ? "✅ 批准合并" : "❌ 需要修改"}\n\n`;
    report += `### 摘要\n${summary}\n\n`;
    report += `### 详细评论 (${comments.length} 条)\n\n`;

    for (const comment of comments as ReviewComment[]) {
      report += `${emoji[comment.severity]} **${comment.file}:${comment.line}**\n`;
      report += `> ${comment.message}\n`;
      if (comment.suggestion) {
        report += `建议: \`${comment.suggestion}\`\n`;
      }
      report += "\n";
    }

    // 如果配置了 GitHub,可以自动发布到 PR
    if (process.env.GITHUB_TOKEN && process.env.PR_NUMBER) {
      await postToGitHub(report);
    }

    // 同时输出到控制台
    console.log(report);

    return {
      content: `审查报告已生成。${comments.length} 条评论。结论: ${approved ? "批准" : "需修改"}。`,
    };
  },
});

async function postToGitHub(body: string) {
  const repo = process.env.GITHUB_REPOSITORY!;
  const prNumber = process.env.PR_NUMBER!;

  await fetch(`https://api.github.com/repos/${repo}/issues/${prNumber}/comments`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ body }),
  });
}

6.4 审查提示词模板

// src/prompts/review.ts
export function buildReviewPrompt(diffStat: string): string {
  return `你是一位资深代码审查工程师。请审查以下代码变更。

## 审查维度
1. **安全性**: SQL 注入、XSS、路径遍历、硬编码密钥
2. **性能**: N+1 查询、内存泄漏、不必要的循环
3. **可维护性**: 命名规范、函数复杂度、重复代码
4. **正确性**: 逻辑错误、边界条件、错误处理

## 变更统计
${diffStat}

## 审查流程
1. 使用 git_diff 工具获取完整差异(不带 stat 参数)
2. 逐文件分析变更内容
3. 使用 post_review_comment 工具发布审查结果

## 输出要求
- summary: 用中文写一段总体评价
- comments: 每个问题一条评论,必须包含文件名和行号
- approved: 只有 0 个 critical 问题时才批准`;
}

6.5 主入口

// src/index.ts
import { query } from "@anthropic-ai/claude-agent-sdk";
import { gitDiffTool } from "./tools/git-diff";
import { postCommentTool } from "./tools/comment";
import { securityHook } from "./hooks/audit";
import { buildReviewPrompt } from "./prompts/review";

async function main() {
  const targetBranch = process.env.TARGET_BRANCH ?? "main";
  const sourceBranch = process.env.SOURCE_BRANCH ?? "HEAD";

  // 获取差异统计(用 Bash 工具)
  const statResult = await query({
    prompt: `执行 git diff --stat ${targetBranch}...${sourceBranch},返回输出`,
    options: {
      allowedTools: ["Bash"],
      maxTurns: 2,
    },
  });

  // 启动审查代理
  const result = await query({
    prompt: buildReviewPrompt(statResult),
    options: {
      model: "claude-sonnet-4-20250514",
      maxTurns: 25,
      customTools: [gitDiffTool, postCommentTool],
      allowedTools: ["Read", "Grep", "git_diff", "post_review_comment"],
      hooks: [securityHook],
      systemPrompt: `你是一个代码审查机器人。
规则:
- 必须使用工具获取实际代码,不要猜测
- 每个问题必须有具体的文件名和行号
- 安全问题标记为 critical,性能标记为 warning,其他标记为 info
- 审查完毕后必须调用 post_review_comment 发布结果`,
    },
  });

  console.log("\n=== 审查代理执行完毕 ===");
  console.log(result);
}

main().catch(console.error);

6.6 运行方式

# 命令行运行
TARGET_BRANCH=main SOURCE_BRANCH=feature/login npx tsx src/index.ts

# CI/CD 中运行(GitHub Actions)
env:
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  GITHUB_REPOSITORY: ${{ github.repository }}
  PR_NUMBER: ${{ github.event.pull_request.number }}
  TARGET_BRANCH: main
  SOURCE_BRANCH: ${{ github.head_ref }}

第七步:进阶模式

7.1 会话持久化与恢复

import { query, saveSession, loadSession } from "@anthropic-ai/claude-agent-sdk";

// 第一次运行,保存会话
const result = await query({
  prompt: "开始分析项目架构",
  options: { sessionId: "arch-analysis-001" },
});

// 后续运行,恢复上下文
const continued = await query({
  prompt: "继续上次的架构分析,现在重点关注数据库层",
  options: { sessionId: "arch-analysis-001" },
});

7.2 与 claude -p 的协同

Agent SDK 和 claude -p 可以协同使用——CLI 用于快速脚本,SDK 用于复杂逻辑:

# CLI: 快速批量操作
for dir in packages/*/; do
  claude -p --output-format json \
    "检查 $dir 的 package.json 是否有过时的依赖" \
    --allowedTools "Read" \
    --max-turns 3
done

# SDK: 复杂的多步骤代理
npx tsx complex-agent.ts

7.3 成本控制策略

const result = await query({
  prompt: "简要总结这个文件的功能",
  options: {
    model: "claude-haiku-4-5-20251001", // 简单任务用 Haiku
    maxTurns: 3,                         // 限制轮次
    allowedTools: ["Read"],              // 最小工具集
  },
});

// 复杂任务才用 Sonnet
const complexResult = await query({
  prompt: "重构整个模块的架构",
  options: {
    model: "claude-sonnet-4-20250514",
    maxTurns: 30,
    allowedTools: ["Read", "Write", "Edit", "Bash", "Glob", "Grep"],
  },
});

常见陷阱与解决方案

问题 原因 解决方案
代理陷入无限循环 任务目标不明确,代理反复尝试 设置 maxTurns,优化 prompt
工具调用权限不足 allowedTools 未包含所需工具 检查白名单,添加缺失工具名
Token 消耗过大 大文件读取 + 多轮推理 用 Glob/Grep 精确定位,避免读取整个项目
自定义工具未生效 工具名不匹配或 Schema 错误 确保 defineTool 的 name 与 allowedTools 一致
Hook 阻塞了正常操作 Hook 规则过严 先在测试环境调试 Hook 逻辑
并行子代理 API 限流 并发请求超过速率限制 控制并发数(建议 3-5),加入重试逻辑
流式输出解析错误 事件类型判断不完整 使用 switch 语句覆盖所有事件类型

架构总览

graph TB
    subgraph 用户应用
        A[TypeScript 代码]
    end

    subgraph "Agent SDK 层"
        B[query 入口函数]
        C[Agent Loop<br/>推理→决策→执行]
        D[Hook Engine<br/>PreToolUse / PostToolUse]
    end

    subgraph "工具层"
        E[内置工具<br/>Read Write Edit Bash<br/>Glob Grep WebSearch]
        F[自定义工具<br/>defineTool 注册<br/>MCP In-Process Server]
        G[外部 MCP<br/>第三方服务集成]
    end

    subgraph "Claude API"
        H[消息发送/接收]
        I[工具调用解析]
        J[流式响应]
    end

    A --> B
    B --> C
    C --> D
    D --> E & F & G
    E & F & G --> D
    D --> C
    C <--> H
    H <--> I
    H <--> J

    style B fill:#6c5ce7,color:#fff
    style C fill:#0984e3,color:#fff
    style D fill:#fdcb6e,color:#000
    style F fill:#00b894,color:#fff

参考来源

  1. Agent SDK overview - Claude Code Docs — Agent SDK 官方概述与核心概念
  2. anthropics/claude-agent-sdk-typescript - GitHub — TypeScript SDK 源码与示例
  3. Give Claude custom tools - Claude Code Docs — 自定义工具定义文档
  4. Run Claude Code programmatically - Claude Code Docs — Headless 模式与编程式调用
  5. Build Production AI Agents with Claude Agent SDK and TypeScript — 生产级 Agent 构建教程

训练营适用性评估:本教程适合「AI 工程化训练营」和「DevOps 自动化训练营」,建议教学时长 4-5 小时(含上机实操)。学员需具备 TypeScript 基础和异步编程经验。建议分三个阶段教学:SDK 基础(1.5h)→ 自定义工具与 Hook(1.5h)→ 实战项目(1.5-2h)。

[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。

51学通信知识星球海报-扫码加入