跳到主要内容
Cowers://
全部文章
Agent 架构

Agent 概念

AI Agent(人工智能智能体)是一个以模型为决策核心、能够读取当前状态、选择并调用工具、根据执行结果继续行动,直到完成任务或停止的系统。 最小闭环可以记成:目标 → 决策 → 行动 → 观察 → 更新状态 → 再决策。

Agent 介绍:让模型从回答问题走向执行任务

阅读提示 本笔记面向已经了解大语言模型(LLM)和 Prompt、正在学习 Agent 的读者。主线是:Agent 是什么 → 一次任务如何循环 → 各组件分别负责什么 → 什么时候应该使用 Agent

本文先讲与框架无关的机制;具体框架选型可继续阅读Agent 常见框架与区别,决定要做之后的代码分层见Agent 架构:lang 系框架的工程分层

目录


核心概念 **AI Agent(人工智能智能体)**是一个以模型为决策核心、能够读取当前状态、选择并调用工具、根据执行结果继续行动,直到完成任务或停止的系统。

最小闭环可以记成:目标 → 决策 → 行动 → 观察 → 更新状态 → 再决策

一、Agent 到底是什么?

一句话说,普通 LLM 主要负责“生成内容”,Agent 系统则把模型放进一个可反复执行的控制循环,让它有机会“采取行动”。

例如,用户提出:

查询北京明天的天气;如果下雨,就提醒我带伞。

普通对话模型可能直接根据已有知识回答,但它并不知道明天的真实天气。Agent 可以:

  1. 判断需要查询实时天气;
  2. 生成对天气工具的调用请求;
  3. 由运行时执行工具并返回结果;
  4. 根据结果判断是否需要提醒;
  5. 输出带有依据的最终答复。

这里真正让系统跨越“说”与“做”的,不是模型突然获得了外部能力,而是开发者为它接入了工具(Tool)执行循环(Agent Loop)

Agent 的三个最低识别条件

判断一个系统是否具有 Agent 特征,可以看它是否具备:

  1. 目标: 知道当前要完成什么,而不只是续写一句话;
  2. 行动能力: 能选择工具或动作影响外部环境;
  3. 反馈闭环: 能读取行动结果,并据此决定下一步或结束。

记忆、复杂规划、多 Agent 协作都能增强 Agent,但不是每个 Agent 的最低必需条件。一个只调用一次天气工具再回答的简单 Agent,依然具有完整的“决策—行动—观察”闭环。

“自主”不等于“完全无人控制” Agent 的自主性通常是受约束的局部自主:它只能在开发者提供的工具、权限、预算、轮次和策略范围内选择动作。生产系统越重要,边界通常越明确。

二、Agent 如何完成一次任务?

Agent 的核心不是某个框架,而是一段由运行时驱动的循环。

agent-loop-overview

读图时从上往下看:模型先判断是否需要工具;如果需要,它只生成工具调用请求,运行时负责校验和执行;工具结果进入状态后,模型再次判断。模型输出最终答案或触发停止条件时,循环结束。

一次工具调用的完整过程

假设系统提供工具:

def get_weather(city: str, date: str) -> str:
    """查询指定城市和日期的天气。"""
    return "小雨,18°C"

用户输入“北京明天会下雨吗?”后,消息可能经历以下变化:

1. UserMessage
   北京明天会下雨吗?
 
2. AssistantMessage(工具调用请求)
   tool = get_weather
   arguments = {"city": "北京", "date": "明天"}
 
3. ToolMessage(真实执行结果)
   小雨,18°C
 
4. AssistantMessage(最终回答)
   北京明天预计有小雨,建议带伞。

最重要的边界是:

  • 模型决定调用什么,并生成结构化参数;
  • 运行时校验和执行调用,获得真实结果;
  • 模型读取结果,再决定继续调用工具还是结束。

⚠️ 把工具调用请求当成执行结果 错误操作: 模型生成 get_weather(...) 后,程序直接声称天气已经查询完成。

实际结果: 用户看到一个貌似真实、其实未经执行的结果;涉及写数据库、发邮件或付款时,后果更严重。

原因: 模型只能生成“调用工具的意图和参数”,不会自动执行应用代码。

正确做法: 由可信运行时校验工具名与参数、执行函数、捕获异常,再把真实结果作为 Tool Message 送回模型。

Agent 何时停止?

常见停止条件包括:

  • 模型给出最终答案;
  • 目标状态已经满足;
  • 达到最大步数、Token 或费用预算;
  • 工具连续失败或动作重复;
  • 即将执行高风险动作,需要人工确认;
  • 用户取消任务。

没有停止条件的 Agent 可能反复调用同一工具,所以“会停下来”与“会行动”同样重要。

三、Agent 由哪些部分组成?

agent-components

这张图展示最常见的 Agent 结构:模型负责判断,工具负责执行,系统指令规定角色与边界,状态保存任务过程。规划、记忆和安全控制通常建立在这四部分之上。

1. Model:负责判断,不负责真实执行

**Model(模型)**是决策核心。它读取目标、上下文、工具描述和当前状态,然后生成下一步动作或最终回答。

模型擅长处理语义和不确定信息,但它的输出具有概率性。因此,金额计算、权限判断、数据一致性等确定性规则不应只交给模型。

2. Tools:把语言意图连接到真实世界

**Tool(工具)**是 Agent 可以选择的外部能力,例如:

  • 查询数据库;
  • 调用搜索、天气或地图 API;
  • 读取或写入文件;
  • 执行代码;
  • 发送邮件;
  • 创建订单。

一个可靠工具需要清楚的名称、用途、输入模式、返回结构和错误语义。工具描述含糊时,模型更容易选错工具或填错参数。

3. Instructions:规定目标、边界与行为

**System Instructions(系统指令)**类似岗位说明书,负责说明 Agent 的角色、允许做什么、必须遵守什么,以及何时应向用户确认。

它适合表达行为规则,但不能替代代码层权限。提示词可能被误解或受到提示注入影响,真正的安全边界必须由运行时强制执行。

4. State:保存当前任务进行到哪里

**State(状态)**是完成当前任务所需的工作记录,例如:

  • 对话消息;
  • 已调用工具及结果;
  • 当前计划与完成进度;
  • 用户确认状态;
  • 错误、重试次数和预算。

状态解决的是“这次任务进行到哪里”,不必然等于长期记忆。

5. Memory:跨轮次或跨任务保留有用信息

**Memory(记忆)**通常分为:

  • 短期记忆: 当前任务中的消息和中间结果;
  • 长期记忆: 跨会话保存的偏好、历史事实或经验;
  • 外部知识: 通过 RAG 检索到的文档内容。

长期记忆不是“把所有聊天都永久塞给模型”。它需要筛选、存储、检索、更新和删除机制,否则容易积累过期信息或泄露隐私。

State 和「短期记忆」是什么关系? 看上面两节会发现它们的范围明显重叠——都包含当前任务的消息和中间结果。这不是笔记写重了,而是这两个词本来就切在不同的维度上:

  • State 是按「存在哪、由谁管」划分的:它是运行时那一份可序列化的工作数据,节点读它、写它,检查点存的就是它。
  • 短期记忆是按「给谁用」划分的:它指本次任务里、要喂给后续模型调用的那部分上下文(或其摘要)。

所以更准确的说法是:短期记忆通常是 State 的一个子集或它的派生物——State 里的消息历史经过裁剪、摘要、重排之后,才成为模型这一轮实际读到的短期记忆。State 里还有很多不进上下文的东西(重试计数、预算、内部标记)。

⚠️ 各框架的术语并不统一:LangGraph 里这两件事都落在 State + Checkpointer 上,「短期记忆」基本等同于同一 thread 内的 State 持久化;另一些框架会把 Memory 做成独立于 State 的组件。读文档时先确认对方的定义,不要拿一套术语去套另一套。

6. Guardrails:让自主行动留在安全边界内

**Guardrails(护栏)**是对输入、输出和动作的约束,包括:

  • 身份认证与权限校验;
  • 工具参数校验;
  • 只读与写入操作分级;
  • 超时、限流、最大步数和费用预算;
  • 敏感操作人工确认;
  • 日志、追踪和审计。

高风险动作不能只靠 Prompt 约束 “未经确认不要付款”写在提示词里仍然只是软约束。付款、删除、发布、发信等动作应在工具执行层强制检查权限、确认令牌和幂等键。

四、Tool Calling 为什么是关键机制?

**Tool Calling(工具调用)**是模型以结构化方式表达“我要调用哪个工具、传入哪些参数”的机制。

它解决了自然语言与程序接口之间的转换问题:

“查一下 1001 号订单”
        ↓ 模型理解意图
{"name": "get_order", "arguments": {"order_id": 1001}}
        ↓ 运行时校验并执行
{"status": "paid", "amount": 299.00}

Tool Calling 本身还不是 Agent。只有当系统把工具结果送回模型,并允许模型根据结果继续决策时,才形成 Agent Loop。

好工具为什么比长提示词更重要?

模型只能依据工具接口判断如何行动。如果工具把“查询、修改、删除”混在一个含糊入口里,提示词再长也难以彻底消除误用。

更好的接口是:

get_order(order_id)                    # 只读
update_shipping_address(order_id, ...) # 明确写入
cancel_order(order_id, reason)         # 高风险,要求确认

这让权限、审计和人工确认都能落在明确的动作边界上。

五、Agent、Workflow、RAG 和多 Agent 有什么区别?

这些概念可以组合,但解决的问题不同。

Agent 与 Workflow

**Workflow(工作流)**由开发者预先规定主要步骤和分支;Agent 则允许模型在运行时选择下一步。

Workflow:输入 → 固定步骤 A → 条件分支 B/C → 输出
Agent:   输入 → 模型判断下一步 → 工具结果 → 再判断 → 输出

生产系统常使用混合模式:外层 Workflow 固定合规流程,局部节点交给 Agent 处理语义判断。

Agent 与 RAG

RAG = Retrieval-Augmented Generation(检索增强生成),即检索外部数据,并用检索结果增强生成

注意这个定义比常见的说法宽:数据源不限于「一个事先建好的向量知识库」,也可以是搜索引擎、数据库、API、代码仓库;检索时机也不必然是「先检索、后生成」这一趟固定顺序——Agent 完全可以在推理中途按需发起多次检索,或者根据第一次生成的结果再去检索一轮。「固定知识库 + 一次前置检索」只是 RAG 最常见的一种实现形态,不是它的定义。

RAG 解决知识来源问题;Agent 解决动作决策与执行问题。RAG 可以作为 Agent 的一个检索工具,Agent 也可以完全不使用 RAG。更多机制见RAG 概念

单 Agent 与多 Agent

**Multi-Agent System(多智能体系统)**让多个具有不同角色、工具或上下文的 Agent 协作。

多 Agent 的价值通常来自明确的权限隔离、上下文隔离、专业分工或并行执行,而不是简单地把同一个提示词复制成多个角色。

⚠️ 把复杂任务直接升级为多 Agent 错误操作: 单 Agent 尚未稳定,就增加研究员、规划员、写作者、审核员等多个角色。

实际结果: 消息传递、上下文同步、失败恢复和成本同时变复杂,最终质量未必提高。

原因: 多 Agent 增加的是新的协作边界,并不会自动修复工具设计、数据质量或评价标准的问题。

正确做法: 先验证单 Agent 或 Workflow;只有在权限、上下文、并行或专业职责确实需要隔离时,再拆分 Agent。

六、什么时候应该使用 Agent?

适合 Agent 的任务

  • 目标明确,但完成路径会随中间结果变化;
  • 需要组合多个工具;
  • 输入是自然语言或其他非结构化信息;
  • 允许在受控范围内试错和重规划;
  • 任务价值足以覆盖模型调用、观察和治理成本。

例如:研究助理、故障诊断、跨系统客服处理、代码修改与验证。

不适合优先使用 Agent 的任务

  • 步骤完全固定、规则清楚;
  • 要求严格确定性或极低延迟;
  • 单个函数或一次数据库查询就能完成;
  • 缺少可验证的完成标准;
  • 无法限制高风险动作权限。

例如,计算税额、校验权限和执行固定审批链通常应由普通程序或 Workflow 主导。

选择规则 能用普通函数解决,就先用函数;需要固定编排,就用 Workflow;只有当“下一步必须根据语义和现场结果动态决定”时,再引入 Agent。

七、如何设计一个可靠的 Agent?

可以按以下顺序设计:

第一步:定义可验证的目标

不要只写“帮助用户解决问题”,应明确成功标准,例如:

  • 已获得订单状态;
  • 已生成满足字段约束的报告;
  • 修改已通过测试;
  • 用户已确认但尚未支付。

目标不可验证,Agent 就难以知道何时结束,也无法进行自动评测。

第二步:从最少的工具开始

每个工具保持单一职责,并区分只读、写入和破坏性动作。工具的返回值应结构化,错误也应能被机器识别。

第三步:显式设计状态与停止条件

至少记录当前步骤、关键结果、失败次数、预算和确认状态,并设置最大循环次数与超时。

第四步:把确定性规则留在代码里

模型适合做意图识别、信息抽取、规划候选和自然语言生成;权限、金额、状态机、唯一性和事务一致性应由代码控制。

第五步:给写操作加入人工确认

“读取订单”和“取消订单”不应拥有相同执行门槛。发送、发布、删除、付款等不可逆或外部可见动作,应在执行前展示具体影响并获得确认。

第六步:建立可观测与评测闭环

至少保留:

  • 模型输入输出;
  • 工具名、参数、结果和耗时;
  • 每一步状态变化;
  • Token、费用和失败原因;
  • 最终结果是否满足成功标准。

没有这些记录,Agent 出错时只能看到“最终答案不对”,无法定位是模型选错工具、参数错误、工具失败,还是状态丢失。

这六步在项目里放在哪 本节说的是设计原则;具体到代码分层——State 怎么声明、停止条件写在哪条边上、人工确认依赖什么机制、可观测挂在哪一层——见Agent 架构:lang 系框架的工程分层

八、常见误区与失败原因

误区 1:Agent 就是 Prompt 加几个工具

仅把工具说明放进提示词,不代表系统已经形成可靠 Agent。还需要执行器、状态管理、异常处理、停止条件和权限控制。

误区 2:Agent 一定需要复杂规划

复杂规划只是可选策略。很多有效 Agent 每轮只选择一个下一步,通过工具结果逐步推进。提前生成一份很长的计划,反而可能在环境变化后迅速失效。

误区 3:记忆越多越聪明

无差别保存历史会增加噪声、Token 和隐私风险。有效记忆需要回答三个问题:保存什么、何时检索、何时更新或删除。

误区 4:模型可以负责所有业务判断

模型输出具有概率性。即使相同输入,也可能因为上下文或采样产生差异。合规、权限、金额和数据状态等规则必须由确定性代码再次校验。

误区 5:能完成演示就等于可以上线

演示通常只覆盖成功路径;生产环境还会遇到超时、重复调用、部分成功、过期状态、提示注入和权限越界。

⚠️ 工具失败后无限重试 错误操作: 工具报错后,把同一错误不断送回模型,让模型无限重试。

实际结果: 任务卡住,Token 和外部 API 费用持续增加,还可能重复产生副作用。

原因: 系统没有区分可重试错误与永久错误,也没有最大次数、退避或幂等控制。

正确做法: 为错误分类;限制重试次数;写操作使用幂等键;超过阈值后停止并向用户说明失败位置。

速查表

概念 主要解决什么问题 谁控制下一步 是否涉及外部工具
普通 LLM 调用 理解与生成内容 应用或用户
Tool Calling 把自然语言意图转换为结构化工具请求 模型提出,运行时执行 是(但模型只是提出请求,执行与否由运行时决定)
Agent 根据反馈动态选择动作并完成目标 模型与运行时共同控制 通常是
Workflow 按预定义步骤稳定执行 开发者定义的流程 不一定
RAG 从外部知识库检索依据 检索流程或 Agent 使用检索器
Multi-Agent 隔离职责、上下文或权限并协作 多个 Agent 与协调机制 通常是

组件速记

组件 一句话职责 不能替代什么
Model 理解上下文并提出下一步 真实执行与硬性权限
Tool 执行查询或动作 决定业务目标
Instructions 描述角色、策略和软约束 代码层安全控制
State 保存当前任务进度 自动形成长期记忆
Memory 跨轮次检索有用信息 可靠的数据治理
Guardrails 限制输入、输出和动作 完整业务设计

复习重点

可直接复述的结论

  1. Agent 的本质不是“更会聊天”,而是模型决策、工具执行、结果反馈构成的循环
  2. 模型只生成工具调用请求;真实执行、权限、异常和事务由运行时负责。
  3. Agent 的最低闭环是目标、行动与反馈;记忆、复杂规划和多 Agent 都是可选增强。
  4. Workflow 强调预定义与可控,Agent 强调运行时动态决策;两者经常组合使用。
  5. RAG 解决“去哪里找知识”,Agent 解决“下一步采取什么动作”。
  6. 可靠 Agent 必须具备停止条件、权限隔离、人工确认、可观测性和可验证目标。
  7. 选型顺序是:普通函数 → Workflow → 单 Agent → 确有隔离价值时再用多 Agent

自测问题

  1. 为什么模型生成 Tool Call 不等于工具已经执行?
  2. State 与长期 Memory 有什么区别?
  3. 为什么付款权限不能只写进 System Prompt?
  4. 一个固定审批流程为什么通常更适合 Workflow?
  5. 在什么条件下,把单 Agent 拆成多 Agent 才有实际价值?