跳到正文
sobolewski.pro今日 AI,每晚送达订阅

每天一封,一键即可退订。 隐私政策

如何构建AI智能体:用 Python 和 Claude Agent SDK 一步步实现

如何构建AI智能体,让它自己读代码、修 bug?本文一步步安装 Claude Agent SDK,编写第一个智能体,再加上自定义工具和 MCP。

4 分钟阅读

本文的其他语言版本:العربيةDeutschEnglishEspañolFrançaisItaliano日本語Polski

本文内容
  1. 从开发者的角度看,AI 智能体是什么?
  2. 第 1 步:如何安装 Claude Agent SDK?
  3. 第 2 步:如何设置 API 密钥?
  4. 第 3 步:如何编写第一个 AI 智能体?
  5. 第 4 步:如何设定智能体能自己做什么?
  6. 第 5 步:如何给智能体加上自定义工具?
  7. 第 6 步:如何把智能体连接到 MCP 服务器?
  8. 第一个智能体之后做什么?
  9. 需要注意什么?
  10. 常见问题

如何构建AI智能体,又不必从零写整个循环?我知道的最短路径是 Claude Agent SDK。这是一个面向 Python 和 TypeScript 的库,提供的工具、智能体循环和上下文管理,和 Claude Code 底层用的完全一样。我们只写十几行代码,智能体就能自己读文件、修 bug、运行命令。

在这篇教程里,我们用 Python 搭建第一个智能体,配置它的权限,再给它加上自定义工具和 MCP 服务器。所有命令和代码片段都来自 Agent SDK 官方快速入门,以及文中链接的文档页面。

从开发者的角度看,AI 智能体是什么?

按照文档的说法,智能体是一种应用:它自己规划接下来的步骤并调用工具来完成任务,比如读文件、运行命令或修改代码。不涉及代码的整体介绍,我在什么是 AI 智能体里写过。

对开发者来说,最关键的是循环:模型思考,调用工具,查看结果,再决定下一步。Agent SDK 接管了这个循环,以及工具执行、上下文管理和重试,我们只需要读取消息流。

文档把使用 Claude 的方式分成四种:

  1. Agent SDK:在我们自己的应用里运行 Claude Code 智能体的库(运行在我们自己管理的进程中),
  2. Claude Code CLI:用于日常交互式工作的终端(详见我的 Claude Code 教程),
  3. Client SDK:直接访问 Claude API,工具循环要自己写(或者交给测试版的“tool runner”),
  4. Managed Agents:由 Anthropic 托管、通过 API 配置的智能体。

本教程讲的是第一种。

第 1 步:如何安装 Claude Agent SDK?

需要 Python 3.10+(TypeScript 则需要 Node.js 18.14+)和一个 Claude Console 账号。先创建项目文件夹:

mkdir my-agent
cd my-agent

默认情况下,智能体可以访问这个目录及其子目录中的文件。文档推荐使用包管理器 uv:

uv init
uv add claude-agent-sdk

用普通的 pip(macOS 和 Linux)是这样:

python3 -m venv .venv
source .venv/bin/activate
pip install claude-agent-sdk

有意思的是,通常不需要单独安装 Claude Code:两个 SDK 都自带 Claude Code 的原生二进制文件。例外是没有预编译包的平台,比如 Windows ARM64 (这时手动安装 Claude Code,SDK 会在 PATH 里找到它)。

第 2 步:如何设置 API 密钥?

在 Claude Console 创建密钥,然后在运行智能体的终端里把它设为环境变量:

export ANTHROPIC_API_KEY=your-api-key

SDK 不会自动加载 .env 文件,所以如果把密钥放在 .env 里,需要自己加载(比如用 dotenv 包)。除了 Anthropic 密钥,也可以通过设置相应的变量来使用 Amazon Bedrock、Claude Platform on AWS、Google Cloud 或 Microsoft Foundry,例如 CLAUDE_CODE_USE_BEDROCK=1。

文档里有一条限制:未经事先批准,Anthropic 不允许基于 Agent SDK 构建的产品提供 claude.ai 账号登录,也不允许使用订阅额度。智能体靠 API 密钥运行,按 token 付费(怎么追踪用量,我在 Claude API 成本一文中写过)。

第 3 步:如何编写第一个 AI 智能体?

快速入门里的例子是一个查找并修复代码 bug 的智能体。先创建一个故意带两个 bug 的 utils.py:

def calculate_average(numbers):
    total = 0
    for num in numbers:
        total += num
    return total / len(numbers)


def get_user_name(user):
    return user["name"].upper()

calculate_average([]) 会因除以零而崩溃,get_user_name(None) 会抛出 TypeError。接下来是智能体本身,也就是 agent.py:

import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, ResultMessage


async def main():
    # Agentic loop: streams messages as Claude works
    async for message in query(
        prompt="Review utils.py for bugs that would cause crashes. Fix any issues you find.",
        options=ClaudeAgentOptions(
            allowed_tools=["Read", "Edit", "Glob"],  # Auto-approve these tools
            permission_mode="acceptEdits",  # Auto-approve file edits
        ),
    ):
        # Print human-readable output
        if isinstance(message, AssistantMessage):
            for block in message.content:
                if hasattr(block, "text"):
                    print(block.text)  # Claude's reasoning
                elif hasattr(block, "name"):
                    print(f"Tool: {block.name}")  # Tool being called
        elif isinstance(message, ResultMessage):
            print(f"Done: {message.subtype}")  # Final result


asyncio.run(main())

这段代码有三部分:

  1. query 创建智能体循环,返回一个异步迭代器,所以用 async for 实时读取消息,
  2. prompt 是任务。用哪些工具由 Claude 自己决定,
  3. options 是配置:这里 allowed_tools 预先批准了 Read、Edit 和 Glob,permission_mode="acceptEdits" 会自动接受文件修改。

运行:

uv run agent.py

(或在已激活的 venv 中运行 python agent.py)。智能体会输出它的推理过程和每次调用的工具,最后打印 Done: success。完成后,utils.py 里已经处理了空列表和用户缺失的情况。智能体自己读了文件、找到了边界情况并修好了代码,而我们没写一行处理工具的函数。

如果看到 Not logged in 或 Invalid API key,几乎可以肯定是这个终端里没有设置 ANTHROPIC_API_KEY 变量。

第 4 步:如何设定智能体能自己做什么?

智能体能做什么,由工具决定。文档给出了三种典型组合:

  1. Read、Glob、Grep:只做分析,不修改文件,
  2. Read、Edit、Glob:分析加修改代码,
  3. Read、Edit、Bash、Glob、Grep:带终端命令的完全自动化。

比如想让智能体搜索网页或运行测试,只需加一个工具并修改提示词:

options = ClaudeAgentOptions(
    allowed_tools=["Read", "Edit", "Glob", "Bash"], permission_mode="acceptEdits"
)

启用 Bash 后,快速入门建议的任务是“Write unit tests for utils.py, run them, and fix any failures”。还可以通过 system_prompt 给智能体设定角色,比如一位遵守 PEP 8 的资深 Python 开发者。

第二个杠杆是权限模式(permission_mode):

  1. "default" 把每个未批准的调用交给我们的 canUseTool 函数,没有这个函数就拒绝,
  2. "acceptEdits" 接受文件修改,以及工作目录中 mkdir、mv 之类的简单命令,
  3. "plan" 让智能体先研究代码、制定计划,
  4. "dontAsk" 从不询问:只运行预先批准的内容,其余一律拒绝(适合没人守在键盘前的智能体),
  5. "auto" 让每个操作都经过一个分类器,由它逐一审查并决定拦截或放行,
  6. "bypassPermissions" 不经询问执行一切,按文档的说法只适用于隔离环境,比如 CI 或容器。

文档里的黄金法则:开发机上用 "acceptEdits","bypassPermissions" 只用在智能体无法破坏任何重要东西的地方。为什么这很重要,可以看我写的 AI 智能体安全指南。

最好一开始就设好上限:max_turns 限制轮数,max_budget_usd 在估算成本超出时停止循环。没有它们,智能体会一直运行到它自己认为完成为止,碰上“改进这个项目”这类开放式任务,可能要跑很久 ;)

第 5 步:如何给智能体加上自定义工具?

内置工具只是开始。自定义工具用装饰器 @tool 定义(名称、描述、输入模式和函数),然后封装进一个在同一进程中运行的 MCP 服务器。文档的例子从 Open-Meteo API 获取气温,所以先添加 httpx 库:

uv add httpx

工具定义:

from typing import Annotated, Any
import httpx
from claude_agent_sdk import tool, create_sdk_mcp_server


# Define a tool: name, description, input schema, handler
@tool(
    "get_temperature",
    "Get the current temperature at a location",
    {
        "latitude": Annotated[float, "Latitude coordinate"],
        "longitude": Annotated[float, "Longitude coordinate"],
    },
)
async def get_temperature(args: dict[str, Any]) -> dict[str, Any]:
    async with httpx.AsyncClient() as client:
        response = await client.get(
            "https://api.open-meteo.com/v1/forecast",
            params={
                "latitude": args["latitude"],
                "longitude": args["longitude"],
                "current": "temperature_2m",
                "temperature_unit": "fahrenheit",
            },
        )
        data = response.json()

    # Return a content array - Claude sees this as the tool result
    return {
        "content": [
            {
                "type": "text",
                "text": f"Temperature: {data['current']['temperature_2m']}°F",
            }
        ]
    }


# Wrap the tool in an in-process MCP server
weather_server = create_sdk_mcp_server(
    name="weather",
    version="1.0.0",
    tools=[get_temperature],
)

在同一个文件里,把服务器传给智能体。工具的完整名称格式是 mcp__{服务器}__{工具},把它写进 allowed_tools,工具就能在不请求许可的情况下运行:

import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage


async def main():
    options = ClaudeAgentOptions(
        mcp_servers={"weather": weather_server},
        allowed_tools=["mcp__weather__get_temperature"],
    )

    async for message in query(
        prompt="What's the temperature in San Francisco?",
        options=options,
    ):
        # ResultMessage is the final message after all tool calls complete
        if isinstance(message, ResultMessage) and message.subtype == "success":
            print(message.result)


asyncio.run(main())

智能体会调用我们的工具,并根据结果作答。把天气换成任何东西都行:我们的数据库、内部 API 或某个脚本。

第 6 步:如何把智能体连接到 MCP 服务器?

现成的 MCP 服务器(协议本身我在什么是 MCP 里介绍过)在 mcp_servers 选项中配置。文档里的例子通过 HTTP 把智能体连到 Claude Code 的远程文档服务器:

options = ClaudeAgentOptions(
    mcp_servers={
        "claude-code-docs": {
            "type": "http",
            "url": "https://code.claude.com/docs/mcp",
        }
    },
    allowed_tools=["mcp__claude-code-docs__*"],
)

allowed_tools 中的星号会批准该服务器的所有工具。给出提示词“Use the docs MCP server to explain what hooks are in Claude Code”,智能体就会检索文档并返回答案。

第一个智能体之后做什么?

Agent SDK 还具备 Claude Code 的其他功能:

  1. hooks:在工具调用之前或之后运行的自定义代码,
  2. 子智能体,用于拆分出来的子任务,
  3. 会话:用 ResultMessage.session_id 中的 ID 可以带着完整上下文恢复对话,或者分叉出新对话,
  4. 技能、命令和记忆,和 Claude Code 一样从 .claude/ 目录加载。

现成的示例应用(包括邮件助手和研究型智能体)在 claude-agent-sdk-demos 仓库里。

需要注意什么?

第一,成本。上下文每一轮都在增长,一个大文件或输出很多的命令一下子就能吃掉几千个 token。固定部分(系统提示词、工具定义)会自动缓存,但还是建议从第一天就设置 max_budget_usd (上限可能会被超出一次回复的成本,所以留点余量)。

第二,权限。在普通笔记本电脑上给智能体 Bash 加 bypassPermissions,等于自找麻烦,完全自动化还是留给容器吧。

第三,品牌。按照文档,基于 SDK 构建的产品可以叫“Claude Agent”或“ Powered by Claude”,但不能叫“Claude Code”,也不能冒充 Anthropic 的产品。

常见问题

如何构建AI智能体,而不用从零写循环?

最简单的办法是用一个已经内置循环的库,比如 Claude Agent SDK。安装 claude-agent-sdk,设置 ANTHROPIC_API_KEY,再用提示词和允许的工具列表调用 query()。剩下的工作,也就是调用工具和管理上下文,都由 SDK 完成。

Claude Agent SDK 免费吗?

库本身不收费,但智能体使用 Claude API,所以要为消耗的 token 付费。未经 Anthropic 批准,不能把它接到 claude.ai 订阅上。

Agent SDK 和 Claude API 有什么区别?

用普通的 Client SDK(Claude API)时,工具循环要自己写,或者使用测试版的 tool runner。Agent SDK 自带 Claude Code 的内置工具(读写文件、执行命令、网页搜索),以及权限、会话和 hooks。

能用 TypeScript 写智能体吗?

可以。包名是 @anthropic-ai/claude-agent-sdk,需要 Node.js 18.14+。在文档的示例中,选项名称和 Python 一样,只是改用 camelCase(allowedTools、permissionMode)。

  • AI
  • AI 智能体
  • Claude
  • 编程
  • 教程

今日 AI,每晚送达

每晚送上当天最重要的 AI 新闻和博客新文章。简明扼要,附有来源。

每天一封,一键即可退订。 隐私政策