1. 引言:不追框架,先懂思想

AI Agent(智能体)是近两年大模型应用领域最热的关键词之一。但很多入门教程一上来就甩出 LangChain、AutoGPT、AgentScope 等重量级框架,学习曲线陡峭,反而让人看不清 Agent 的本质。

这篇文章想做的,是剥掉框架的外壳,用几十行纯 Python 代码讲清楚 Agent 的核心思想:大模型不只是"说话",而是会思考、决策、调用工具,最后形成完整闭环。

读完你会发现,Agent 并没有那么神秘——它本质上就是"大模型 + 工具调用 + 循环反馈"的组合拳。

2. Agent 的核心思想:思考、决策、调用工具

2.1 普通大模型在做什么

当我们用 ChatGPT 这类产品提问时,对话流程大致是:

  • 用户输入问题
  • 大模型基于训练数据和上下文直接生成回答
  • 返回结果

这个过程本质上是一个单次推理:模型只能"凭记忆"回答。遇到需要实时数据、私有数据或执行具体操作的任务时,它就会捉襟见肘。

2.2 Agent 增加了什么

Agent 在"大模型"外面包了一层行动能力。它的核心循环可以拆成三个环节:

  1. 思考(Reason):大模型理解用户意图,判断"这个问题我能不能直接回答?"
  2. 决策(Decide):如果不能直接回答,它决定"我需要调用哪个工具、传什么参数"
  3. 调用工具(Act):执行工具获取外部信息或完成操作,然后把结果反馈给大模型,由它整合生成最终回复

这个闭环可以反复进行,直到大模型认为信息足够、可以给出最终答案为止。

下面是 Agent 的完整工作流程图:

是

否

用户提问

大模型思考

需要调用工具?

生成工具调用指令

执行工具获取信息

把结果反馈给大模型

直接生成最终回复

返回答案给用户

图中的关键在闭环:工具结果会再次进入大模型,形成"思考 → 调用 → 反馈 → 再思考"的循环,而不是一次就结束。

3. Agent 与普通对话机器人的区别

理解二者差异,是入门 Agent 的关键一步。下面这张对比图可以帮你快速建立认知:

AI Agent

是

否

用户提问

大模型思考

需要工具?

调用工具获取实时/外部信息

把结果反馈给大模型

生成最终答案

普通对话机器人

用户提问

大模型直接生成答案

返回答案

具体差异可以归纳为三点:

对比维度普通对话机器人AI Agent
信息范围仅凭模型参数记忆可访问实时数据、私有系统
执行能力只能"说",不能"做"可调用 API、查库、操作文件
推理模式单次推理直接输出多轮循环,直到任务完成

一句话总结:对话机器人是"只会说",Agent 是"既会想,也会做"。

4. 极简 Demo:用 Python 实现工具调用智能体

下面我们动手写一个最小可运行的 Agent。它不依赖任何 Agent 框架,只用 requests 直接调用 OpenAI 兼容接口,核心逻辑不到 60 行。

4.1 整体设计

我们的 Agent 只有一个工具:get_weather(查天气)。场景是:

  • 用户问"北京今天天气怎么样?"
  • 大模型发现自己不知道实时天气,于是决定调用 get_weather 工具
  • 工具返回结果后,大模型整合信息,生成自然语言回复

4.2 完整代码

import json
import requests
from typing import Optional

# ========== 配置区 ==========
API_URL = "https://api.openai.com/v1/chat/completions"
API_KEY = "你的-API-Key"
MODEL = "gpt-4o-mini"  # 或任何支持 function calling 的模型

# ========== 定义工具 ==========
# 工具列表会直接告诉大模型:"我有这些能力,你可以按需调用"
TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "获取指定城市的实时天气信息",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "城市名称,例如:北京"
                    }
                },
                "required": ["city"]
            }
        }
    }
]


def get_weather(city: str) -> str:
    """本地工具函数:模拟天气查询(实际场景可替换为真实 API)"""
    fake_db = {
        "北京": "晴,25°C,空气质量优",
        "上海": "多云,28°C,东南风 3 级",
        "广州": "雷阵雨,30°C,湿度较大",
    }
    return fake_db.get(city, "晴转多云,23°C")


def call_llm(messages: list[dict], tools: Optional[list] = None) -> dict:
    """调用大模型,messages 为对话历史,tools 为可选工具列表"""
    headers = {
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
    }
    payload = {
        "model": MODEL,
        "messages": messages,
    }
    if tools:
        payload["tools"] = tools
        payload["tool_choice"] = "auto"  # 让模型自己决定是否调用工具

    resp = requests.post(API_URL, headers=headers, json=payload, timeout=60)
    resp.raise_for_status()
    return resp.json()


def run_agent(user_question: str) -> str:
    """
    Agent 主循环:
    1. 大模型思考用户问题
    2. 大模型决策:是否调用工具
    3. 若调用,执行工具并把结果反馈给大模型
    4. 大模型基于工具结果生成最终回复
    """
    messages = [{"role": "user", "content": user_question}]

    # ---- 第一轮:让大模型思考并决策 ----
    response = call_llm(messages, tools=TOOLS)
    message = response["choices"][0]["message"]

    # 如果大模型决定调用工具
    if message.get("tool_calls"):
        # 把大模型的工具调用请求追加到对话历史
        messages.append(message)

        for tool_call in message["tool_calls"]:
            func_name = tool_call["function"]["name"]
            args = json.loads(tool_call["function"]["arguments"])

            # 执行对应的本地工具
            if func_name == "get_weather":
                result = get_weather(args["city"])
            else:
                result = f"未知工具:{func_name}"

            # 把工具执行结果反馈给大模型
            messages.append({
                "role": "tool",
                "tool_call_id": tool_call["id"],
                "content": result,
            })

        # ---- 第二轮:大模型基于工具结果生成最终回复 ----
        response = call_llm(messages)
        return response["choices"][0]["message"]["content"]

    # 不需要工具时,直接返回第一轮的回答
    return message["content"]


if __name__ == "__main__":
    # 测试 1:需要调用工具的问题
    print("Q: 北京今天天气怎么样?")
    print("A:", run_agent("北京今天天气怎么样?"))
    print("-" * 50)

    # 测试 2:不需要工具的问题
    print("Q: 用一句话解释什么是人工智能?")
    print("A:", run_agent("用一句话解释什么是人工智能?"))

4.3 代码解读:三个关键点

第一,工具以结构化方式"声明"给大模型。 TOOLS 列表用 JSON Schema 描述了工具名称、用途和参数,大模型就是通过这份描述来理解"我什么时候该调它、传什么参数"。

第二,tool_choice 设为 "auto"。 这表示把决策权交给模型:它自己判断要不要调工具。这正是 Agent "决策"能力的体现。

第三,工具结果必须"喂回去"。 很多初学者容易漏掉这一步——调完工具就结束了。实际上,工具返回的结果要作为一条 role: "tool" 的消息追加回对话历史,再让大模型进行第二轮推理,它才能把"北京 25°C"这种原始数据转化为"北京今天晴朗,气温 25°C,适合出门"这样的自然语言回复。

4.4 运行效果预期

第一个问题会触发工具调用,Agent 返回类似:

北京今天天气晴朗,气温 25°C,空气质量优,适合户外活动。

第二个问题不需要工具,Agent 直接回答:

人工智能是让计算机系统模拟人类智能、完成学习与推理任务的技术。

5. 当前轻量 Agent 的局限性

这个 Demo 足够轻量、易理解,但它也诚实地暴露了轻量 Agent 的边界。了解这些局限,才能在实际项目中做出合理的技术选型。

5.1 单轮调用为主,难以处理复杂任务

我们的实现中,工具调用只走了一个循环。真实场景里,一个任务往往需要多轮、多工具协作,比如"先查用户信息 → 再查订单 → 最后生成报告"。这需要引入更复杂的状态管理和任务规划能力。

5.2 缺少记忆与上下文管理

Demo 没有持久化记忆。每次运行 run_agent 都是全新的对话。要让 Agent 记住"用户偏好、历史对话",需要额外的存储和检索方案。

5.3 没有错误处理与重试机制

工具执行失败、返回异常、参数错误等情况,Demo 都未处理。生产级 Agent 需要设计兜底策略:工具失败时要不要重试?要不要降级为"直接回答"?

5.4 安全性几乎为零

让大模型自由调用工具存在风险:它可能调用不该调用的接口、泄露敏感数据。真实系统必须加权限控制(白名单、鉴权)和人工确认环节。

5.5 没有并行与性能优化

当需要调用多个独立工具时,轻量实现是串行执行的。高效率 Agent 会考虑并行调用、结果聚合等优化手段。

小结:轻量 Agent 的价值在于帮助理解原理、快速验证想法。当需求变得复杂时,再引入成熟框架去解决工程化问题,是更务实的路径。

6. 总结

Agent 的核心并不神秘,本质上是一个循环:

思考 → 决策 → 调用工具 → 反馈 → 再思考

用几十行 Python 就能把这个闭环跑通。相比普通对话机器人,Agent 的核心突破在于获得了"行动"的能力——它不再只是回答问题,而是能够获取外部信息、操作真实系统。

建议你亲自动手把这套代码跑起来,然后试着扩展一个新工具(比如查股票、查快递),你会发现:所谓 Agent,不过是把大模型的"嘴",接上了真实世界的"手"。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐