<!-- title: Claude Agent SDK：用TypeScript构建生产级AI Agent -->

## 概述

本教程聚焦 Anthropic 在 2025 年底发布、2026 年持续迭代的 **Claude Agent SDK**（原 Claude Code SDK），手把手教你用 TypeScript 从零构建一个具备自定义工具、生命周期钩子、MCP 集成和子 Agent 编排能力的生产级 AI Agent。学完即可将 Agent 嵌入 CI/CD 管道、批量任务系统或任何需要自主决策的自动化场景。

**适用人群**：有 TypeScript 基础、想超越 `claude -p` 命令行模式、在代码层面完全控制 Agent 行为的中高级开发者。

---

## 前置条件

| 项目 | 要求 |
|------|------|
| Node.js | >= 18.0 |
| TypeScript | >= 5.3（项目内安装即可） |
| Claude 账户 | Pro / Max / Team / Enterprise 均可 |
| API Key | `ANTHROPIC_API_KEY` 环境变量 |
| 基础知识 | 熟悉 async/await、事件流、npm 包管理 |

### 环境准备

```bash
# 创建项目目录
mkdir my-claude-agent && cd my-claude-agent

# 初始化 TypeScript 项目
npm init -y
npm install typescript @types/node --save-dev
npx tsc --init

# 安装 Claude Agent SDK
npm install @anthropic-ai/claude-agent-sdk

# 设置 API Key（写入 .bashrc 或 .zshrc 持久化）
export ANTHROPIC_API_KEY="sk-ant-xxxxx"
```

---

## 一、理解 Agent SDK 架构

Claude Agent SDK 不是对 `/v1/messages` API 的简单封装。它直接暴露了 Claude Code 内部使用的 **Agent Loop**——包括工具调用、上下文管理、流式输出、权限控制等完整能力链。

```mermaid
graph TB
    subgraph "Your Application"
        A[Entry Point<br/>index.ts]
        A --> B[createSession]
    end

    subgraph "Agent SDK Core"
        B --> C[Agent Loop<br/>思考→决策→工具调用→观察]
        C --> D[Built-in Tools<br/>Read/Write/Bash/Glob/Grep]
        C --> E[Custom Tools<br/>你定义的工具]
        C --> F[MCP Servers<br/>外部工具协议]
        C --> G[Hooks<br/>PreToolUse/PostToolUse]
    end

    subgraph "Anthropic API"
        C -->|Messages API| H[Claude Model]
    end

    C -->|subscribe| I[Event Stream<br/>Message/ToolCall/Result]

    style B fill:#7c3aed,color:#fff
    style C fill:#2563eb,color:#fff
    style E fill:#059669,color:#fff
    style G fill:#dc2626,color:#fff
```

### 核心概念速览

| 概念 | 说明 |
|------|------|
| **Session** | 一次 Agent 运行实例，包含上下文、工具集和配置 |
| **Agent Loop** | 模型自动循环执行：思考 → 调用工具 → 观察结果 → 继续思考 |
| **Custom Tools** | 你定义的 TypeScript 函数，Agent 可自主决定调用 |
| **Hooks** | 生命周期回调，在工具调用前后拦截、校验、记录 |
| **Subagents** | 从主 Agent 派生的子 Agent，可并行执行独立任务 |
| **MCP Integration** | 通过 Model Context Protocol 连接外部服务 |

---

## 二、第一个 Agent：30 秒跑起来

创建 `src/01-hello.ts`：

```typescript
import { createSession } from "@anthropic-ai/claude-agent-sdk";

async function main() {
  const session = createSession({
    model: "claude-sonnet-4-6",
    workingDirectory: process.cwd(),
    systemPrompt: "你是一个代码分析助手，用中文回答问题。",
  });

  const result = await session.run("请分析当前目录结构，告诉我这是什么项目");

  console.log("=== Agent 回复 ===");
  console.log(result.finalMessage);
}

main().catch(console.error);
```

运行：

```bash
npx tsx src/01-hello.ts
```

**预期输出**：Agent 会自主调用 `Glob` 工具扫描目录，调用 `Read` 工具读取 `package.json`，然后返回项目分析结果。

### 事件流模式：实时追踪 Agent 行为

上面的 `session.run()` 是简化写法。生产环境中你需要订阅事件流，实时了解 Agent 在做什么：

```typescript
import { createSession } from "@anthropic-ai/claude-agent-sdk";

async function main() {
  const session = createSession({
    model: "claude-sonnet-4-6",
    workingDirectory: process.cwd(),
  });

  // 订阅事件流
  session.subscribe((event) => {
    switch (event.type) {
      case "assistant_message":
        // Agent 的文本输出
        process.stdout.write(event.content);
        break;
      case "tool_call":
        console.log(`\n🔧 调用工具: ${event.toolName}`);
        console.log(`   参数: ${JSON.stringify(event.input).slice(0, 200)}`);
        break;
      case "tool_result":
        console.log(`   结果: ${String(event.output).slice(0, 100)}...`);
        break;
      case "error":
        console.error(`\n❌ 错误: ${event.message}`);
        break;
    }
  });

  await session.run("统计 src 目录下所有 .ts 文件的代码行数");
}

main().catch(console.error);
```

**常见问题**：

| 问题 | 原因 | 解决方案 |
|------|------|----------|
| `ANTHROPIC_API_KEY not set` | 环境变量未配置 | `export ANTHROPIC_API_KEY=sk-ant-...` |
| `Model not found` | 模型名称错误 | 确认使用 `claude-sonnet-4-6` 或 `claude-opus-4-6` |
| `ECONNREFUSED` | 网络代理问题 | 设置 `HTTPS_PROXY` 或检查防火墙 |
| 超时 | 复杂任务轮次过多 | 设置 `maxTurns` 限制 |

---

## 三、自定义工具：让 Agent 拥有你的能力

Agent 的强大来自于**工具**。内置工具让 Agent 能读写文件、执行命令，但自定义工具让 Agent 能操作你的业务系统。

### 3.1 定义工具的基本模式

```typescript
import { createSession, tool } from "@anthropic-ai/claude-agent-sdk";
import { z } from "zod";

// 定义工具 schema
const SearchDatabaseSchema = z.object({
  query: z.string().describe("SQL 查询语句"),
  database: z.string().default("main").describe("数据库名称"),
});

// 创建会话并注册工具
const session = createSession({
  model: "claude-sonnet-4-6",
  workingDirectory: process.cwd(),
  tools: [
    {
      name: "search_database",
      description: "查询业务数据库，执行 SQL 并返回结果。仅支持 SELECT 语句。",
      inputSchema: SearchDatabaseSchema,
      execute: async (input) => {
        // 安全检查：只允许 SELECT
        if (!input.query.trim().toUpperCase().startsWith("SELECT")) {
          return { error: "只允许 SELECT 查询" };
        }

        // 模拟数据库查询
        console.log(`[DB] 执行查询: ${input.query}`);
        const mockResults = [
          { id: 1, name: "产品A", sales: 15000 },
          { id: 2, name: "产品B", sales: 28000 },
          { id: 3, name: "产品C", sales: 9500 },
        ];
        return { rows: mockResults, rowCount: mockResults.length };
      },
    },
    {
      name: "send_notification",
      description: "向团队发送通知消息，用于报告异常或关键指标",
      inputSchema: z.object({
        channel: z.enum(["slack", "email", "webhook"]).describe("通知渠道"),
        message: z.string().describe("通知内容"),
        priority: z.enum(["low", "medium", "high"]).default("medium"),
      }),
      execute: async (input) => {
        console.log(
          `[NOTIFY] ${input.priority.toUpperCase()} -> ${input.channel}: ${input.message}`
        );
        return { status: "sent", timestamp: new Date().toISOString() };
      },
    },
  ],
});
```

### 3.2 工具设计的五个原则

```mermaid
graph LR
    A[单一职责] --> B[描述精确]
    B --> C[Schema 严格]
    C --> D[安全边界]
    D --> E[幂等设计]

    style A fill:#10b981,color:#fff
    style B fill:#3b82f6,color:#fff
    style C fill:#8b5cf6,color:#fff
    style D fill:#ef4444,color:#fff
    style E fill:#f59e0b,color:#fff
```

**原则一：描述精确——描述即 Prompt**

工具的 `description` 是 Agent 决定是否调用该工具的关键依据。模糊描述 = 错误调用。

```typescript
// ❌ 糟糕的描述
{ description: "查询数据" }

// ✅ 精确的描述
{ description: "查询业务数据库中的销售数据。支持按日期范围、产品类别、地区筛选。仅返回聚合统计结果，不返回原始明细行。" }
```

**原则二：Schema 严格——用 Zod 约束输入**

```typescript
// ❌ 松散定义
inputSchema: z.object({ path: z.string() })

// ✅ 严格定义，带描述和约束
inputSchema: z.object({
  path: z.string()
    .min(1)
    .describe("目标文件或目录的绝对路径"),
  recursive: z.boolean()
    .default(false)
    .describe("是否递归处理子目录"),
  maxDepth: z.number()
    .min(1).max(10)
    .default(3)
    .describe("递归最大深度，1-10"),
})
```

**原则三：安全边界——永远不要信任模型输入**

```typescript
execute: async (input) => {
  // 白名单校验
  const ALLOWED_TABLES = ["products", "orders", "users"];
  const tableName = extractTableName(input.query);
  if (!ALLOWED_TABLES.includes(tableName)) {
    return { error: `表 ${tableName} 不在允许列表中` };
  }

  // 路径遍历防护
  const resolved = path.resolve(input.path);
  if (!resolved.startsWith(ALLOWED_BASE_DIR)) {
    return { error: "路径超出允许范围" };
  }

  // 执行实际操作...
}
```

**原则四：幂等设计——Agent 可能重复调用**

```typescript
// 使用幂等键确保重复调用安全
execute: async (input) => {
  const idempotencyKey = `${input.action}:${input.target}:${input checksum}`;
  if (await cache.has(idempotencyKey)) {
    return { status: "already_applied", skipped: true };
  }
  const result = await performAction(input);
  await cache.set(idempotencyKey, result);
  return result;
}
```

**原则五：返回结构化数据**

```typescript
// ❌ 返回纯文本
return "找到 3 个文件，总共 500 行";

// ✅ 返回结构化数据，Agent 可以进一步处理
return {
  files: [
    { path: "src/index.ts", lines: 120, functions: 5 },
    { path: "src/utils.ts", lines: 230, functions: 12 },
    { path: "src/config.ts", lines: 150, functions: 4 },
  ],
  summary: { totalFiles: 3, totalLines: 500, totalFunctions: 21 },
};
```

---

## 四、生命周期钩子：精细控制 Agent 行为

Hooks 是 Agent SDK 的核心治理机制。你可以在不修改工具代码的前提下，拦截、记录、审批甚至阻止 Agent 的操作。

### 4.1 四类钩子

```typescript
import { createSession, HookPoint } from "@anthropic-ai/claude-agent-sdk";

const session = createSession({
  model: "claude-sonnet-4-6",
  workingDirectory: process.cwd(),

  hooks: {
    // 1. 工具调用前——审批与拦截
    onPreToolUse: async (context) => {
      const { toolName, input } = context;

      // 阻止危险操作
      if (toolName === "Bash" && typeof input.command === "string") {
        const dangerous = ["rm -rf", "DROP TABLE", "format", ":(){:|:&};:"];
        if (dangerous.some((d) => input.command.includes(d))) {
          return {
            decision: "block" as const,
            reason: `阻止危险命令: ${input.command}`,
          };
        }
      }

      // 保护敏感文件
      if (toolName === "Write" || toolName === "Edit") {
        const sensitive = [".env", "credentials", "secret", "private_key"];
        if (
          typeof input.file_path === "string" &&
          sensitive.some((s) => input.file_path.includes(s))
        ) {
          return {
            decision: "block" as const,
            reason: `禁止修改敏感文件: ${input.file_path}`,
          };
        }
      }

      // 记录审计日志
      auditLog.record({
        timestamp: new Date(),
        tool: toolName,
        input: JSON.stringify(input).slice(0, 500),
        decision: "allow",
      });

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

    // 2. 工具调用后——结果处理
    onPostToolUse: async (context) => {
      const { toolName, input, output } = context;

      // 自动格式化修改过的文件
      if (toolName === "Write" && input.file_path?.endsWith(".ts")) {
        // 可触发 prettier/eslint
        console.log(`[POST] ${input.file_path} 已修改，建议运行 lint`);
      }

      // 敏感输出脱敏
      if (toolName === "Read" && typeof output === "string") {
        const sanitized = output.replace(
          /password["\s:=]+["']?[^"'\s,}]+/gi,
          'password: "***REDACTED***"'
        );
        return { modifiedOutput: sanitized };
      }
    },

    // 3. 通知——Agent 状态变化
    onNotification: async (notification) => {
      console.log(`[NOTIFY] ${notification.type}: ${notification.message}`);
      // 可发送到监控系统
      metrics.increment(`agent.notification.${notification.type}`);
    },

    // 4. 会话开始/结束
    onSessionStart: async () => {
      console.log("[SESSION] Agent 会话开始");
      await loadProjectContext();
    },
    onSessionEnd: async (summary) => {
      console.log(
        `[SESSION] 会话结束，共 ${summary.toolCallCount} 次工具调用，${summary.tokenUsage} tokens`
      );
      await reportUsage(summary);
    },
  },
});
```

### 4.2 钩子执行流程

```mermaid
sequenceDiagram
    participant U as 用户代码
    participant SDK as Agent SDK
    participant H as Hook 系统
    participant T as 工具执行器

    U->>SDK: session.run(prompt)
    SDK->>SDK: Agent 思考：决定调用工具X

    rect rgb(254, 243, 199)
        Note over SDK,H: PreToolUse 钩子链
        SDK->>H: onPreToolUse(toolX, input)
        H-->>SDK: decision: allow / block
    end

    alt decision = block
        SDK-->>SDK: 跳过执行，返回拒绝原因
    else decision = allow
        SDK->>T: execute(toolX, input)
        T-->>SDK: output

        rect rgb(220, 252, 231)
            Note over SDK,H: PostToolUse 钩子链
            SDK->>H: onPostToolUse(toolX, input, output)
            H-->>SDK: modifiedOutput（可选）
        end

        SDK->>SDK: Agent 继续思考...
    end

    SDK-->>U: 最终结果
```

---

## 五、MCP 集成：连接外部工具生态

Agent SDK 通过 Model Context Protocol（MCP）连接第三方服务，无需自己实现每个工具的通信协议。

### 5.1 连接 MCP Server

```typescript
import { createSession } from "@anthropic-ai/claude-agent-sdk";

const session = createSession({
  model: "claude-sonnet-4-6",
  workingDirectory: process.cwd(),

  mcpServers: {
    // 方式一：本地进程（stdio 传输）
    github: {
      transport: "stdio",
      command: "npx",
      args: ["-y", "@modelcontextprotocol/server-github"],
      env: {
        GITHUB_PERSONAL_ACCESS_TOKEN: process.env.GITHUB_TOKEN!,
      },
    },

    // 方式二：HTTP 传输
    database: {
      transport: "http",
      url: "http://localhost:3001/mcp",
      headers: {
        Authorization: `Bearer ${process.env.DB_API_KEY}`,
      },
    },

    // 方式三：内联 MCP Server（直接在代码中定义）
    customAnalytics: {
      transport: "inline",
      tools: [
        {
          name: "get_analytics",
          description: "获取网站分析数据",
          inputSchema: {
            type: "object",
            properties: {
              metric: {
                type: "string",
                enum: ["pageviews", "unique_visitors", "bounce_rate"],
              },
              dateRange: { type: "string", description: "如: 7d, 30d, 90d" },
            },
            required: ["metric"],
          },
          handler: async (input: any) => {
            // 直接调用你的分析 API
            const resp = await fetch(
              `https://analytics.example.com/api/${input.metric}?range=${input.dateRange || "7d"}`
            );
            return resp.json();
          },
        },
      ],
    },
  },
});

// Agent 现在可以自主使用 GitHub、数据库、分析工具
const result = await session.run(
  "查看 myorg/myrepo 最近 7 天的 PR，分析合并率，然后查询对应时间段的产品页面访问量变化"
);
```

### 5.2 MCP 连接模式对比

```mermaid
graph TB
    subgraph "Agent Session"
        A[Agent Loop]
    end

    subgraph "stdio 模式"
        B1[子进程] --> B2[MCP Server<br/>如 GitHub/文件系统]
    end

    subgraph "HTTP 模式"
        C1[HTTP Client] --> C2[远程 MCP Server<br/>如数据库/API 网关]
    end

    subgraph "inline 模式"
        D1[进程内函数调用] --> D2[自定义工具<br/>无需额外进程]
    end

    A -->|stdin/stdout| B1
    A -->|HTTP POST| C1
    A -->|直接调用| D1

    style B2 fill:#3b82f6,color:#fff
    style C2 fill:#8b5cf6,color:#fff
    style D2 fill:#10b981,color:#fff
```

| 模式 | 适用场景 | 启动开销 | 调试难度 |
|------|----------|----------|----------|
| stdio | 本地工具（文件、Git） | 需启动子进程 | 中等 |
| HTTP | 远程服务（数据库、API） | 无（直连） | 低 |
| inline | 自定义逻辑、快速原型 | 零 | 最低 |

---

## 六、子 Agent 编排：并行处理复杂任务

当单个 Agent 难以高效处理复杂任务时，子 Agent（Subagent）模式允许你派生多个专注的 Agent 并行工作。

### 6.1 定义和调用子 Agent

```typescript
import { createSession, subagent } from "@anthropic-ai/claude-agent-sdk";

// 定义子 Agent 配置
const codeReviewer = subagent({
  name: "code-reviewer",
  description: "专注代码质量审查，检查安全漏洞、性能问题和代码风格",
  systemPrompt: `你是一个严格的代码审查员。检查以下内容：
1. 安全漏洞（SQL 注入、XSS、路径遍历）
2. 性能问题（N+1 查询、内存泄漏、不必要的同步操作）
3. 代码风格（命名规范、函数长度、注释质量）
输出格式：按严重程度分级（Critical/Warning/Info）的审查报告。`,
  allowedTools: ["Read", "Glob", "Grep"], // 只给读权限
  maxTurns: 10,
});

const testWriter = subagent({
  name: "test-writer",
  description: "根据代码自动生成单元测试和集成测试",
  systemPrompt: `你是一个测试工程师。为给定代码编写：
1. 单元测试覆盖正常路径和边界条件
2. 使用项目现有的测试框架
3. Mock 外部依赖
4. 确保测试可独立运行`,
  allowedTools: ["Read", "Write", "Glob", "Grep", "Bash"],
  maxTurns: 15,
});

const docWriter = subagent({
  name: "doc-writer",
  description: "根据代码生成 API 文档和使用说明",
  systemPrompt: "根据代码生成 Markdown 格式的 API 文档，包含参数说明、返回值、使用示例。",
  allowedTools: ["Read", "Write", "Glob"],
  maxTurns: 8,
});

// 主 Agent 会话
const session = createSession({
  model: "claude-sonnet-4-6",
  workingDirectory: process.cwd(),
  subagents: [codeReviewer, testWriter, docWriter],
});
```

### 6.2 并行编排实战

```typescript
// 主 Agent 接收到任务后，会自动决定何时调用子 Agent
// 也可以通过 prompt 显式引导并行执行
const result = await session.run(`
请对 src/api/ 目录下的所有接口文件执行以下任务（并行）：
1. 用 code-reviewer 审查代码质量
2. 用 test-writer 为每个接口编写测试
3. 用 doc-writer 生成 API 文档

最后汇总三方面结果，给出综合评分和改进建议。
`);

console.log(result.finalMessage);
```

### 6.3 编排模式对比

```mermaid
graph TB
    subgraph "模式一：串行子 Agent"
        S1[主 Agent] --> SA1[子 Agent A]
        SA1 --> SA2[子 Agent B]
        SA2 --> SA3[子 Agent C]
        SA3 --> S1
    end

    subgraph "模式二：并行子 Agent"
        P1[主 Agent] --> PA1[子 Agent A]
        P1 --> PA2[子 Agent B]
        P1 --> PA3[子 Agent C]
        PA1 --> P1
        PA2 --> P1
        PA3 --> P1
    end

    subgraph "模式三：嵌套子 Agent"
        N1[主 Agent] --> NA1[编排 Agent]
        NA1 --> NB1[子 Agent 1]
        NA1 --> NB2[子 Agent 2]
        NB1 --> NA1
        NB2 --> NA1
        NA1 --> N1
    end

    style S1 fill:#2563eb,color:#fff
    style P1 fill:#059669,color:#fff
    style N1 fill:#dc2626,color:#fff
```

| 模式 | 适用场景 | Token 消耗 | 延迟 |
|------|----------|-----------|------|
| 串行 | 后一步依赖前一步结果 | 最低 | 最高 |
| 并行 | 独立任务可同时执行 | 较高 | 最低 |
| 嵌套 | 复杂任务需要层次化分解 | 最高 | 中等 |

---

## 七、完整实战项目：智能代码质量巡检 Agent

将前面学到的所有能力整合为一个可部署的代码质量巡检系统。

### 7.1 项目结构

```
code-patrol/
├── src/
│   ├── index.ts          # 入口，CLI 参数解析
│   ├── agent.ts          # Agent 配置，工具和钩子
│   ├── tools/
│   │   ├── metrics.ts    # 代码度量工具
│   │   ├── git-tools.ts  # Git 操作工具
│   │   └── report.ts     # 报告生成工具
│   └── hooks/
│       ├── audit.ts      # 审计钩子
│       └── guard.ts      # 安全防护钩子
├── package.json
└── tsconfig.json
```

### 7.2 核心代码：agent.ts

```typescript
import { createSession, subagent } from "@anthropic-ai/claude-agent-sdk";
import { z } from "zod";

// ===== 自定义工具 =====
const codeMetricsTool = {
  name: "analyze_complexity",
  description:
    "分析指定目录下 TypeScript 文件的圈复杂度、函数行数、依赖深度。返回按复杂度排序的报告。",
  inputSchema: z.object({
    directory: z.string().describe("要分析的目录路径"),
    threshold: z.number().default(10).describe("复杂度告警阈值"),
  }),
  execute: async (input: { directory: string; threshold: number }) => {
    // 实际项目中可调用 sonarqube API 或自定义分析器
    const mockMetrics = [
      { file: `${input.directory}/auth.ts`, complexity: 18, functions: 6, lines: 340 },
      { file: `${input.directory}/api.ts`, complexity: 12, functions: 8, lines: 280 },
      { file: `${input.directory}/utils.ts`, complexity: 4, functions: 12, lines: 180 },
    ];

    const violations = mockMetrics.filter(
      (m) => m.complexity > input.threshold
    );

    return {
      totalFiles: mockMetrics.length,
      violations,
      summary: {
        avgComplexity:
          mockMetrics.reduce((s, m) => s + m.complexity, 0) / mockMetrics.length,
        maxComplexity: Math.max(...mockMetrics.map((m) => m.complexity)),
      },
    };
  },
};

const gitAnalysisTool = {
  name: "git_hotspots",
  description: "分析 Git 历史中的变更热点文件（被频繁修改的文件通常需要关注）",
  inputSchema: z.object({
    since: z.string().default("2 weeks ago").describe("时间范围"),
    topN: z.number().default(10).describe("返回排名前 N 的热点文件"),
  }),
  execute: async (input: { since: string; topN: number }) => {
    // 模拟 git log --format="%H" --name-only 分析
    return {
      hotspots: [
        { file: "src/api/auth.ts", changes: 23, authors: 4, risk: "high" },
        { file: "src/api/payments.ts", changes: 18, authors: 3, risk: "high" },
        { file: "src/utils/validator.ts", changes: 15, authors: 2, risk: "medium" },
      ],
      period: input.since,
    };
  },
};

// ===== 子 Agent 定义 =====
const securityScanner = subagent({
  name: "security-scanner",
  description: "扫描代码中的安全漏洞，包括 OWASP Top 10 风险",
  systemPrompt: `你是一个安全扫描专家。检查以下安全问题：
- SQL 注入、XSS、CSRF
- 硬编码密钥和凭证
- 不安全的反序列化
- 路径遍历漏洞
- 不安全的随机数生成
按 CVSS 评分标准给出严重程度。`,
  allowedTools: ["Read", "Glob", "Grep"],
  maxTurns: 12,
});

const archAnalyzer = subagent({
  name: "arch-analyzer",
  description: "分析项目架构模式、模块耦合度和循环依赖",
  systemPrompt: `你是一个架构分析专家。评估：
1. 模块划分是否合理
2. 是否存在循环依赖
3. 分层是否清晰（controller/service/dao）
4. 公共组件复用率
输出架构健康度评分（0-100）。`,
  allowedTools: ["Read", "Glob", "Grep"],
  maxTurns: 10,
});

// ===== 安全钩子 =====
const guardHook = {
  onPreToolUse: async (context: any) => {
    // 禁止写操作——巡检 Agent 只读不写
    const writeTools = ["Write", "Edit"];
    if (writeTools.includes(context.toolName)) {
      return {
        decision: "block" as const,
        reason: "巡检模式下禁止文件修改操作",
      };
    }
    return { decision: "allow" as const };
  },

  onSessionEnd: async (summary: any) => {
    console.log(`\n📊 巡检统计:`);
    console.log(`   工具调用: ${summary.toolCallCount} 次`);
    console.log(`   Token 消耗: ${summary.tokenUsage}`);
    console.log(`   执行时间: ${summary.duration}ms`);
  },
};

// ===== 创建 Agent =====
export function createPatrolAgent(targetDir: string) {
  return createSession({
    model: "claude-sonnet-4-6",
    workingDirectory: targetDir,
    systemPrompt: `你是代码质量巡检 Agent。你的任务是全面评估项目代码质量并生成结构化报告。

巡检流程：
1. 先用 analyze_complexity 获取复杂度概况
2. 用 git_hotspots 识别高频变更文件
3. 用 security-scanner 并行扫描安全漏洞
4. 用 arch-analyzer 并行分析架构健康度
5. 汇总所有结果，生成最终报告

报告格式：
- 总体评分（A/B/C/D）
- 各维度评分和详细发现
- 优先修复建议（按影响排序）`,

    tools: [codeMetricsTool, gitAnalysisTool],
    subagents: [securityScanner, archAnalyzer],
    hooks: guardHook,
    maxTurns: 30,
  });
}
```

### 7.3 入口文件：index.ts

```typescript
import { createPatrolAgent } from "./agent";

async function main() {
  const targetDir = process.argv[2] || process.cwd();

  console.log(`🔍 启动代码质量巡检: ${targetDir}\n`);

  const agent = createPatrolAgent(targetDir);

  // 订阅事件，实时展示进度
  agent.subscribe((event) => {
    switch (event.type) {
      case "tool_call":
        console.log(`  ⚙️  ${event.toolName}(${JSON.stringify(event.input).slice(0, 80)}...)`);
        break;
      case "subagent_start":
        console.log(`  🤖 启动子 Agent: ${event.subagentName}`);
        break;
      case "subagent_complete":
        console.log(`  ✅ 子 Agent 完成: ${event.subagentName}`);
        break;
    }
  });

  const result = await agent.run(
    `对 ${targetDir} 执行全面代码质量巡检，生成评估报告。`
  );

  // 输出最终报告
  console.log("\n" + "=".repeat(60));
  console.log(result.finalMessage);
  console.log("=".repeat(60));
}

main().catch((err) => {
  console.error("巡检失败:", err);
  process.exit(1);
});
```

### 7.4 运行与输出

```bash
# 巡检指定项目
npx tsx src/index.ts /path/to/your/project

# 预期输出示例：
# 🔍 启动代码质量巡检: /path/to/your/project
#
#   ⚙️  analyze_complexity({"directory":"src","threshold":10})...
#   ⚙️  git_hotspots({"since":"2 weeks ago","topN":10})...
#   🤖 启动子 Agent: security-scanner
#   🤖 启动子 Agent: arch-analyzer
#   ✅ 子 Agent 完成: security-scanner
#   ✅ 子 Agent 完成: arch-analyzer
#
# ============================================================
# 📋 代码质量巡检报告
#
# 总体评分: B+
#
# | 维度 | 评分 | 状态 |
# |------|------|------|
# | 复杂度 | 7/10 | ⚠️  auth.ts 超阈值 |
# | 安全性 | 8/10 | ✅  无高危漏洞 |
# | 架构 | 7.5/10 | ⚠️  api 层耦合较重 |
# | 变更热点 | 6/10 | ⚠️  auth.ts 变更过于频繁 |
# ...
```

---

## 八、Token 优化与成本控制

Agent SDK 的灵活性意味着 token 消耗可能快速累积。以下是生产环境中的关键优化策略。

### 8.1 限制工具权限

```typescript
// 只给 Agent 必要的工具，减少无意义的工具探索
const session = createSession({
  // ...
  allowedTools: ["Read", "Glob", "Grep"], // 移除 Bash、Write、Edit
  // 或者使用 deniedTools 排除特定工具
  deniedTools: ["Bash"], // 明确禁止
});
```

### 8.2 控制轮次

```typescript
const session = createSession({
  // ...
  maxTurns: 15, // 最多 15 轮工具调用循环
  // 每轮 = 一次模型调用 + 可能的工具调用
  // 建议：简单任务 5-10 轮，复杂任务 15-30 轮
});
```

### 8.3 压缩系统提示

```typescript
// ❌ 冗长的系统提示
systemPrompt: `你是一个专业的代码审查员，你的职责是审查代码质量。你需要检查以下所有方面：
1. 代码是否有安全漏洞
2. 代码是否有性能问题
...（500字）`

// ✅ 精简但精确的系统提示
systemPrompt: `代码审查员。检查：安全漏洞、性能问题、可维护性。
输出：JSON 格式 {severity, file, line, issue, fix}`
```

### 8.4 流式输出 + 早停

```typescript
agent.subscribe((event) => {
  if (event.type === "assistant_message") {
    // 检测到满意结果时提前终止
    if (event.content.includes("## 最终报告")) {
      // 可以选择停止后续不必要的工具调用
    }
  }
});
```

---

## 九、从开发到部署的完整流程

```mermaid
graph LR
    subgraph "开发阶段"
        A[npm install<br/>@anthropic-ai/claude-agent-sdk] --> B[定义工具<br/>和钩子]
        B --> C[配置子 Agent<br/>和 MCP]
        C --> D[本地测试<br/>tsx 运行]
    end

    subgraph "测试阶段"
        D --> E[单元测试<br/>mock Agent 响应]
        E --> F[集成测试<br/>真实 API 调用]
        F --> G[压力测试<br/>并发 + 长时间运行]
    end

    subgraph "部署阶段"
        G --> H[Docker 镜像]
        H --> I[CI/CD 集成]
        I --> J[定时任务 / Webhook 触发]
    end

    style A fill:#7c3aed,color:#fff
    style G fill:#059669,color:#fff
    style J fill:#2563eb,color:#fff
```

### Dockerfile 示例

```dockerfile
FROM node:20-slim

WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY dist/ ./dist/

# 安全：不硬编码 API Key
ENV ANTHROPIC_API_KEY=""
ENV NODE_ENV=production

CMD ["node", "dist/index.js"]
```

### GitHub Actions 集成

```yaml
name: Code Quality Patrol
on:
  schedule:
    - cron: "0 2 * * 1" # 每周一凌晨 2 点
  workflow_dispatch: # 手动触发

jobs:
  patrol:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: "20"

      - run: npm ci

      - name: Run Code Patrol Agent
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        run: npx tsx src/index.ts ${{ github.workspace }}

      - name: Upload Report
        uses: actions/upload-artifact@v4
        with:
          name: patrol-report
          path: patrol-report.md
```

---

## 十、常见问题与故障排除

| 问题 | 症状 | 解决方案 |
|------|------|----------|
| Agent 无限循环 | 同一工具反复调用 | 设置 `maxTurns`，在钩子中检测重复模式 |
| Token 消耗过高 | 单次运行 > 100K tokens | 缩小工具范围，精简系统提示，使用子 Agent 隔离上下文 |
| 子 Agent 超时 | 长时间无响应 | 为子 Agent 设置更短的 `maxTurns`，添加超时机制 |
| MCP 连接失败 | `ECONNREFUSED` 或超时 | 检查 MCP Server 是否运行，网络是否可达 |
| 工具 Schema 错误 | Agent 无法正确传参 | 检查 Zod schema 是否与 `execute` 参数类型匹配 |
| 内存泄漏 | 长时间运行后 OOM | 确保关闭完成的 session，避免在全局累积事件 |

---

## 延伸阅读

- [Agent SDK 官方文档](https://code.claude.com/docs/en/agent-sdk/overview) — Anthropic 官方 Agent SDK 概览和 API 参考
- [Claude Agent SDK TypeScript GitHub](https://github.com/anthropics/claude-agent-sdk-typescript) — 源码、示例和更新日志
- [Agent SDK Quickstart](https://code.claude.com/docs/en/agent-sdk/quickstart) — Python 和 TypeScript 快速入门
- [Subagents in the SDK](https://code.claude.com/docs/en/agent-sdk/subagents) — 子 Agent 定义和编排
- [Connect to external tools with MCP](https://code.claude.com/docs/en/agent-sdk/mcp) — MCP 集成指南

---

## 参考来源

1. [Agent SDK overview - Claude Code Docs](https://code.claude.com/docs/en/agent-sdk/overview) — Anthropic 官方 Agent SDK 架构说明和核心概念
2. [GitHub - anthropics/claude-agent-sdk-typescript](https://github.com/anthropics/claude-agent-sdk-typescript) — TypeScript SDK 源码仓库，含安装指南和 API 参考
3. [Subagents in the SDK - Claude Code Docs](https://code.claude.com/docs/en/agent-sdk/subagents) — 子 Agent 定义、并行执行和编排模式官方文档
4. [Connect to external tools with MCP - Claude Code Docs](https://code.claude.com/docs/en/agent-sdk/mcp) — MCP Server 集成三种传输模式说明
5. [Controlling Claude Agent Execution With Hooks](https://team400.ai/blog/2026-03-claude-agent-sdk-hooks-guide) — 钩子系统的实践模式和配置示例

---

## 训练营适用性评估

| 维度 | 评估 |
|------|------|
| **适合训练营类型** | AI Agent 开发营、DevOps 自动化营、企业代码治理营 |
| **预计教学时长** | 4-6 小时（含动手实验） |
| **学员基础要求** | TypeScript 中级、了解 async/await 和事件驱动 |
| **实验环境需求** | Node.js 18+、Anthropic API Key、Git |
| **难度评级** | ⭐⭐⭐⭐（中高级） |
| **可拆分模块** | 基础 Agent（1h）→ 自定义工具（1.5h）→ Hooks + MCP（1.5h）→ 子 Agent + 实战（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学通信知识星球海报-扫码加入](https://wiki.500nian.com/images/zhixingqiu_qrcode.png)
