Agent 到底是什么

Agent 是 AI 应用里最容易被神化的词。

很多介绍会把 Agent 描述成“会自己思考、自己规划、自己使用工具的 AI”。这个说法不算错,但对工程实现帮助有限。前端工程师真正需要理解的是:Agent 不是某个更聪明的模型,也不是把 Prompt 写长一点,而是一种围绕目标、状态、工具和反馈循环组织起来的执行系统。

如果 Chat UI 是一次或多次模型调用的交互界面,那么 Agent 更像一个带状态的任务执行器。它会接受目标,观察已有信息,决定下一步,调用工具,读取结果,再决定是否继续、重试、请求用户确认或结束。

一个工程化定义

在生产系统里,可以把 Agent 定义成:

一个由应用层驱动的多步执行系统。它基于用户目标和当前状态,使用模型进行规划或决策,调用受控工具改变或查询外部环境,并通过观察结果持续推进任务。

这个定义里有几个关键词。

第一,Agent 是系统,不是模型。模型只是 Agent 的决策部件之一。Agent 还包括状态存储、工具注册、权限控制、执行器、日志、超时、重试和人工确认。

第二,Agent 是多步的。一次问答不叫 Agent。模型生成一段文案也不叫 Agent。只有当系统需要根据中间结果决定下一步时,Agent 的概念才有意义。

第三,Agent 会使用工具。工具可以是搜索、数据库查询、代码执行、浏览器操作、发邮件、创建工单、调用业务 API。没有工具的 Agent 通常只是一个会自我对话的生成器。

第四,Agent 有反馈循环。它不是一次性生成完整答案,而是 observe、plan、act、verify、recover 的循环。

这张图很重要:Agent 的核心不是“模型想得更久”,而是“应用让模型在一个受控循环里做下一步决策”。

Agent 和普通 Chat 的区别

普通 Chat 以消息为中心。用户输入一条消息,系统拼上下文,调用模型,返回回答。即使有多轮历史,本质上仍然是“用户驱动下一轮”。

Agent 以任务为中心。用户给出目标后,系统可以在一次用户输入后执行多个内部步骤。用户不一定知道每一步的细节,但系统必须记录每一步的状态。

维度普通 ChatAgent
交互单位messagetask / run / step
推进方式用户发下一条消息系统自主推进多步
状态重点对话历史目标、计划、工具结果、错误状态
工具调用可选,通常较少核心能力
失败处理返回错误或让用户重问重试、降级、恢复、人工确认
可观察性看最终回答看每一步计划、调用、结果和判断

前端工程师做 Agent UI 时,也不能只把它当聊天窗口。你需要展示任务进度、步骤状态、工具调用、失败原因、可取消入口和人工确认点。

Agent 的基本组成

一个可落地的 Agent 通常至少包含七个模块。

Goal

Goal 是用户想完成的任务,例如“帮我调研三个竞品并生成对比表”,“检查这个 PR 是否有明显风险”,“根据客户反馈生成一个工单草稿”。

Goal 不能只是自然语言原文。系统应该把它转成更明确的任务对象:

type AgentGoal = {
  id: string;
  userId: string;
  taskType: 'research' | 'review' | 'support' | 'ops';
  instruction: string;
  constraints: string[];
  successCriteria: string[];
  requiresApproval?: boolean;
};

越高风险的 Agent,越需要明确 success criteria。否则系统很难判断什么时候应该结束。

State

State 是 Agent 的生命线。没有状态持久化,Agent 就无法暂停、恢复、审计和重试。

一个最小状态可以包括:

type AgentRunState = {
  runId: string;
  goal: AgentGoal;
  status: 'queued' | 'running' | 'waiting_approval' | 'failed' | 'completed' | 'cancelled';
  plan: AgentStep[];
  currentStepId?: string;
  observations: Observation[];
  toolCalls: ToolCallRecord[];
  errors: AgentError[];
  createdAt: string;
  updatedAt: string;
};

前端如果只拿到最终文本,就无法做可靠的 Agent 体验。更好的方式是订阅 run state 的变化,把每个 step 渲染成可检查的执行轨迹。

Planner

Planner 负责把目标拆成步骤,或者在每轮循环中决定下一步。

Planner 可以很简单,例如固定 Prompt 让模型输出 JSON:

{
  "nextAction": "search_web",
  "reason": "需要先找到官方价格页面",
  "input": {
    "query": "product enterprise pricing official"
  }
}

也可以很复杂,例如结合任务模板、状态机和模型决策。但无论复杂度如何,Planner 的输出都应该是结构化的,并经过 schema 校验。不要让模型直接输出一段“我接下来要搜索一下”,然后靠字符串猜测要执行什么。

Tools

工具是 Agent 与外部世界连接的边界。

工具定义应该包括名称、用途、参数 schema、权限、超时、幂等性、风险等级和结果 schema。

type AgentTool = {
  name: string;
  description: string;
  inputSchema: unknown;
  outputSchema: unknown;
  riskLevel: 'read' | 'write' | 'external_effect';
  timeoutMs: number;
  requiresApproval: boolean;
};

对前端工程师来说,工具结果不只是后端日志。它会影响 UI 状态:正在搜索、读取了哪些文档、生成了什么草稿、等待哪一步确认、哪一步失败。

Executor

Executor 负责真正执行工具调用。它不应该盲信模型输出。

Executor 要做的事包括:

  • 校验工具是否存在。
  • 校验参数是否符合 schema。
  • 检查用户权限。
  • 判断是否需要人工确认。
  • 设置超时和重试。
  • 记录请求、响应、错误和耗时。
  • 把工具结果写回 Agent State。

如果 Planner 是“大脑”,Executor 就是“刹车、方向盘和仪表盘”。Agent 能否进入生产,往往取决于 Executor 是否足够严谨。

Verifier

Verifier 判断当前结果是否可靠,任务是否可以结束。

它可以用规则判断,例如“必须有三条来源”,“JSON 必须符合 schema”,“所有引用都来自已读取文档”。也可以用模型判断,例如让 LLM-as-judge 检查报告是否覆盖 success criteria。

没有 Verifier 的 Agent 很容易出现两种问题:过早结束,给出没有证据的答案;或者一直循环,反复搜索和改写。

Memory

Memory 不是 Agent 的必需品,但很多 Agent 会需要短期记忆。

这里的 memory 更准确地说是任务内状态:已经查过哪些来源、哪些工具失败过、用户已经拒绝了什么方案、当前假设是什么。

不要一开始就把长期用户记忆、向量库、对话历史全塞给 Agent。Agent 最需要的是与当前任务相关、可解释、可裁剪的工作记忆。

面向前端工程师的理解方式

前端工程师可以把 Agent 看成一种“异步多步表单 + 状态机 + AI 决策器”的组合。

传统前端流程里,用户填写表单,点击提交,后端返回结果。复杂一点的场景会有上传、排队、处理中、成功、失败、重试。

Agent 只是把“后端处理中”展开成多个可观察步骤:

  • 正在理解目标。
  • 正在规划步骤。
  • 正在调用搜索工具。
  • 正在读取结果。
  • 正在生成中间结论。
  • 正在等待用户确认。
  • 正在恢复失败步骤。
  • 正在输出最终结果。

因此 Agent UI 不应该只显示一个 spinner。用户需要知道系统在做什么、为什么卡住、是否可以取消、是否需要介入。

一个基本的 Agent 前端状态可以这样设计:

type AgentRunView = {
  runId: string;
  title: string;
  status: 'running' | 'waiting_approval' | 'failed' | 'completed';
  steps: Array<{
    id: string;
    title: string;
    status: 'pending' | 'running' | 'success' | 'failed' | 'skipped';
    startedAt?: string;
    endedAt?: string;
    summary?: string;
    toolName?: string;
    recoverable?: boolean;
  }>;
  finalOutput?: string;
};

这类结构比聊天消息更适合承载 Agent。聊天可以作为入口和结果展示,但执行过程应该有专门的任务视图。

系统设计

一个基础 Agent 系统可以这样拆分:

这个架构有几个关键点。

第一,Agent 通常应该异步执行。多步任务可能持续几十秒到几分钟,不能只依赖一个同步 HTTP 请求。

第二,状态要落库。前端刷新页面后,应该还能看到任务进度。Worker 重启后,应该能从最近的稳定步骤恢复。

第三,UI 应该通过事件流订阅状态变化。SSE、WebSocket 或轮询都可以,关键是不要让用户面对一个沉默的等待界面。

第四,工具执行要集中管理。不要让每个 Agent Prompt 自己“决定”怎么调用任意 API。

第五,Eval 和 Audit 要从第一天存在。Agent 的风险不只在最终答案,也在中间行动。

可靠性边界

Agent 的可靠性边界来自三个事实。

第一,模型的规划不是确定性程序。它可能漏步骤、重复步骤、选择错误工具,或者在上下文变长后偏离目标。

第二,工具结果不是天然可信。搜索结果可能过时,网页可能含有注入内容,API 可能超时,业务数据可能缺字段。

第三,多步系统会放大错误。第一步的小误判可能影响后续所有步骤,最后形成看似完整但基础错误的结果。

所以生产 Agent 必须设置边界:

  • 限制最大步骤数和最大耗时。
  • 对高风险工具做人工确认。
  • 对工具参数做 schema 校验和权限校验。
  • 对外部内容做隔离,不能让它覆盖系统规则。
  • 对最终结果做验证,尤其是引用、事实、格式和权限。
  • 保留完整 trace,便于复盘。
  • 支持取消、暂停、重试和从某一步恢复。

如果一个 Agent 不能解释自己做过什么,也不能在失败后恢复,它就更像一个不可控的黑盒任务。

常见坑

把 Agent 当成更长的 Prompt

很多早期实现会写一个超长 Prompt,让模型“一次性规划并执行”。这会让系统看起来智能,但很难控制。

真正的 Agent 应该让模型输出结构化决策,由应用层执行工具,再把观察结果反馈给模型。执行权应该在应用层,而不是在一段自然语言里。

没有状态模型

如果系统只保存最终回答,不保存 step、tool call、observation 和 error,后续就无法排查失败。

前端体验也会变差:刷新丢进度,失败不知道哪一步错,用户只能重新开始。

工具权限过大

Agent 最危险的地方不是“说错话”,而是“做错事”。写数据库、发邮件、创建订单、删除资源这类工具必须有明确权限和确认机制。

一个实用原则是:读工具可以更自动,写工具要更谨慎,对外部产生影响的工具必须可审计。

没有停止条件

Agent 如果没有明确停止条件,就容易反复搜索、反复总结、反复修正。

停止条件可以包括达到 success criteria、最大步骤数、成本上限、连续失败次数、用户取消或 verifier 判定无需继续。

把所有问题都交给 Agent

不是所有 AI 功能都需要 Agent。分类、摘要、改写、结构化抽取、固定审批流,通常用普通模型调用或 Workflow 更合适。

Agent 适合路径开放、需要探索、需要根据中间结果调整策略的任务。它不是默认方案。

小结

Agent 不是魔法,也不是某个独立的模型能力。它是一种多步 AI 执行系统:用模型做规划或决策,用工具连接外部世界,用状态记录过程,用验证和恢复控制风险。

对前端工程师来说,理解 Agent 的关键不是追逐概念,而是把它拆成可渲染、可观察、可取消、可恢复的任务体验。

当你能清楚回答“目标是什么、状态在哪里、工具边界是什么、失败后怎么恢复、用户如何介入”时,Agent 才从 Demo 走向工程系统。