<!-- title: Claude Code Agent SDK编程实战全攻略 -->

# Claude Code Agent SDK编程实战：从零构建自定义AI Agent

## 概述

本教程面向有一定TypeScript基础的开发者，深入讲解如何使用Claude Agent SDK（`@anthropic-ai/claude-code`）将Claude Code的核心能力——文件读写、Shell执行、代码搜索、子Agent编排——嵌入你自己的应用程序中。你将从一条`claude()`调用出发，逐步构建出带流式输出、工具白名单、多步推理的生产级AI Agent，并掌握Headless模式、管道脚本、与Hooks联动的完整自动化链路。

**适合人群**：已熟悉Claude Code基本操作、希望将其能力程序化嵌入CI/CD、内部工具或SaaS产品的中高级开发者。

**学习目标**：
- 理解Agent SDK的架构设计与核心API
- 用TypeScript编写自定义Agent，支持流式输出与工具权限控制
- 掌握Headless模式（`claude -p`）在脚本和CI中的应用
- 构建一个完整的"代码审查+自动修复"Agent实战项目

---

## 前置条件

| 条件 | 说明 |
|------|------|
| Node.js ≥ 18 | Agent SDK需要ESM支持 |
| TypeScript ≥ 5.0 | 推荐`strict`模式 |
| Claude Code ≥ v2.1.100 | 确保SDK与CLI版本兼容 |
| Claude订阅 | Pro/Max/Team均可，2026年6月15日后Agent SDK使用将有独立额度 |
| 基础Git知识 | Worktree、分支操作 |

```bash
# 验证环境
node --version    # v18+
npx tsc --version # 5.0+
claude --version  # 2.1.100+
```

---

## 第一章：Agent SDK架构与核心概念

### 1.1 Agent SDK是什么

Claude Agent SDK是Anthropic官方发布的TypeScript/Python库，它把Claude Code的整个Agent循环——提示解析、工具调用、上下文管理、多轮推理——封装为可编程的API。你不再需要手动拼接HTTP请求或管理对话状态，一个函数调用就能获得完整的Agent能力。

```
┌─────────────────────────────────────────────┐
│            你的应用程序                        │
│  ┌─────────────────────────────────────┐    │
│  │     @anthropic-ai/claude-code       │    │
│  │  ┌───────────────────────────────┐  │    │
│  │  │    Claude Agent Loop          │  │    │
│  │  │  ┌──────┐ ┌──────┐ ┌──────┐  │  │    │
│  │  │  │ Read │ │ Bash │ │Edit  │  │  │    │
│  │  │  └──────┘ └──────┘ └──────┘  │  │    │
│  │  │  ┌──────┐ ┌──────┐ ┌──────┐  │  │    │
│  │  │  │ Grep │ │Glob  │ │Agent │  │  │    │
│  │  │  └──────┘ └──────┘ └──────┘  │  │    │
│  │  └───────────────────────────────┘  │    │
│  └─────────────────────────────────────┘    │
│                    ↕                          │
│         本地文件系统 + Git仓库               │
└─────────────────────────────────────────────┘
```

### 1.2 核心API一览

| API | 用途 | 返回值 |
|-----|------|--------|
| `claude()` | 单次Agent调用，返回完整结果 | `Promise<AgentResult>` |
| `claudeStream()` | 流式调用，逐步接收消息 | `AsyncIterable<AgentEvent>` |
| `createSession()` | 创建持久化会话 | `Session` |
| `Session#sendMessage()` | 在会话中继续对话 | `Promise<AgentResult>` |

### 1.3 与Headless模式的关系

Headless模式（`claude -p`）是CLI层面的非交互接口，Agent SDK是其编程层面的等价物。两者底层共享同一套Agent引擎：

```mermaid
flowchart TB
    subgraph "用户触达方式"
        CLI[claude -p 命令行]
        SDK["@anthropic-ai/claude-code<br/>TypeScript SDK"]
        PY["@anthropic-ai/claude-code<br/>Python SDK"]
    end

    subgraph "Agent引擎"
        CORE[Agent Loop<br/>工具调度 · 上下文管理<br/>多轮推理 · 权限控制]
    end

    subgraph "工具层"
        T1[文件读写]
        T2[Shell执行]
        T3[代码搜索]
        T4[子Agent]
        T5[MCP工具]
    end

    CLI --> CORE
    SDK --> CORE
    PY --> CORE
    CORE --> T1 & T2 & T3 & T4 & T5
```

---

## 第二章：安装与基础用法

### 2.1 项目初始化

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

# 初始化Node.js项目（ESM模式）
npm init -y
npm pkg set type="module"

# 安装依赖
npm install @anthropic-ai/claude-code
npm install -D typescript @types/node

# TypeScript配置
cat > tsconfig.json << 'EOF'
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "strict": true,
    "esModuleInterop": true,
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "include": ["src/**/*"]
}
EOF

mkdir src
```

### 2.2 第一次调用

创建你的第一个Agent脚本：

```typescript
// src/hello-agent.ts
import { claude } from "@anthropic-ai/claude-code";

const result = await claude({
  prompt: "列出当前目录的文件结构，并说明每个文件的用途",
  options: {
    maxTurns: 3,
    allowedTools: ["Read", "Glob", "Bash"],
  },
});

console.log("Agent回复：");
console.log(result.text);

console.log("\n--- 统计信息 ---");
console.log(`总轮次: ${result.turns}`);
console.log(`使用的工具: ${result.toolsUsed.join(", ")}`);
console.log(`Token消耗: ${result.usage?.totalTokens}`);
```

```bash
# 运行
npx tsx src/hello-agent.ts
```

**预期输出**：

```
Agent回复：
当前目录包含以下文件：

1. package.json - Node.js项目配置文件，定义依赖和脚本
2. tsconfig.json - TypeScript编译配置
3. src/hello-agent.ts - 主Agent脚本

--- 统计信息 ---
总轮次: 2
使用的工具: Glob, Read
Token消耗: 3842
```

### 2.3 常见问题与解决

| 问题 | 原因 | 解决方案 |
|------|------|----------|
| `MODULE_NOT_FOUND` | ESM/CJS混用 | 确保`package.json`设置`"type": "module"` |
| `claude: command not found` | 未安装Claude Code CLI | `npm install -g @anthropic-ai/claude-code` |
| `Authentication required` | 未登录 | 运行`claude login`完成认证 |
| `Tool not allowed` | 工具不在白名单 | 在`allowedTools`中添加工具名 |

---

## 第三章：流式输出与事件处理

### 3.1 流式调用基础

对于长时间运行的Agent任务，流式输出能让你实时展示进度：

```typescript
// src/stream-agent.ts
import { claudeStream } from "@anthropic-ai/claude-code";

const stream = claudeStream({
  prompt: "分析当前项目的代码质量，找出潜在问题",
  options: {
    maxTurns: 10,
    allowedTools: ["Read", "Glob", "Grep", "Bash"],
  },
});

let fullText = "";
let toolCalls = 0;

for await (const event of stream) {
  switch (event.type) {
    case "text":
      // 实时输出Agent的文本内容
      process.stdout.write(event.content);
      fullText += event.content;
      break;

    case "tool_use":
      toolCalls++;
      console.log(`\n[工具调用 #${toolCalls}] ${event.tool}`);
      console.log(`  参数: ${JSON.stringify(event.input).slice(0, 100)}...`);
      break;

    case "tool_result":
      const status = event.isError ? "❌ 失败" : "✅ 完成";
      console.log(`  结果: ${status}`);
      break;

    case "done":
      console.log(`\n\n=== Agent完成 ===`);
      console.log(`总文本长度: ${fullText.length} 字符`);
      console.log(`工具调用次数: ${toolCalls}`);
      break;
  }
}
```

### 3.2 事件类型详解

```mermaid
flowchart LR
    subgraph "Agent事件流"
        E1["session_start<br/>会话初始化"]
        E2["text<br/>流式文本输出"]
        E3["tool_use<br/>发起工具调用"]
        E4["tool_result<br/>工具返回结果"]
        E5["thinking<br/>推理中间步骤"]
        E6["done<br/>Agent完成"]
        E7["error<br/>错误事件"]
    end

    E1 --> E2
    E2 --> E3
    E3 --> E4
    E4 --> E2
    E2 --> E5
    E5 --> E6
    E3 --> E7
```

| 事件类型 | 字段 | 说明 |
|----------|------|------|
| `text` | `content` | Agent生成的文本片段 |
| `tool_use` | `tool`, `input` | 即将执行的工具和参数 |
| `tool_result` | `output`, `isError` | 工具执行结果 |
| `thinking` | `content` | Agent的推理过程（Extended Thinking模式） |
| `done` | `result` | Agent完成，包含完整结果 |
| `error` | `message` | 错误信息 |

### 3.3 结构化输出

当Agent需要返回结构化数据而非自由文本时，使用JSON Schema约束输出：

```typescript
// src/structured-output.ts
import { claude } from "@anthropic-ai/claude-code";

interface CodeIssue {
  file: string;
  line: number;
  severity: "error" | "warning" | "info";
  message: string;
  suggestion: string;
}

const CodeReviewSchema = {
  type: "object",
  properties: {
    issues: {
      type: "array",
      items: {
        type: "object",
        properties: {
          file: { type: "string" },
          line: { type: "number" },
          severity: { 
            type: "string", 
            enum: ["error", "warning", "info"] 
          },
          message: { type: "string" },
          suggestion: { type: "string" },
        },
        required: ["file", "line", "severity", "message"],
      },
    },
    summary: { type: "string" },
    score: { type: "number", minimum: 0, maximum: 10 },
  },
  required: ["issues", "summary", "score"],
};

const result = await claude({
  prompt: `审查以下TypeScript文件的代码质量，找出所有问题：
  
  重点检查：
  1. 类型安全性
  2. 错误处理
  3. 性能问题
  4. 代码风格`,
  options: {
    maxTurns: 5,
    allowedTools: ["Read", "Glob"],
    // 结构化输出通过提示词引导实现
  },
});

// 解析结果
const jsonMatch = result.text.match(/```json\n([\s\S]*?)\n```/);
if (jsonMatch) {
  const review: CodeReviewSchema = JSON.parse(jsonMatch[1]);
  console.log(`代码评分: ${review.score}/10`);
  console.log(`发现 ${review.issues.length} 个问题`);
  review.issues.forEach((issue, i) => {
    console.log(`\n[${issue.severity.toUpperCase()}] ${issue.file}:${issue.line}`);
    console.log(`  ${issue.message}`);
    if (issue.suggestion) {
      console.log(`  建议: ${issue.suggestion}`);
    }
  });
}
```

---

## 第四章：权限控制与工具白名单

### 4.1 工具白名单机制

Agent SDK继承了Claude Code的完整工具集，但你可以精确控制Agent能使用哪些工具：

```typescript
// src/permission-control.ts
import { claude } from "@anthropic-ai/claude-code";

// 只读模式 —— 只允许查看，不允许修改
const readOnlyResult = await claude({
  prompt: "分析项目依赖关系，生成依赖图谱",
  options: {
    maxTurns: 5,
    allowedTools: [
      "Read",    // 读文件
      "Glob",    // 文件搜索
      "Grep",    // 内容搜索
      "Bash",    // 注意：Bash可以执行任意命令
    ],
    // Bash命令白名单（通过permissionMode控制）
    permissionMode: "default",  // 会弹出权限确认
  },
});

// 完全自动模式 —— 信任Agent的所有操作
const fullAutoResult = await claude({
  prompt: "重构src/utils目录，将所有工具函数按功能分类到子模块中",
  options: {
    maxTurns: 20,
    allowedTools: ["Read", "Write", "Edit", "Glob", "Grep", "Bash", "Agent"],
    permissionMode: "acceptEdits",  // 自动接受文件编辑
  },
});
```

### 4.2 权限模式详解

| 模式 | 说明 | 适用场景 |
|------|------|----------|
| `default` | 每次敏感操作需确认 | 开发调试阶段 |
| `acceptEdits` | 自动接受文件编辑，Shell仍需确认 | 代码重构 |
| `acceptAll` | 自动接受所有操作 | CI/CD、无人值守 |
| `dontAsk` | 不询问，但也不自动执行受限操作 | 最严格的安全模式 |

### 4.3 安全最佳实践

```typescript
// src/safe-agent.ts
import { claude } from "@anthropic-ai/claude-code";

// 生产环境推荐配置
const safeConfig = {
  // 1. 最小工具集原则
  allowedTools: ["Read", "Glob", "Grep"] as const,
  
  // 2. 限制最大轮次，防止失控
  maxTurns: 10,
  
  // 3. 使用strict模式
  permissionMode: "dontAsk" as const,
  
  // 4. 设置工作目录，限制Agent活动范围
  cwd: "/app/workspace",
  
  // 5. 设置超时
  timeout: 300_000, // 5分钟
};

const result = await claude({
  prompt: "检查workspace目录下的代码，生成安全审计报告",
  options: safeConfig,
});
```

---

## 第五章：Headless模式与脚本集成

### 5.1 CLI层面的Headless模式

Agent SDK底层依赖的`claude -p`模式（Headless模式）是脚本集成的关键入口：

```bash
# 基础用法：单次提问
claude -p "解释这个函数的作用"

# 管道输入
cat src/index.ts | claude -p "审查这段代码"

# JSON输出格式
claude -p "列出所有TODO注释" --output-format json

# 流式JSON输出
claude -p "重构整个项目" --output-format stream-json

# 指定模型
claude -p "生成单元测试" --model claude-sonnet-4-6-20250514

# 限制工具和轮次
claude -p "分析代码" --max-turns 5 --allowedTools "Read,Glob,Grep"

# Bare模式：纯净输出，无额外标记
claude -p "生成README" --bare
```

### 5.2 在Shell脚本中编排Agent

```bash
#!/bin/bash
# multi-review.sh —— 批量代码审查脚本

set -e

# 审查所有最近修改的TypeScript文件
CHANGED_FILES=$(git diff --name-only HEAD~1 | grep '\.ts$')

echo "=== 开始审查 ${CHANGED_FILES} 个文件 ==="

for file in $CHANGED_FILES; do
  echo ""
  echo "--- 审查: $file ---"
  
  # 使用Headless模式审查每个文件
  claude -p "审查这个文件中的代码质量问题，重点关注：
  1. 类型安全
  2. 错误处理
  3. 性能瓶颈
  4. 安全漏洞
  
  输出格式：
  - 严重程度（Critical/Warning/Info）
  - 行号
  - 问题描述
  - 修复建议" \
    --allowedTools "Read,Grep" \
    --max-turns 3 \
    --bare \
    < "$file" | tee "reviews/$(basename $file).review.md"
done

echo ""
echo "=== 所有审查完成 ==="
echo "结果保存在 reviews/ 目录"
```

### 5.3 SDK与Headless的对比

| 维度 | `claude -p` (Headless) | Agent SDK |
|------|----------------------|-----------|
| 语言 | Shell/任意 | TypeScript/Python |
| 流式控制 | `stream-json`格式 | `for await`循环 |
| 结果解析 | 需手动解析JSON/文本 | 类型化的对象 |
| 会话管理 | 无状态，每次新会话 | 支持持久化Session |
| 错误处理 | 退出码+stderr | try/catch异常 |
| 适用场景 | 快速脚本、CI/CD | 复杂应用、自定义Agent |

---

## 第六章：会话管理与多轮对话

### 6.1 持久化会话

```typescript
// src/session-agent.ts
import { createSession } from "@anthropic-ai/claude-code";

// 创建一个持久化会话
const session = await createSession({
  options: {
    maxTurns: 30,
    allowedTools: ["Read", "Write", "Edit", "Glob", "Grep", "Bash"],
  },
});

// 第一轮：理解项目
const r1 = await session.sendMessage(
  "分析当前项目的整体架构，用Mermaid语法画出架构图"
);
console.log("架构分析完成:", r1.text.slice(0, 200));

// 第二轮：基于理解进行操作
const r2 = await session.sendMessage(
  "基于刚才的分析，重构src/api目录，将路由按领域拆分为独立模块"
);
console.log("重构完成:", r2.text.slice(0, 200));

// 第三轮：验证
const r3 = await session.sendMessage(
  "运行测试验证重构没有破坏现有功能"
);
console.log("测试结果:", r3.text.slice(0, 200));

// 关闭会话
await session.close();
```

### 6.2 会话状态流转

```mermaid
stateDiagram-v2
    [*] --> Created: createSession()
    Created --> Active: sendMessage()
    Active --> Active: 继续对话
    Active --> Paused: 超时/手动暂停
    Paused --> Active: sendMessage()
    Active --> Closed: close()
    Closed --> [*]
    
    note right of Active
        会话保持完整上下文
        包括对话历史和工具调用记录
    end note
```

### 6.3 上下文窗口管理

长会话会消耗大量Token。Agent SDK提供了上下文管理策略：

```typescript
// src/context-aware-agent.ts
import { claude } from "@anthropic-ai/claude-code";

// 策略1：限制轮次，自动压缩上下文
const result1 = await claude({
  prompt: "大规模重构项目",
  options: {
    maxTurns: 15,
    // 超过上下文窗口时自动压缩历史
    contextManagement: {
      strategy: "auto-compact",  // 自动压缩
      maxTokens: 180_000,        // 上下文上限
    },
  },
});

// 策略2：分段处理大任务
async function processLargeCodebase(files: string[]) {
  const BATCH_SIZE = 5;
  const results = [];
  
  for (let i = 0; i < files.length; i += BATCH_SIZE) {
    const batch = files.slice(i, i + BATCH_SIZE);
    const result = await claude({
      prompt: `分析以下文件的代码质量和依赖关系：\n${batch.join("\n")}`,
      options: {
        maxTurns: 8,
        allowedTools: ["Read", "Grep"],
      },
    });
    results.push({
      files: batch,
      analysis: result.text,
      tokens: result.usage?.totalTokens,
    });
    
    console.log(`已处理 ${Math.min(i + BATCH_SIZE, files.length)}/${files.length} 文件`);
  }
  
  return results;
}
```

---

## 第七章：子Agent编排与并行处理

### 7.1 启用子Agent

Agent SDK允许Agent在执行过程中调用子Agent（通过`Agent`工具），实现任务的分层委托：

```typescript
// src/orchestration.ts
import { claude } from "@anthropic-ai/claude-code";

const result = await claude({
  prompt: `你是一个代码审查编排器。请执行以下任务：

  1. 使用子Agent分析src/api目录的安全漏洞
  2. 使用子Agent分析src/utils目录的性能问题
  3. 使用子Agent检查所有TypeScript文件的类型安全性
  4. 汇总三个子Agent的结果，生成综合报告`,
  
  options: {
    maxTurns: 25,
    allowedTools: [
      "Read", "Glob", "Grep",  // 基础工具
      "Agent",                   // 允许调用子Agent
    ],
  },
});
```

### 7.2 并行Agent调度

```typescript
// src/parallel-agents.ts
import { claude } from "@anthropic-ai/claude-code";

interface ReviewResult {
  dimension: string;
  score: number;
  findings: string[];
}

async function parallelReview(
  filePath: string,
  dimensions: string[]
): Promise<ReviewResult[]> {
  // 并行启动多个Agent，每个负责一个审查维度
  const reviews = await Promise.all(
    dimensions.map(async (dim) => {
      const result = await claude({
        prompt: `以"${dim}"维度审查以下代码。只输出JSON格式的结果：
        {"score": 数字0-10, "findings": ["问题1", "问题2"]}
        
        文件: ${filePath}`,
        options: {
          maxTurns: 5,
          allowedTools: ["Read", "Grep"],
        },
      });

      // 解析Agent的JSON输出
      try {
        const jsonStr = result.text.match(/\{[\s\S]*\}/)?.[0];
        return {
          dimension: dim,
          ...(jsonStr ? JSON.parse(jsonStr) : { score: 0, findings: [] }),
        };
      } catch {
        return { dimension: dim, score: 0, findings: ["解析失败"] };
      }
    })
  );

  return reviews;
}

// 使用示例
const results = await parallelReview("src/auth/login.ts", [
  "安全性",
  "性能",
  "可维护性",
  "测试覆盖",
]);

console.log("=== 综合审查结果 ===");
results.forEach((r) => {
  console.log(`\n[${r.dimension}] 评分: ${r.score}/10`);
  r.findings.forEach((f) => console.log(`  - ${f}`));
});
```

### 7.3 Agent编排架构

```mermaid
flowchart TB
    subgraph "主Agent进程"
        MAIN[主Agent<br/>任务拆分与汇总]
    end

    subgraph "并行子Agent组"
        A1[安全审查Agent]
        A2[性能分析Agent]
        A3[代码质量Agent]
        A4[测试覆盖Agent]
    end

    subgraph "共享资源"
        FS[文件系统<br/>只读访问]
    end

    MAIN -->|"维度1: 安全"| A1
    MAIN -->|"维度2: 性能"| A2
    MAIN -->|"维度3: 质量"| A3
    MAIN -->|"维度4: 测试"| A4

    A1 & A2 & A3 & A4 --> FS

    A1 -->|"结果1"| MAIN
    A2 -->|"结果2"| MAIN
    A3 -->|"结果3"| MAIN
    A4 -->|"结果4"| MAIN

    MAIN --> REPORT[综合报告<br/>评分 + 改进建议]
```

---

## 第八章：与Hooks联动

### 8.1 Hooks在Agent SDK中的行为

当Agent通过SDK执行工具时，你配置在`settings.json`中的Hooks同样会触发。这为Agent操作增加了审计和安全防护层：

```json
// .claude/settings.json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "command": "node scripts/validate-command.js",
        "description": "验证Shell命令安全性"
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Edit",
        "command": "node scripts/post-edit-lint.js",
        "description": "编辑后自动运行lint"
      }
    ],
    "Stop": [
      {
        "command": "node scripts/on-complete.js",
        "description": "Agent完成后发送通知"
      }
    ]
  }
}
```

### 8.2 Hook脚本示例

```javascript
// scripts/validate-command.js
// PreToolUse Hook: 拦截危险命令

const input = JSON.parse(process.argv[2] || "{}");
const toolInput = input.tool_input || {};
const command = toolInput.command || "";

// 危险命令黑名单
const BLOCKED_PATTERNS = [
  /rm\s+-rf\s+\//,          // 递归删除根目录
  /DROP\s+TABLE/i,          // SQL注入
  /:\s*\(\)\s*\{/,          // Fork bomb
  /curl\s+.*\|\s*sh/,       // 远程脚本执行
  />\/dev\/sd/,              // 直接写磁盘
];

const blocked = BLOCKED_PATTERNS.some(p => p.test(command));

if (blocked) {
  // 输出JSON拒绝结果
  console.log(JSON.stringify({
    decision: "block",
    reason: `命令被安全策略拦截: ${command.slice(0, 50)}...`
  }));
  process.exit(0);
}

// 允许执行
console.log(JSON.stringify({ decision: "allow" }));
process.exit(0);
```

### 8.3 PostToolUse自动格式化

```javascript
// scripts/post-edit-lint.js
// PostToolUse Hook: 文件编辑后自动格式化

const input = JSON.parse(process.argv[2] || "{}");
const filePath = input.tool_input?.file_path || "";

const { execSync } = require("child_process");

// 根据文件类型执行格式化
if (filePath.endsWith(".ts") || filePath.endsWith(".tsx")) {
  try {
    execSync(`npx prettier --write "${filePath}"`, { stdio: "pipe" });
    console.log(JSON.stringify({
      message: `✅ 已格式化: ${filePath}`
    }));
  } catch (e) {
    console.log(JSON.stringify({
      message: `⚠️ 格式化失败: ${e.message}`
    }));
  }
} else if (filePath.endsWith(".py")) {
  try {
    execSync(`black "${filePath}"`, { stdio: "pipe" });
    console.log(JSON.stringify({
      message: `✅ 已格式化: ${filePath}`
    }));
  } catch (e) {
    console.log(JSON.stringify({
      message: `⚠️ 格式化失败`
    }));
  }
}
```

---

## 第九章：实战项目——代码审查与自动修复Agent

### 9.1 项目结构

```
code-review-agent/
├── package.json
├── tsconfig.json
├── .claude/
│   └── settings.json        # Hooks配置
├── src/
│   ├── index.ts             # 主入口
│   ├── reviewer.ts          # 审查逻辑
│   ├── fixer.ts             # 自动修复
│   ├── reporter.ts          # 报告生成
│   └── types.ts             # 类型定义
└── scripts/
    ├── validate-cmd.js      # Hook: 命令验证
    └── notify.js            # Hook: 完成通知
```

### 9.2 类型定义

```typescript
// src/types.ts
export interface ReviewIssue {
  file: string;
  line: number;
  column?: number;
  severity: "critical" | "warning" | "info";
  category: "security" | "performance" | "bug" | "style" | "type-safety";
  title: string;
  description: string;
  fix?: string;           // 建议的修复代码
  confidence: number;      // 0-1
}

export interface ReviewReport {
  timestamp: string;
  filesReviewed: number;
  totalIssues: number;
  criticalCount: number;
  warningCount: number;
  score: number;           // 0-100
  issues: ReviewIssue[];
  autoFixed: number;
  summary: string;
}

export interface AgentConfig {
  maxTurns: number;
  parallelReviews: number;
  autoFix: boolean;
  severityThreshold: "critical" | "warning" | "info";
  outputFormat: "json" | "markdown" | "html";
}
```

### 9.3 核心审查逻辑

```typescript
// src/reviewer.ts
import { claude } from "@anthropic-ai/claude-code";
import type { ReviewIssue, AgentConfig } from "./types.js";

export class CodeReviewer {
  private config: AgentConfig;

  constructor(config: Partial<AgentConfig> = {}) {
    this.config = {
      maxTurns: 10,
      parallelReviews: 3,
      autoFix: false,
      severityThreshold: "warning",
      outputFormat: "markdown",
      ...config,
    };
  }

  async reviewFiles(files: string[]): Promise<ReviewIssue[]> {
    // 将文件分批并行审查
    const batches = this.chunkArray(files, this.config.parallelReviews);
    const allIssues: ReviewIssue[] = [];

    for (const batch of batches) {
      const batchIssues = await Promise.all(
        batch.map((file) => this.reviewSingleFile(file))
      );
      allIssues.push(...batchIssues.flat());
    }

    // 按严重程度排序
    const severityOrder = { critical: 0, warning: 1, info: 2 };
    allIssues.sort(
      (a, b) => severityOrder[a.severity] - severityOrder[b.severity]
    );

    return allIssues;
  }

  private async reviewSingleFile(filePath: string): Promise<ReviewIssue[]> {
    const result = await claude({
      prompt: `你是一个专业的代码审查专家。请仔细审查文件 ${filePath}。

审查维度：
1. **安全漏洞**: SQL注入、XSS、CSRF、硬编码密钥、不安全的反序列化
2. **性能问题**: N+1查询、内存泄漏、不必要的同步操作、大数据处理
3. **Bug风险**: 空指针、竞态条件、边界条件、资源泄露
4. **类型安全**: any类型滥用、类型断言、缺少泛型约束
5. **代码风格**: 命名规范、函数长度、圈复杂度

对每个问题输出JSON格式：
{
  "line": 行号,
  "severity": "critical"|"warning"|"info",
  "category": 分类,
  "title": 问题标题,
  "description": 详细描述,
  "fix": "修复代码（如果有明确修复方案）",
  "confidence": 0.0到1.0
}

最终输出JSON数组：[问题1, 问题2, ...]`,
      options: {
        maxTurns: this.config.maxTurns,
        allowedTools: ["Read", "Grep"],
      },
    });

    return this.parseIssues(result.text, filePath);
  }

  private parseIssues(text: string, filePath: string): ReviewIssue[] {
    try {
      const jsonMatch = text.match(/\[[\s\S]*\]/);
      if (!jsonMatch) return [];

      const issues = JSON.parse(jsonMatch[0]);
      return issues.map((issue: any) => ({
        ...issue,
        file: filePath,
      }));
    } catch {
      console.error(`解析审查结果失败: ${filePath}`);
      return [];
    }
  }

  private chunkArray<T>(arr: T[], size: number): T[][] {
    const chunks: T[][] = [];
    for (let i = 0; i < arr.length; i += size) {
      chunks.push(arr.slice(i, i + size));
    }
    return chunks;
  }
}
```

### 9.4 自动修复模块

```typescript
// src/fixer.ts
import { claude } from "@anthropic-ai/claude-code";
import type { ReviewIssue } from "./types.js";

export class AutoFixer {
  async fixIssues(issues: ReviewIssue[]): Promise<number> {
    // 只修复有明确修复方案且置信度高的issues
    const fixable = issues.filter(
      (i) => i.fix && i.confidence >= 0.8 && i.severity !== "critical"
    );

    let fixedCount = 0;

    // 按文件分组
    const byFile = new Map<string, ReviewIssue[]>();
    for (const issue of fixable) {
      const list = byFile.get(issue.file) || [];
      list.push(issue);
      byFile.set(issue.file, list);
    }

    // 逐文件修复
    for (const [file, fileIssues] of byFile) {
      console.log(`修复 ${file} 中的 ${fileIssues.length} 个问题...`);

      const issueList = fileIssues
        .map((i) => `- 第${i.line}行 [${i.severity}] ${i.title}\n  修复: ${i.fix}`)
        .join("\n");

      const result = await claude({
        prompt: `请修复文件 ${file} 中的以下问题：

${issueList}

要求：
1. 保持代码风格一致
2. 不改变非相关代码
3. 修复后确保语法正确
4. 如果修复可能引入新问题，跳过该修复`,
        options: {
          maxTurns: 15,
          allowedTools: ["Read", "Edit", "Bash"],
          permissionMode: "acceptEdits",
        },
      });

      // 验证修复
      const verifyResult = await claude({
        prompt: `验证文件 ${file} 的修复是否正确：
1. 检查语法是否正确
2. 确认问题是否已解决
3. 检查是否引入了新问题`,
        options: {
          maxTurns: 3,
          allowedTools: ["Read", "Bash"],
        },
      });

      if (verifyResult.text.includes("修复正确") || 
          verifyResult.text.includes("no errors")) {
        fixedCount += fileIssues.length;
        console.log(`  ✅ 修复成功`);
      } else {
        console.log(`  ⚠️ 修复可能有问题，建议人工确认`);
      }
    }

    return fixedCount;
  }
}
```

### 9.5 报告生成

```typescript
// src/reporter.ts
import type { ReviewReport, ReviewIssue } from "./types.js";

export class Reporter {
  generateMarkdownReport(
    issues: ReviewIssue[],
    filesReviewed: number,
    autoFixed: number
  ): string {
    const critical = issues.filter((i) => i.severity === "critical");
    const warnings = issues.filter((i) => i.severity === "warning");
    const info = issues.filter((i) => i.severity === "info");

    const score = Math.max(
      0,
      100 - critical.length * 15 - warnings.length * 5 - info.length * 1
    );

    let report = `# 🔍 代码审查报告\n\n`;
    report += `**审查时间**: ${new Date().toISOString()}\n`;
    report += `**审查文件数**: ${filesReviewed}\n`;
    report += `**代码评分**: ${score}/100\n\n`;

    report += `## 📊 问题统计\n\n`;
    report += `| 严重程度 | 数量 |\n|----------|------|\n`;
    report += `| 🔴 Critical | ${critical.length} |\n`;
    report += `| 🟡 Warning | ${warnings.length} |\n`;
    report += `| 🔵 Info | ${info.length} |\n`;
    report += `| **总计** | **${issues.length}** |\n\n`;

    if (autoFixed > 0) {
      report += `## 🔧 自动修复\n\n`;
      report += `已自动修复 **${autoFixed}** 个问题。\n\n`;
    }

    if (critical.length > 0) {
      report += `## 🔴 严重问题\n\n`;
      critical.forEach((issue) => {
        report += `### ${issue.file}:${issue.line}\n`;
        report += `**${issue.title}** [${issue.category}]\n\n`;
        report += `${issue.description}\n\n`;
        if (issue.fix) {
          report += `> 💡 建议: ${issue.fix}\n\n`;
        }
      });
    }

    if (warnings.length > 0) {
      report += `## 🟡 警告\n\n`;
      warnings.forEach((issue) => {
        report += `- **${issue.file}:${issue.line}** — ${issue.title}\n`;
      });
      report += `\n`;
    }

    return report;
  }
}
```

### 9.6 主入口

```typescript
// src/index.ts
import { CodeReviewer } from "./reviewer.js";
import { AutoFixer } from "./fixer.js";
import { Reporter } from "./reporter.js";
import type { AgentConfig } from "./types.js";

async function main() {
  const config: AgentConfig = {
    maxTurns: 10,
    parallelReviews: 3,
    autoFix: process.argv.includes("--fix"),
    severityThreshold: "warning",
    outputFormat: "markdown",
  };

  // 获取待审查的文件列表
  const { execSync } = await import("child_process");
  const changedFiles = execSync(
    'git diff --name-only HEAD~1 -- "*.ts" "*.tsx" "*.js" "*.jsx"',
    { encoding: "utf-8" }
  ).trim().split("\n").filter(Boolean);

  if (changedFiles.length === 0) {
    console.log("没有发现变更的代码文件");
    return;
  }

  console.log(`📋 发现 ${changedFiles.length} 个变更文件`);
  console.log(`📄 文件列表: ${changedFiles.join(", ")}`);
  console.log(`🔧 自动修复: ${config.autoFix ? "开启" : "关闭"}\n`);

  // 执行审查
  const reviewer = new CodeReviewer(config);
  const issues = await reviewer.reviewFiles(changedFiles);

  // 可选：自动修复
  let autoFixed = 0;
  if (config.autoFix) {
    const fixer = new AutoFixer();
    autoFixed = await fixer.fixIssues(issues);
  }

  // 生成报告
  const reporter = new Reporter();
  const report = reporter.generateMarkdownReport(
    issues,
    changedFiles.length,
    autoFixed
  );

  console.log(report);
}

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

### 9.7 运行实战项目

```bash
# 只审查不修复
npx tsx src/index.ts

# 审查并自动修复
npx tsx src/index.ts --fix

# 审查特定分支的变更
git diff main..feature/auth --name-only -- "*.ts" | npx tsx src/index.ts
```

### 9.8 完整工作流程

```mermaid
flowchart TB
    START[Git Push / PR 创建] --> DIFF[获取变更文件列表]
    DIFF --> FILTER[过滤代码文件<br/>.ts .tsx .js .jsx]
    FILTER --> PARALLEL[并行审查Agent]

    subgraph "并行审查"
        direction LR
        PA1[安全审查<br/>Agent 1]
        PA2[性能审查<br/>Agent 2]
        PA3[质量审查<br/>Agent 3]
    end

    PARALLEL --> PA1 & PA2 & PA3

    PA1 & PA2 & PA3 --> MERGE[合并审查结果]
    MERGE --> SCORE[计算代码评分]
    SCORE --> CHECK{是否需要<br/>自动修复？}

    CHECK -->|是 --fix| FIX[AutoFixer Agent<br/>修复并验证]
    CHECK -->|否| REPORT[生成Markdown报告]

    FIX --> REPORT
    REPORT --> OUTPUT[输出到终端 / 文件]

    style CHECK fill:#f9f,stroke:#333
    style FIX fill:#bfb,stroke:#333
    style OUTPUT fill:#bbf,stroke:#333
```

---

## 第十章：生产部署注意事项

### 10.1 Token预算管理

```typescript
// src/budget-manager.ts
import { claude } from "@anthropic-ai/claude-code";

class BudgetManager {
  private totalBudget: number;
  private spent: number = 0;

  constructor(maxTokens: number = 500_000) {
    this.totalBudget = maxTokens;
  }

  remaining(): number {
    return Math.max(0, this.totalBudget - this.spent);
  }

  async runAgent(prompt: string, maxTurns: number = 5): Promise<any> {
    if (this.remaining() < 10_000) {
      throw new Error(`Token预算不足: 剩余 ${this.remaining()}`);
    }

    const result = await claude({
      prompt,
      options: { maxTurns },
    });

    // 累计消耗
    if (result.usage?.totalTokens) {
      this.spent += result.usage.totalTokens;
    }

    console.log(`本次消耗: ${result.usage?.totalTokens}, 剩余预算: ${this.remaining()}`);
    return result;
  }
}

// 使用
const budget = new BudgetManager(1_000_000); // 100万Token预算
const result = await budget.runAgent("审查所有代码");
```

### 10.2 错误重试与容错

```typescript
// src/resilient-agent.ts
async function resilientAgentCall(
  prompt: string,
  maxRetries: number = 3
): Promise<any> {
  let lastError: Error | null = null;

  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const result = await claude({
        prompt,
        options: { maxTurns: 10 },
      });
      return result;
    } catch (error: any) {
      lastError = error;
      
      if (error.message?.includes("rate limit")) {
        const delay = Math.min(1000 * Math.pow(2, attempt), 30_000);
        console.log(`速率限制，${delay}ms后重试 (${attempt}/${maxRetries})`);
        await new Promise((r) => setTimeout(r, delay));
      } else if (error.message?.includes("context window")) {
        // 上下文溢出，减少轮次重试
        console.log(`上下文溢出，减少任务复杂度后重试`);
        const result = await claude({
          prompt: prompt.slice(0, 2000),  // 截断提示
          options: { maxTurns: 3 },
        });
        return result;
      } else {
        throw error;  // 不可重试的错误直接抛出
      }
    }
  }

  throw lastError;
}
```

### 10.3 Agent SDK额度注意

从2026年6月15日起，Anthropic将Agent SDK和`claude -p`的使用量从交互式额度中分离，改为独立的月度Agent SDK额度。关键影响：

| 项目 | 变更前 | 变更后 |
|------|--------|--------|
| Agent SDK调用 | 消耗交互式额度 | 独立的Agent SDK月度额度 |
| `claude -p` | 消耗交互式额度 | 独立的Agent SDK月度额度 |
| 交互式Claude Code | 不受影响 | 不受影响 |
| 额度重置 | 按订阅周期 | 按月重置 |

生产环境中建议通过`result.usage`字段持续监控Token消耗，避免超出额度。

---

## 延伸阅读

- [Anthropic官方Agent SDK文档](https://code.claude.com/docs/en/agent-sdk/overview) — Agent SDK完整参考
- [Agent SDK TypeScript API Reference](https://code.claude.com/docs/en/agent-sdk/typescript) — TypeScript接口详解
- [Claude Agent SDK GitHub仓库](https://github.com/anthropics/claude-agent-sdk-typescript) — 源码与示例
- [Headless Mode官方文档](https://code.claude.com/docs/en/headless) — 非交互模式参考
- [Hooks参考文档](https://code.claude.com/docs/en/hooks) — Hook事件与配置
- [Scheduled Tasks文档](https://code.claude.com/docs/en/scheduled-tasks) — 定时任务与/loop
- [Worktrees并行开发](https://code.claude.com/docs/en/worktrees) — Git工作树隔离

## 参考来源

1. [Run Claude Code programmatically - Anthropic官方文档](https://code.claude.com/docs/en/headless) — Headless模式与Agent SDK编程指南
2. [Agent SDK reference - TypeScript - Anthropic官方文档](https://code.claude.com/docs/en/agent-sdk/typescript) — TypeScript Agent SDK完整API参考
3. [anthropics/claude-agent-sdk-typescript - GitHub](https://github.com/anthropics/claude-agent-sdk-typescript) — 官方Agent SDK源码仓库与使用示例
4. [Build Production AI Agents with the Claude Agent SDK and TypeScript](https://noqta.tn/en/tutorials/claude-agent-sdk-typescript-ai-agents-2026) — 生产级Agent构建教程
5. [Claude Code SDK: Build Custom AI Agents & Programmatic Automation](https://skillsplayground.com/guides/claude-code-sdk/) — SDK编程化自动化综合指南
6. [Hooks reference - Anthropic官方文档](https://code.claude.com/docs/en/hooks) — Hook事件系统完整参考
7. [Run prompts on a schedule - Anthropic官方文档](https://code.claude.com/docs/en/scheduled-tasks) — 定时任务与循环调度

---

**训练营适用性评估**：

| 维度 | 评估 |
|------|------|
| 适合训练营类型 | AI工程训练营、Agent开发进阶营、DevOps自动化训练营 |
| 学员基础要求 | TypeScript中级、Claude Code基本操作经验、Node.js项目经验 |
| 预计教学时长 | 6-8小时（含实操） |
| 实操比重 | 70%实操 + 30%讲解 |
| 硬件要求 | 每人一台开发机，安装Node.js 18+和Claude Code |
| 产出物 | 可运行的代码审查Agent，含审查、修复、报告三模块 |
| 难度等级 | ⭐⭐⭐⭐（中高级） |

> [!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)
