Agent SDK智能体开发套件1

1 Agent SDK的定位:从工具到组件

  • 它预设开发者是应用构建者,旨在将ClaudeCode的核心能力深度嵌入自有应用中
点击查看代码
# Python
pip install claude-agent-sdk
# TypeScript/Node.js 
npm install @anthropic-ai/claude-agent-sdk

2 核心API:query函数

  • Agent SDK的入口是query函数,异步消息流。

2.1 Python版本

点击查看代码
import asyncio

from claude_agent_sdk import query, ClaudeAgentOptions


async def analyze_code():
    options = ClaudeAgentOptions(
        max_turns=5,
        allowed_tools=["Read", "Grep", "Glob"],
        system_prompt="你是一名代码架构分析师",
    )

    async for message in query(
        prompt="分析 src/auth/ 目录的实现架构",
        options=options,
    ):
        if message.type == "assistant":
            for block in message.content:
                if hasattr(block, "text"):
                    print(block.text, end="", flush=True)
        elif message.type == "result":
            print(f"\n\n完成。费用:${message.total_cost_usd:.4f}")


asyncio.run(analyze_code())

2.2 TypeScript版本

点击查看代码
import { query, ClaudeAgentOptions } from "@anthropic-ai/claude-agent-sdk";

const options: ClaudeAgentOptions = {
  maxTurns: 5,
  allowedTools: ["Read", "Grep", "Glob"],
  systemPrompt: "你是一名代码架构分析师。",
};

async function analyzeCode() {
  for await (const message of query({
    prompt: "分析 src/auth/ 目录的实现架构",
    options,
  })) {
    if (message.type === "assistant") {
      for (const block of message.content) {
        if ("text" in block) {
          process.stdout.write(block.text);
        }
      }
    } else if (message.type === "result") {
      console.log(`\n\n完成。费用:$${message.totalCostUsd}`);
    }
  }
}

analyzeCode();

3 消息类型:解读Claude的输出流

3.1 system/init——会话初始化

点击查看代码
{
  "type": "system",
  "subtype": "init",
  "session_id": "550e8400-...",
  "model": "claude-sonnet4-6",
  "tools": [
    "Read",
    "Grep",
    "Glob"
  ],
  "mcp_servers": []
}

3.2 assistant——Claude的响应

点击查看代码
{
  "type": "assistant",
  "message": {
    "role": "assistant",
    "content": [
      {
        "type": "text",
        "text": "让我先看看目录结构……"
      },
      {
        "type": "tool_use",
        "id": "toolu_xxx",
        "name": "Glob",
        "input": {
          "pattern": "src/auth/**/*"
        }
      }
    ]
  }
}

3.3 user——工具执行结果

点击查看代码
{
  "type": "user",
  "message": {
    "role": "user",
    "content": [
      {
        "type": "tool_result",
        "tool_use_id": "toolu_xxx",
        "content": "src/auth/\n├── login.ts\n├── session.ts\n└── middleware.ts"
      }
    ]
  }
}

3.4 result——任务完成

  • 以下代码展示了任务完成时的终止消息示例。
点击查看代码
{
  "type": "result",
  "subtype": "success",
  "session_id": "550e8400-...",
  "num_turns": 5,
  "total_cost_usd": 0.0342,
  "duration_ms": 12345,
  "duration_api_ms": 10000,
  "usage": {
    "input_tokens": 5000,
    "output_tokens": 1500,
    "cache_read_input_tokens": 3000
  },
  "result": "架构分析:src/auth/ 采用分层设计...",
  "structured_output": null
}
  • 以下代码展示了一个实用的消息处理模式,用于在异步消息流中收集文本输出、记录工具调用详情并存储会话元数据。
点击查看代码
async def process_query(prompt: str, options: ClaudeAgentOptions) -> dict:
    """处理查询流并聚合结果。"""
    # 初始化结果容器
    result = {
        "text": [],
        "tools": [],
        "metadata": {},
        "error": None,
    }

    # 异步遍历消息流
    async for message in query(prompt=prompt, options=options):
        if message.type == "assistant":
            # 处理助手响应中的内容块
            for block in message.content:
                if hasattr(block, "text"):
                    # 收集文本输出(思考或回答)
                    result["text"].append(block.text)
                elif hasattr(block, "name"):
                    # 记录工具调用(名称与输入参数)
                    result["tools"].append({
                        "tool": block.name,
                        "input": block.input,
                    })

        elif message.type == "result":
            # 提取终止消息中的元数据
            result["metadata"] = {
                "session_id": message.session_id,
                "cost": message.total_cost_usd,
                "turns": message.num_turns,
                "duration_ms": message.duration_ms,
            }

            # 检查是否因错误终止
            if message.is_error:
                result["error"] = message.subtype

    return result

4 ClaudeAgentOptions:精细的行为控制

点击查看代码
from claude_agent_sdk import ClaudeAgentOptions

options = ClaudeAgentOptions(
    # === 模型与执行控制 ===
    model="claude-sonnet-4-6",       # 指定使用的模型版本
    max_turns=10,                    # 限制最大交互轮数,防止死循环
    max_budget_usd=1.0,              # 设置单次任务的费用上限(美元),超出即停止

    # === 工具权限管理 ===
    # 白名单:仅允许使用列出的工具
    allowed_tools=["Read", "Grep", "Glob", "Write"],
    # 黑名单:明确禁止使用的工具(优先级通常高于白名单或作为补充)
    disallowed_tools=["Bash"],

    # === 权限模式 ===
    # default:           标准模式,需用户确认危险操作
    # acceptEdits:       自动接受文件编辑
    # plan:              仅规划不执行
    # bypassPermissions: 跳过所有确认(高风险,仅限受信任环境)
    permission_mode="default",

    # === 提示工程 ===
    system_prompt="你是一名高级代码审查员",         # 设定核心系统指令
    append_system_prompt="务必检查SQL注入漏洞",      # 在核心指令后追加特定要求

    # === 工作环境配置 ===
    cwd="path/to/project",           # 设置 Agent 的工作目录
    env={"PROJECT_NAME": "MyApp"},   # 注入自定义环境变量

    # === 会话管理 ===
    resume="session-id-to-resume",   # 从指定的 session_id 恢复上下文
    no_session_persistence=False,    # 若为 True,则任务结束后不保存会话历史

    # === 结构化输出 ===
    # 强制模型输出符合特定 JSON Schema 格式的数据
    output_format={
        "type": "json_schema",
        "schema": my_schema,
    },

    # === MCP 集成 ===
    # 动态启动并连接外部 MCP 服务器
    mcp_servers=[
        {
            "name": "db",
            "command": "python",
            "args": ["./db_server.py"],
        }
    ],
)

4.1 权限模式详解

  • 权限模式是Agent SDK应用安全防线的核心。

4.2 工具权限的模式匹配

  • allowed_tools支持与Headless CLI相同的模式匹配语法。
点击查看代码
options = ClaudeAgentOptions(
    allowed_tools=[
        "Read",
        "Grep",
        "Glob",
        "Bash(git diff *)",          # 仅允许执行 git diff 命令
        "Bash(npm test *)",          # 仅允许执行 npm test 命令
        "mcp__database__query",      # 仅允许使用 MCP 数据库查询工具
    ],
)

5 会话管理:跨调用的上下文延续

5.1 基于session_id的会话延续

点击查看代码
# === 第一次调用:分析问题 ===
session_id = None

async for message in query(prompt="分析 src/auth 的安全问题", options=options):
    if message.type == "system" and message.subtype == "init":
        # 【关键】获取会话 ID,用于后续恢复上下文
        session_id = message.session_id

    if message.type == "result":
        print(message.result)


# === 第二次调用:在上一轮上下文的基础上继续深入 ===
resume_options = ClaudeAgentOptions(**options.__dict__, resume=session_id)

async for message in query(
    prompt="重点分析你发现的第一个SQL注入风险",
    options=resume_options,
):
    if message.type == "result":
        print(message.result)

5.2 会话分叉

点击查看代码
# === 基于同一个分析结果,探索不同的方向 ===

# 创建分叉配置:复用原会话状态,但开启新分支
options_fork = ClaudeAgentOptions(
    **options.__dict__,
    resume=session_id,
    fork_session=True,
)

# --- 方向 A:探讨微服务重构方案 ---
async for message in query(
    prompt="如果重构为微服务架构,需要修改哪些部分?",
    options=options_fork,
):
    ...

# --- 方向 B:探讨现有架构的安全加固方案 ---
# 基于同一个 session_id 再次分叉,确保两个方向完全独立
async for message in query(
    prompt="如果保持现有架构,应如何加固安全性?",
    options=options_fork,
):
    ...

6 自定义工具:扩展Claude的能力边界

  • Agent SDK中的自定义工具实质上是进程内MCP服务器。

6.1 使用@tool装饰器定义工具

点击查看代码
import json

from claude_agent_sdk import tool, create_sdk_mcp_server


# === 工具 1:数据库查询(只读) ===
@tool(
    name="query_database",
    description="Execute a read-only SQL query on the application database",
    parameters={
        "query": str,
        "limit": int,
    },
)
async def query_database(args):
    sql = args["query"]
    limit = args.get("limit", 100)

    # 【安全关键】强制校验:仅允许 SELECT 语句
    if not sql.strip().upper().startswith("SELECT"):
        return {
            "content": [{"type": "text", "text": "Error: Only SELECT queries allowed"}],
            "isError": True,
        }

    results = await db.execute(f"{sql} LIMIT {limit}")
    return {
        "content": [{"type": "text", "text": json.dumps(results, indent=2)}],
    }


# === 工具 2:发送通知 ===
@tool(
    name="send_notification",
    description="Send a notification to the team Slack channel",
    parameters={
        "channel": str,
        "message": str,
    },
)
async def send_notification(args):
    await slack.post_message(args["channel"], args["message"])
    return {
        "content": [{"type": "text", "text": f"Notification sent to #{args['channel']}"}],
    }


# === 创建 MCP 服务器承载这些工具 ===
tools_server = create_sdk_mcp_server(
    name="app-tools",
    version="1.0.0",
    tools=[query_database, send_notification],
)

6.2 在Agent配置中注册并启用自定义工具

点击查看代码
options = ClaudeAgentOptions(
    mcp_servers={
        "app-tools": tools_server,
    },
    allowed_tools=[
        # 内置工具
        "Read",
        "Grep",
        "Glob",
        # 自定义 MCP 工具
        "mcp__app-tools__query_database",
        "mcp__app-tools__send_notification",
    ],
)

6.3 使用Pydantic模型进行参数验证

点击查看代码
from pydantic import BaseModel, Field
from claude_agent_sdk import tool


# === 定义结构化参数模型 ===
class DatabaseQueryParams(BaseModel):
    table: str = Field(
        ...,
        description="Table name",
    )
    columns: list[str] = Field(
        default=["*"],
        description="Columns to select",
    )
    where: str | None = Field(
        default=None,
        description="SQL WHERE clause condition (optional)",
    )
    limit: int = Field(
        default=100,
        ge=1,
        le=1000,
        description="Maximum number of rows to return",
    )


# === 将模型直接作为工具参数定义 ===
@tool(
    name="safe_query",
    description="Execute a safe, parameterized database query",
    parameters=DatabaseQueryParams,
)
async def safe_query(args: DatabaseQueryParams):
    # args 已经通过 Pydantic 模型验证,类型安全
    ...
posted @ 2026-08-04 11:27  不知者buwei  阅读(0)  评论(0)    收藏  举报