7AA7 博客

AI Agent 初识:从对话到自主调用工具的距离

Moon 槐 UID:80
2026-10-13 11:50
24 4 1

大模型对话接口本质上是”文本进、文本出”。用户问天气,模型只能给出一段看起来像天气信息的文字,它并不能真的去看一眼气象数据。Agent 想解决的就是这个断层:让模型不仅会说,还会做——查数据库、调接口、读文件、执行脚本,把结果拿回来继续推理。

从”会聊天”到”会做事”,中间隔着的不是模型能力的跃迁,而是一套工程结构。这套结构好不好,决定了 Agent 是稳定工具还是不稳定玩具。

一、Agent 的四个基本构成

一个最小可用的 Agent 循环,通常由四块组成:

        ┌──────────┐
        │   LLM    │ ← 核心推理引擎
        └────┬─────┘
             │ 决定下一步
   ┌─────────┼─────────┐
   ▼         ▼         ▼
 规划      工具       记忆
(拆解任务) (执行动作) (跨轮状态)
  • LLM:负责理解任务、决定下一步做什么、把中间结果组织成结论。
  • 规划(planning):把一个大目标拆成可执行的步骤序列。可以是模型隐式规划(在推理里自然展开),也可以显式要求它先输出计划再执行。
  • 工具(tools):模型能调用的外部能力,比如搜索、计算、API 调用、代码执行。工具是 Agent 与真实世界交互的唯一通道。
  • 记忆(memory):短期是对话历史,长期可以是向量化的笔记、任务状态、用户偏好。没有记忆的 Agent 每次对话都从零开始。

这四块里,真正决定 Agent 可靠性的是工具层和约束层,而不是模型有多聪明。模型再强,工具描述写得含糊、权限放得过宽,系统照样会出问题。

二、ReAct 式循环:思考、行动、观察

目前最广泛使用的 Agent 执行模式是 ReAct(Reason + Act)循环,每一轮包含三个动作:

Thought: 我需要先查一下上周的订单量,才能回答这个问题。
Action:  query_orders(start="2026-10-13", end="2026-10-19")
Observation: {"total": 1284, "amount": 392011}
Thought: 数据拿到了。现在回答用户的问题,需要把订单量和金额都列出来。
Answer: 上周订单总量 1284 笔,金额约 39.2 万。

这个循环的好处是可观测:每一步”想做什么、做了什么、拿到什么”都留痕,出问题时能定位是哪一步断掉。对比”一口气把答案吐出来”的单步模式,ReAct 的调试友好度高出一大截。

工程实现上有两个细节:

  1. 循环要有边界。设定最大步数(比如 5~10 步),超过就强制让模型输出当前已知的结论或失败原因。没有边界的循环是 Agent 失控的常见入口。
  2. Observation 要控制长度。工具返回的原始数据可能很大(比如整张表),要截断或摘要后再塞回上下文,否则几个来回就把窗口吃满了。

三、工具调用的协议要点

Function calling(工具调用)已经形成了大同小异的接口约定:模型在回答里输出一个”要调用哪个工具、参数是什么”的结构化请求,宿主程序执行后把结果以工具消息的形式返回,模型基于结果继续推理。

一套好用的工具定义,关键在三处:

{
  "name": "query_orders",
  "description": "查询订单列表。时间范围必填,最长跨度不超过 90 天。返回订单数与总金额。",
  "parameters": {
    "type": "object",
    "properties": {
      "start": { "type": "string", "description": "起始日期,格式 YYYY-MM-DD" },
      "end":   { "type": "string", "description": "结束日期,格式 YYYY-MM-DD" }
    },
    "required": ["start", "end"]
  }
}
  • description 写给模型看,不是写给程序员看。要写清”什么时候该用、什么时候不该用、边界是什么”,而不是复述函数名。
  • 参数尽量少而明确。参数越多,模型填错的概率越高。能用默认值的参数就别让它填。
  • 返回值要可读。工具返回给模型的也是文本,压缩成模型容易消化的结构(字段少、有明确语义、错误信息可读),比返回原始 JSON dump 有效得多。

工具返回的错误也要认真设计。”参数错误”这种信息对模型没有帮助,”end 日期不能早于 start 日期,请检查”才能让模型自己纠正。错误信息是 Agent 自我修复能力的重要输入。

四、护栏与权限控制

Agent 会”动手”,就意味着它可能”做错事”。护栏不是可选项,是把 Agent 放进生产环境的前提。常见手段按严格程度递增:

  1. 白名单。只允许调用明确列出的工具,其他一律不暴露。比”把所有 API 都注册上去,靠提示词约束”安全一个数量级。
  2. 参数约束。限制可操作的资源范围(只读某个目录、只操作某个项目的数据),在工具实现层校验,而不是依赖模型自觉。
  3. 确认机制。对高危操作(删除、发送、支付、对外发布)设置人工确认点。Agent 提议、人来批准,这个模式在多数业务里是合理的默认值。
  4. 审计日志。每次工具调用记录:时间、工具名、参数、结果、触发该调用的对话上下文摘要。出问题时能回溯,也方便分析 Agent 的行为模式。
  5. 速率与预算限制。限制单次任务的工具调用总次数、总 Token 消耗、总执行时间。失控的循环会在烧完预算之前先烧掉你的耐心。

一个实用的分类法:读操作可以放开一些,写操作收紧,不可逆操作(删除、对外发送)必须人工确认。按这个梯度设计权限,比一刀切全放开或全锁死都更实用。

五、常见失败模式

Agent 的失败不是”随机出错”,模式相当集中:

失败模式 表现 应对
循环打转 反复调用同一个工具、反复得到同样的错误 最大步数限制 + 重复调用检测
幻觉工具 调用不存在的工具名、编造参数 白名单 + 参数 Schema 校验
权限过大 一次操作影响了不该影响的数据 参数约束 + 确认机制
上下文溢出 工具结果太大,早期任务目标被挤出窗口 结果截断/摘要 + 目标重申
过度自信 中间结果错了但没检查,一路推到结论 关键步骤插入校验点
提示注入 工具返回内容里藏有指令,带偏 Agent 行为 工具返回内容与指令分离、敏感操作确认

其中提示注入是 Agent 时代特有的风险:工具返回的数据里如果含有”请调用删除接口”这类文本,模型可能把它当成指令执行。对策是把”数据”和”指令”在结构上分开(比如工具结果用明确的分隔标签包裹、对工具返回内容做净化),并且永远不要让工具返回内容直接触发高危操作。

六、渐进落地:从确定性脚本到半自主

一口气做”全自主 Agent”是多数项目翻车的原因。更稳的路径是按自主度分级:

  • 级别 0:纯脚本。流程完全确定,LLM 只负责某个环节(比如从文本里抽取字段)。这一步价值已经很实在。
  • 级别 1:受限工具调用。模型可以在白名单里选工具,但每一步的执行流程由代码编排(orchestration),模型只做单步决策。
  • 级别 2:半自主。模型自己决定调用顺序,但关键节点有人工确认、有步数上限、有预算上限。
  • 级别 3:全自主。模型自主规划并执行完整任务。这一步的收益和风险都最大,只在失败代价可控的场景里尝试。

每一级升级的前提是:上一级的失败模式已经被监控和处理。没有监控的升级,只是把问题藏得更深。

从对话到自主调用工具,距离不在模型智商,而在于工程上愿不愿意把工具定义、权限边界、失败处理这些”枯燥的部分”做扎实。Agent 是一个系统工程问题,模型只是其中的一个组件——想清楚这一点,落地就会稳很多。

433浏览量
24赞
4评论
4参与用户
9 分钟阅读时间

评论(4)

  • 苏念禾 · 2026-10-13 14:50

    之前一直半懂不懂,现在清楚多了。

    回复
  • 晚棠 · 2026-10-13 21:50

    想问下这个方案对小团队来说会不会太重。

    回复
  • Liora · 2026-10-14 04:50

    文中举的例子很贴近实际工作。

    回复
  • 沈叙白 · 2026-10-14 11:50

    补充一点:文档里这块其实有说明,容易被忽略。

    回复