AI Agent 开发完全指南:用 Python 从零构建智能体(2026)

手把手教你用 Python 开发 AI Agent 智能体:从 Function Calling 原理到多工具编排,附完整代码示例。覆盖 GPT、Claude、Gemini 等主流模型的 Tool Use 实现,以及生产环境部署的最佳实践。

AI Agent 开发完全指南:用 Python 从零构建智能体(2026)

摘要

  • AI Agent 的核心能力是 Function Calling(工具调用)——让大模型不只会说,还会做
  • 本文从零实现一个完整的 AI Agent:天气查询 + 数据库检索 + 代码执行,附可直接运行的 Python 代码
  • 覆盖 OpenAI、Claude、Gemini 三大模型的 Tool Use 实现方式,代码可直接复用
  • 生产环境要点:错误处理、多轮工具调用、并行调用、安全防护,一次讲透

什么是 AI Agent?从 ChatBot 到智能体的进化

2026 年,AI Agent 已经从「能调用工具的聊天机器人」进化为「可持续运行的软件系统」。一个成熟的 Agent 可以:

  • 自主规划 多步骤任务并拆解执行
  • 调用外部工具 获取实时数据、操作数据库、执行代码
  • 维持长期记忆 跨会话记住用户偏好和上下文
  • 与其他 Agent 协作 组成多 Agent 系统处理复杂任务
能力维度传统 ChatBotAI Agent
输出形式纯文本回复文本 + 工具调用 + 结构化数据
信息来源仅训练数据训练数据 + 实时 API + 数据库
执行能力可执行代码、调用 API、操作文件
任务复杂度单轮问答多步骤规划与执行
状态管理无状态或短期上下文长期记忆 + 会话管理

这不是概念性的差距——而是能不能帮你干活的差距。

核心原理:Function Calling 如何工作

Function Calling(也叫 Tool Use / Tool Calling)是 AI Agent 的核心引擎。它的工作流程可以用一句话概括:

模型决定调什么工具、传什么参数;你的代码负责执行;结果再喂回模型。

完整的 Agent Loop 是这样运转的:

AI Agent Loop 工作流程

用户输入 → 模型推理 → 是否需要工具?
                         ├─ 否 → 直接回复用户
                         └─ 是 → 输出工具调用指令

                              开发者代码执行工具

                              执行结果返回模型

                              模型继续推理(可能再次调用工具)

                              最终回复用户

每个 Function Calling 实现都需要三个核心组件:

  1. 工具定义(Tool Schema):JSON Schema 格式描述工具的名称、功能和参数
  2. 执行层(Execution Layer):你的代码,负责真正执行工具逻辑
  3. 结果整合(Result Integration):将工具执行结果喂回模型,让它继续推理

环境准备与项目搭建

安装依赖

pip install openai httpx

我们只需要 openai 这一个 SDK——因为所有主流模型(GPT、Claude、Gemini、DeepSeek、Qwen)都兼容 OpenAI 的 API 协议。一套代码,多模型通用。

配置 API

from openai import OpenAI

# 使用 OpenAI 兼容接口,可接入 50+ 模型
client = OpenAI(
    api_key="your-api-key",
    base_url="https://api.ofox.io/v1"  # API 聚合网关,国内低延迟
)

提示:如果你直接用 OpenAI 官方 API,把 base_url 改为 https://api.openai.com/v1 即可。代码逻辑完全不变。

第一个 Agent:天气查询助手

从最经典的案例开始——一个能查天气的 AI Agent。

Step 1:定义工具

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "获取指定城市的当前天气信息,包括温度、湿度和天气状况",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "城市名称,如 '北京'、'上海'、'Tokyo'"
                    },
                    "unit": {
                        "type": "string",
                        "enum": ["celsius", "fahrenheit"],
                        "description": "温度单位,默认摄氏度"
                    }
                },
                "required": ["city"]
            }
        }
    }
]

关键要点description 字段非常重要——模型根据描述决定什么时候调用这个工具。描述越精确,模型的判断越准确。

Step 2:实现工具函数

import httpx
import json

def get_weather(city: str, unit: str = "celsius") -> str:
    """调用天气 API 获取实时数据"""
    # 这里用 wttr.in 作为示例,生产环境建议用付费天气 API
    resp = httpx.get(f"https://wttr.in/{city}?format=j1", timeout=10)
    data = resp.json()

    current = data["current_condition"][0]
    temp = current["temp_C"] if unit == "celsius" else current["temp_F"]
    unit_label = "°C" if unit == "celsius" else "°F"

    return json.dumps({
        "city": city,
        "temperature": f"{temp}{unit_label}",
        "humidity": f"{current['humidity']}%",
        "description": current["weatherDesc"][0]["value"],
        "wind": f"{current['windspeedKmph']} km/h"
    }, ensure_ascii=False)

Step 3:实现 Agent Loop

import json

# 工具函数映射表
TOOL_FUNCTIONS = {
    "get_weather": get_weather,
}

def run_agent(user_message: str):
    """运行 Agent:发送消息 → 处理工具调用 → 返回最终结果"""
    messages = [
        {"role": "system", "content": "你是一个智能天气助手。用自然语言回答用户的天气问题。"},
        {"role": "user", "content": user_message}
    ]

    while True:
        # 1. 调用模型
        response = client.chat.completions.create(
            model="openai/gpt-4.1-mini",  # 也可换成 anthropic/claude-sonnet-4.5、google/gemini-2.5-flash 等
            messages=messages,
            tools=tools,
            tool_choice="auto"
        )

        msg = response.choices[0].message
        messages.append(msg)

        # 2. 如果没有工具调用,说明模型已经给出最终回复
        if not msg.tool_calls:
            return msg.content

        # 3. 执行每个工具调用
        for tool_call in msg.tool_calls:
            func_name = tool_call.function.name
            func_args = json.loads(tool_call.function.arguments)

            print(f"🔧 调用工具: {func_name}({func_args})")

            # 执行工具函数
            result = TOOL_FUNCTIONS[func_name](**func_args)

            # 将结果返回给模型
            messages.append({
                "role": "tool",
                "tool_call_id": tool_call.id,
                "content": result
            })

# 测试
answer = run_agent("北京和东京今天哪个更热?")
print(answer)

运行效果:

🔧 调用工具: get_weather({"city": "北京"})
🔧 调用工具: get_weather({"city": "东京"})
今天北京气温 18°C,东京气温 15°C,北京比东京高 3 度。
北京天气晴朗,东京多云,都适合外出活动。

注意观察:模型自动决定要调用两次天气查询,然后对比分析结果。这就是 Agent 的魅力——它不只是转发数据,而是在推理

进阶:多工具协作的智能 Agent

真实场景中,Agent 通常需要协调多个工具。下面构建一个更复杂的助手——同时具备天气查询、数据库检索和计算能力。

定义多个工具

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "获取指定城市的当前天气",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {"type": "string", "description": "城市名称"}
                },
                "required": ["city"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "search_database",
            "description": "搜索产品数据库,返回符合条件的产品列表",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {"type": "string", "description": "搜索关键词"},
                    "category": {
                        "type": "string",
                        "enum": ["electronics", "clothing", "food", "books"],
                        "description": "产品分类"
                    },
                    "max_results": {
                        "type": "integer",
                        "description": "最大返回数量,默认 5"
                    }
                },
                "required": ["query"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "calculate",
            "description": "执行数学计算,支持四则运算、百分比、汇率换算等",
            "parameters": {
                "type": "object",
                "properties": {
                    "expression": {
                        "type": "string",
                        "description": "数学表达式,如 '100 * 0.85' 或 '1999 * 3 + 500'"
                    }
                },
                "required": ["expression"]
            }
        }
    }
]

实现工具函数

def search_database(query: str, category: str = None, max_results: int = 5) -> str:
    """模拟数据库搜索(实际项目中连接真实数据库)"""
    # 模拟数据
    products = [
        {"name": "MacBook Pro 16", "price": 18999, "category": "electronics", "stock": 50},
        {"name": "iPhone 16 Pro", "price": 8999, "category": "electronics", "stock": 200},
        {"name": "AirPods Pro 3", "price": 1899, "category": "electronics", "stock": 500},
        {"name": "Python 编程指南", "price": 89, "category": "books", "stock": 1000},
    ]

    results = [p for p in products if query.lower() in p["name"].lower()
               or (category and p["category"] == category)]

    return json.dumps(results[:max_results], ensure_ascii=False)


def calculate(expression: str) -> str:
    """安全的数学计算(仅允许数字和基本运算符)"""
    import ast
    import operator

    # 使用 ast.literal_eval 的安全替代方案
    allowed_operators = {
        ast.Add: operator.add,
        ast.Sub: operator.sub,
        ast.Mult: operator.mul,
        ast.Div: operator.truediv,
        ast.Mod: operator.mod,
        ast.Pow: operator.pow,
        ast.USub: operator.neg,
    }

    def safe_eval(node):
        if isinstance(node, ast.Expression):
            return safe_eval(node.body)
        elif isinstance(node, ast.Constant) and isinstance(node.value, (int, float)):
            return node.value
        elif isinstance(node, ast.BinOp) and type(node.op) in allowed_operators:
            left = safe_eval(node.left)
            right = safe_eval(node.right)
            return allowed_operators[type(node.op)](left, right)
        elif isinstance(node, ast.UnaryOp) and type(node.op) in allowed_operators:
            return allowed_operators[type(node.op)](safe_eval(node.operand))
        else:
            raise ValueError(f"不支持的表达式")

    try:
        tree = ast.parse(expression, mode="eval")
        result = safe_eval(tree)
        return json.dumps({"expression": expression, "result": result})
    except Exception as e:
        return json.dumps({"error": str(e)})


# 更新工具映射
TOOL_FUNCTIONS = {
    "get_weather": get_weather,
    "search_database": search_database,
    "calculate": calculate,
}

实战:多工具协作

answer = run_agent("帮我查一下电子产品里有哪些苹果设备,算算买一台 MacBook Pro 和一副 AirPods 总共多少钱")
print(answer)
🔧 调用工具: search_database({"query": "Mac", "category": "electronics"})
🔧 调用工具: search_database({"query": "AirPods", "category": "electronics"})
🔧 调用工具: calculate({"expression": "18999 + 1899"})

查到两款苹果设备:
- MacBook Pro 16:18,999 元(库存 50 台)
- AirPods Pro 3:1,899 元(库存 500 副)

两件合计 **20,898 元**。如果你需要下单或了解更多配置信息,随时告诉我。

模型自动编排了三次工具调用:两次搜索 + 一次计算。这种多工具协作是 Agent 的核心价值。

三大模型 Function Calling 对比实测

2026 年主流模型在 Function Calling 能力上各有所长。以下是基于实际测试的对比:

对比维度GPT-5.x 系列Claude Opus/Sonnet 4.xGemini 3.1 Pro
Tool Use 准确率⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
并行工具调用支持支持支持(最强)
复杂推理后调用最强
超长上下文 Tool Use128K200K2M(碾压)
API 协议OpenAI 原生OpenAI 兼容OpenAI 兼容
全球直连需聚合网关需聚合网关需聚合网关

代码层面的差异

好消息是,如果你使用 OpenAI 兼容接口,三个模型的代码完全一样——只需要换 model 参数:

# GPT-5.4
response = client.chat.completions.create(model="openai/gpt-5.4", messages=messages, tools=tools)

# Claude Sonnet 4.6
response = client.chat.completions.create(model="anthropic/claude-sonnet-4.6", messages=messages, tools=tools)

# Gemini 3.1 Pro
response = client.chat.completions.create(model="google/gemini-3.1-pro", messages=messages, tools=tools)

通过 API 聚合网关(如 Ofox),用同一个 API Key 即可调用所有模型,无需管理多套密钥。

模型选择建议

  • 通用 Agent 开发GPT-4.1-miniClaude Sonnet 4.6(性价比最高)
  • 复杂推理 AgentClaude Opus 4.6 或 Gemini 3.1 Pro
  • 超长文档处理:Gemini 3.1 Pro(2M 上下文)
  • 预算敏感:DeepSeek V3 或 GPT-4.1-nano

生产环境最佳实践

从 demo 到生产,还有几个关键问题需要处理。

1. 错误处理与重试

def run_agent_production(user_message: str, max_rounds: int = 10):
    """生产级 Agent Loop,带错误处理和轮次限制"""
    messages = [
        {"role": "system", "content": "你是一个智能助手。如果工具调用失败,告诉用户原因并建议替代方案。"},
        {"role": "user", "content": user_message}
    ]

    for round_num in range(max_rounds):
        try:
            response = client.chat.completions.create(
                model="openai/gpt-4.1-mini",
                messages=messages,
                tools=tools,
                tool_choice="auto",
                timeout=30
            )
        except Exception as e:
            return f"API 调用失败:{e}"

        msg = response.choices[0].message
        messages.append(msg)

        if not msg.tool_calls:
            return msg.content

        for tool_call in msg.tool_calls:
            func_name = tool_call.function.name
            try:
                func_args = json.loads(tool_call.function.arguments)
                func = TOOL_FUNCTIONS.get(func_name)

                if not func:
                    result = json.dumps({"error": f"未知工具: {func_name}"})
                else:
                    result = func(**func_args)

            except json.JSONDecodeError:
                result = json.dumps({"error": "参数解析失败"})
            except Exception as e:
                result = json.dumps({"error": f"工具执行失败: {str(e)}"})

            messages.append({
                "role": "tool",
                "tool_call_id": tool_call.id,
                "content": result
            })

    return "Agent 达到最大执行轮次,请简化你的问题后重试。"

2. 安全防护

Agent 能调用工具意味着它能产生副作用。务必做好安全防护:

# 工具权限控制
TOOL_PERMISSIONS = {
    "get_weather": {"level": "read", "rate_limit": 60},     # 只读,每分钟 60 次
    "search_database": {"level": "read", "rate_limit": 30},  # 只读
    "calculate": {"level": "compute", "rate_limit": 100},    # 计算
    "send_email": {"level": "write", "require_confirm": True}, # 写操作需确认
    "delete_record": {"level": "dangerous", "require_confirm": True}, # 危险操作需确认
}

def execute_tool_safely(func_name: str, func_args: dict) -> str:
    """安全执行工具,带权限检查"""
    perm = TOOL_PERMISSIONS.get(func_name)
    if not perm:
        return json.dumps({"error": "未授权的工具"})

    # 危险操作需要人工确认(生产环境可接入审批系统)
    if perm.get("require_confirm"):
        print(f"⚠️ 高风险操作: {func_name}({func_args})")
        # 在 Web 应用中可以弹出确认对话框
        # confirm = await get_user_confirmation(func_name, func_args)
        return json.dumps({"error": "此操作需要人工确认,已发送审批请求"})

    return TOOL_FUNCTIONS[func_name](**func_args)

3. 流式输出 + 工具调用

生产环境中,流式输出能显著提升用户体验:

def run_agent_streaming(user_message: str):
    """流式输出的 Agent"""
    messages = [
        {"role": "system", "content": "你是一个智能助手。"},
        {"role": "user", "content": user_message}
    ]

    while True:
        stream = client.chat.completions.create(
            model="openai/gpt-4.1-mini",
            messages=messages,
            tools=tools,
            stream=True
        )

        tool_calls_buffer = {}
        content_buffer = ""

        for chunk in stream:
            delta = chunk.choices[0].delta

            # 文本内容:实时输出
            if delta.content:
                print(delta.content, end="", flush=True)
                content_buffer += delta.content

            # 工具调用:收集完整调用信息
            if delta.tool_calls:
                for tc in delta.tool_calls:
                    idx = tc.index
                    if idx not in tool_calls_buffer:
                        tool_calls_buffer[idx] = {
                            "id": tc.id or "",
                            "name": "",
                            "arguments": ""
                        }
                    if tc.id:
                        tool_calls_buffer[idx]["id"] = tc.id
                    if tc.function and tc.function.name:
                        tool_calls_buffer[idx]["name"] = tc.function.name
                    if tc.function and tc.function.arguments:
                        tool_calls_buffer[idx]["arguments"] += tc.function.arguments

        # 如果没有工具调用,返回文本内容
        if not tool_calls_buffer:
            print()  # 换行
            return content_buffer

        # 执行工具调用并将结果加入 messages(同前面的逻辑)
        assistant_msg = {"role": "assistant", "content": content_buffer or None, "tool_calls": []}
        for idx in sorted(tool_calls_buffer.keys()):
            tc = tool_calls_buffer[idx]
            assistant_msg["tool_calls"].append({
                "id": tc["id"],
                "type": "function",
                "function": {"name": tc["name"], "arguments": tc["arguments"]}
            })
        messages.append(assistant_msg)

        for idx in sorted(tool_calls_buffer.keys()):
            tc = tool_calls_buffer[idx]
            func_args = json.loads(tc["arguments"])
            result = TOOL_FUNCTIONS[tc["name"]](**func_args)
            messages.append({
                "role": "tool",
                "tool_call_id": tc["id"],
                "content": result
            })

4. 对话记忆管理

长期运行的 Agent 需要管理上下文窗口:

def manage_context(messages: list, max_tokens: int = 8000) -> list:
    """上下文窗口管理:保留系统提示和最近的对话"""
    # 粗略估算 token 数(中文约 1.5 token/字)
    estimated_tokens = sum(len(m.get("content", "") or "") * 1.5 for m in messages)

    if estimated_tokens <= max_tokens:
        return messages

    # 保留 system 消息和最近的对话
    system_msgs = [m for m in messages if m.get("role") == "system"]
    other_msgs = [m for m in messages if m.get("role") != "system"]

    # 从最近的消息开始保留
    kept = []
    current_tokens = sum(len(m.get("content", "") or "") * 1.5 for m in system_msgs)

    for msg in reversed(other_msgs):
        msg_tokens = len(msg.get("content", "") or "") * 1.5
        if current_tokens + msg_tokens > max_tokens:
            break
        kept.insert(0, msg)
        current_tokens += msg_tokens

    return system_msgs + kept

常见问题(FAQ)

Q: AI Agent 开发需要 GPU 吗?

A: 不需要。AI Agent 开发是纯工程开发——你通过 API 调用云端的大模型,本地只需要一台普通电脑和 Python 环境。模型推理的算力由 API 服务商提供。

Q: 一个 AI Agent 调用多少工具比较合适?

A: 建议单个 Agent 控制在 5-15 个工具。工具太少则能力有限,工具太多模型选择准确率会下降。如果需要更多能力,可以拆分成多个专业 Agent 协作。

Q: Function Calling 的参数校验怎么做?

A: 推荐使用 Pydantic 做参数校验。把工具的参数定义为 Pydantic Model,自动生成 JSON Schema 并校验输入:

from pydantic import BaseModel, Field

class WeatherParams(BaseModel):
    city: str = Field(description="城市名称")
    unit: str = Field(default="celsius", description="温度单位")

# 自动生成 JSON Schema
schema = WeatherParams.model_json_schema()

Q: AI Agent 每次 API 调用的成本大概多少?

A: 以 GPT-4.1-mini 为例,输入 $0.4/百万 token,输出 $1.6/百万 token。一次典型的 Agent 对话(含 2-3 次工具调用)大约消耗 2000-5000 token,成本约 0.001-0.005 美元。通过 API 聚合平台通常还能获得更优惠的价格。

Q: 如何调试 Function Calling?模型不调用工具怎么办?

A: 三个排查方向:1)检查工具描述是否清晰——模型靠描述决定是否调用;2)在 system prompt 中明确告诉模型可以使用哪些工具;3)使用 tool_choice={"type": "function", "function": {"name": "xxx"}} 强制调用特定工具进行测试。

总结与行动建议

  1. 跑通第一个 Agent:复制本文的天气查询代码,替换 API Key,体验完整的 Agent Loop
  2. 接入你的业务工具:把数据库查询、第三方 API 封装成工具函数
  3. 部署到生产:加上错误处理、权限控制和对话记忆管理

常见问题

AI Agent 和普通 ChatBot 有什么区别?
普通 ChatBot 只能生成文本回复,而 AI Agent 具备自主决策能力——它可以调用外部工具(API、数据库、文件系统)、执行多步骤任务、维持长期记忆,并根据中间结果动态调整策略。简单说,ChatBot 是问答机器,Agent 是能干活的助手。
Function Calling 和 Tool Use 有什么区别?
本质上是同一个概念的不同叫法。OpenAI 最初称之为 Function Calling,后来改为 Tool Use / Tool Calling。Anthropic 和 Google 也使用 Tool Use 这个术语。它们都指模型输出结构化的工具调用指令,由开发者代码执行后将结果返回给模型。
开发 AI Agent 用哪个模型最好?
2026 年主流选择:GPT-5.x 系列综合能力强且生态成熟;Claude Opus 4.6 / Sonnet 4.6 在代码生成和复杂推理上表现出色;Gemini 3.1 Pro 拥有 2M 超长上下文和优秀的多模态能力。建议通过 OpenAI 兼容接口接入,方便随时切换模型。
AI Agent 开发需要什么基础?
需要基础的 Python 编程能力、对 HTTP API 调用有基本了解、理解 JSON 数据格式。不需要深入理解机器学习或深度学习原理——现代 Agent 开发主要是工程问题,不是算法问题。
如何在国内稳定调用海外大模型 API 开发 Agent?
推荐使用兼容 OpenAI 协议的 API 聚合平台,通过全球加速节点稳定低延迟访问,无需额外网络配置。只需将 base_url 改为聚合平台地址,即可用同一套代码调用 GPT、Claude、Gemini 等 50+ 模型。