Agent 这个词现在被用得很乱。有人把它理解成“会自己思考的 AI”,有人把它理解成“多个角色互相讨论”,也有人认为只要给大模型接几个工具,就已经是在做 Agent。

但从工程角度看,Agent 最重要的不是“看起来多自主”,而是:

它能不能在明确边界内,稳定完成一个多步骤任务。

这才更接近真实 AI 应用开发。

在这里插入图片描述

一、普通大模型调用解决的是“回答”,Agent 解决的是“任务”

普通 LLM 调用一般是这样的:

用户输入一个问题,模型返回一段文本。

比如用户问:

帮我写一段求职信。

模型直接生成一段求职信。

这个过程没有问题,但它本质上还是一次文本生成。模型并不知道用户的真实简历细节有没有支撑这段求职信,也不知道目标 JD 的关键要求是什么,更不知道哪些内容不能夸大。

RAG 往前走了一步:它会先检索知识库、文档或数据库,再让模型基于材料回答。它主要解决的是“回答有没有依据”。

但 Agent 要解决的不是单次回答,而是任务推进。它不只是“查资料再回答”,而是要根据任务目标,在多个步骤之间做选择:

它可能需要先判断用户意图,再决定要不要查询订单;
它可能需要先检索售后政策,再判断是否能退款;
它可能需要生成一个草稿,但不能直接提交;
它可能需要发现证据不足,然后暂停,要求用户补充信息。

也就是说,Agent 面向的不是单次回答,而是一个可执行的任务过程。

所以我更愿意把 Agent 看成一个系统问题:

Agent 不是把 prompt 写得更像人,而是把模型放进一个可以行动、可以观察、可以被约束的系统里。

二、Agent 和 Workflow 的区别

我不太建议一上来就从“自主规划”理解 Agent。

Anthropic 在《Building effective agents》里把 agentic systems 分成 workflow 和 agent。Workflow 是 LLM 和工具按照预设代码路径被编排;Agent 则是 LLM 可以动态决定自己的流程和工具使用方式。它们都属于 agentic system,但工程含义不同。

这个区分很重要。

如果你的任务路径本来就很清楚,比如:

  1. 解析 JD
  2. 解析简历
  3. 匹配能力项
  4. 找出缺口
  5. 生成定制简历
  6. 做证据检查
  7. 输出风险提示

那它更适合先做成 workflow,而不是一上来就交给 Agent 自己规划。

Workflow 的好处是可控、可测、可复盘。

Agent 的价值在于处理那些路径不固定、步骤数量不确定、需要根据中间结果不断调整的任务。

比如客服场景里,用户可能问的是物流、退款、发票、商品参数、投诉、优惠券、售后政策,也可能把多个问题混在一起。系统很难提前写死所有路径,这时 Agent 才有更明确的价值。

换成代码视角,区别更明显:

Workflow 的下一步主要由开发者写死。
Agent 的下一步主要由模型根据当前状态决定。

这不是说 Agent 没有代码控制,而是说代码负责提供工具、状态和边界,模型负责在这些边界里选择下一步。

但这不代表 Agent 可以无限自由。恰恰相反,Agent 越能行动,越需要边界。

三、用代码理解 Agent

从代码角度看,Agent 不是一个神秘概念。

它可以先理解成:

Agent = 一个由 LLM 驱动下一步决策的任务循环。

这里的“循环”不是说所有框架源码都必须写成 while,而是说 Agent 的运行语义大致相同:模型决定下一步,应用执行工具,工具结果写回状态,模型再基于新状态继续判断。

while (!state.isFinished()) {
    AgentDecision decision = llm.decideNextStep(state, availableTools);

    if (decision.isFinalAnswer()) {
        return decision.answer();
    }

    if (decision.isToolCall()) {
        policyGate.check(user, decision.toolName(), decision.arguments());

        ToolResult result = toolExecutor.execute(
            decision.toolName(),
            decision.arguments()
        );

        state.addToolResult(result);
        traceLog.record(decision, result);
    }

    if (decision.needHumanApproval()) {
        return pauseForHumanReview(state);
    }
}

这不是某个 Agent 框架的完整源码,而是 Agent 的核心运行语义。

普通 LLM 是:

String answer = llm.chat(userQuestion);
return answer;

RAG 是:

List<Document> docs = retriever.search(userQuestion);
String answer = llm.chat(userQuestion, docs);
return answer;

Workflow 是:

JdInfo jd = parseJd(input);
ResumeInfo resume = parseResume(input);
MatchResult match = matchResumeToJd(jd, resume);
RewriteResult rewrite = rewriteResume(match);
RiskReport risk = checkEvidence(rewrite);

return result;

Agent 是:

AgentState state = new AgentState(userGoal);

while (state.canContinue()) {
    AgentDecision decision = model.decide(state, tools);

    switch (decision.type()) {
        case CALL_TOOL -> {
            ToolResult result = executeTool(decision);
            state.observe(result);
        }
        case ASK_USER -> {
            return askUserForMoreInfo(decision.question());
        }
        case NEED_APPROVAL -> {
            return waitForHumanApproval(decision.action());
        }
        case FINAL -> {
            return decision.finalAnswer();
        }
    }
}

区别就在这里:

Workflow 的下一步是代码写死的。
Agent 的下一步是模型根据当前状态决定的。

这也对应了 Anthropic 对 workflow 和 agent 的区分:前者按预设路径执行,后者由模型动态决定流程和工具使用。


代码上,一个 Agent 至少有 5 个对象

不要先想 LangGraph、CrewAI、AutoGen。先想这 5 个类。

(1)AgentState:任务状态
public class AgentState {
    private String goal;
    private int step;
    private List<Message> messages;
    private List<ToolCallRecord> toolCalls;
    private Map<String, Object> facts;
    private boolean finished;
    private boolean needHumanApproval;
}

它回答一个问题:

任务现在进行到哪一步了?

没有 AgentState,就不是连续任务,只是一次问答。


(2)AgentTool:工具
public interface AgentTool {
    String name();

    String description();

    ToolResult execute(Map<String, Object> arguments);
}

比如电商客服 Agent 里可以有:

public class GetOrderTool implements AgentTool {

    public String name() {
        return "get_order";
    }

    public String description() {
        return "根据 orderId 查询当前用户的订单状态";
    }

    public ToolResult execute(Map<String, Object> args) {
        String orderId = (String) args.get("orderId");

        // 查数据库 / 调接口
        return orderService.getOrder(orderId);
    }
}

Spring AI 的 Tool Calling 也是类似思想:模型提出工具调用请求,应用程序负责解析、执行工具、再把结果返回给模型。模型不是直接操作你的数据库。


(3)AgentDecision:模型决定下一步
public sealed interface AgentDecision permits CallTool, FinalAnswer, NeedHumanApproval {
}

public record CallTool(
    String toolName,
    Map<String, Object> arguments
) implements AgentDecision {
}

public record FinalAnswer(
    String answer
) implements AgentDecision {
}

public record NeedHumanApproval(
    String action,
    String reason
) implements AgentDecision {
}

这里就是 Agent 和普通程序最大的区别。

普通程序是你写:

先查订单,再查政策,再生成回复。

Agent 是模型返回:

{
  "type": "CALL_TOOL",
  "toolName": "get_order",
  "arguments": {
    "orderId": "123456"
  }
}

然后你的后端决定:

这个工具存不存在?
这个用户有没有权限?
这个 orderId 是不是他的?
这个动作需不需要人工确认?


(4)PolicyGate:权限边界
public class PolicyGate {

    public void check(User user, String toolName, Map<String, Object> args) {
        if (toolName.equals("submit_refund")) {
            throw new NeedHumanApprovalException("退款提交必须人工确认");
        }

        if (toolName.equals("get_order")) {
            String orderId = (String) args.get("orderId");
            if (!orderService.belongsToUser(orderId, user.id())) {
                throw new AccessDeniedException("不能查询他人订单");
            }
        }
    }
}

边界不是 prompt 里写一句“不要越权”,而是代码里真的拦住。

OWASP 的 Excessive Agency 风险,本质就是 LLM 系统被授予过多功能、权限或自主性后,可能造成破坏性动作;所以工具权限、人工确认、最小授权必须在系统层实现。


(5)AgentRunner:核心循环
public class AgentRunner {

    private final LlmClient llm;
    private final ToolRegistry toolRegistry;
    private final ToolExecutor toolExecutor;
    private final PolicyGate policyGate;
    private final TraceLog traceLog;

    public AgentResult run(User user, String goal) {
        AgentState state = new AgentState(goal);

        while (!state.isFinished() && state.getStep() < 10) {
            AgentDecision decision = llm.decideNextStep(state, toolRegistry.availableTools());

            if (decision instanceof FinalAnswer finalAnswer) {
                state.finish();
                return AgentResult.success(finalAnswer.answer());
            }

            if (decision instanceof NeedHumanApproval approval) {
                return AgentResult.waitingForApproval(approval.action(), approval.reason());
            }

            if (decision instanceof CallTool callTool) {
                policyGate.check(user, callTool.toolName(), callTool.arguments());

                ToolResult result = toolExecutor.execute(
                    callTool.toolName(),
                    callTool.arguments()
                );

                state.addToolCall(callTool, result);
                traceLog.record(state, callTool, result);
                state.nextStep();
            }
        }

        return AgentResult.failed("Agent stopped: max steps reached.");
    }
}

OpenAI Agents SDK 里所谓 agent loop,本质也是:处理工具调用,把结果送回 LLM,然后继续运行直到任务完成;同时配套 guardrails、sessions、tracing 等工程能力。


用电商客服理解一次完整执行

用户问:

我的订单签收三天了,商品破损,可以退吗?

Agent 第一次判断:

{
  "type": "CALL_TOOL",
  "toolName": "get_order",
  "arguments": {
    "orderId": "A1001"
  }
}

后端执行:

policyGate.check(user, "get_order", args);
ToolResult order = getOrderTool.execute(args);
state.addToolResult(order);

工具返回:

{
  "orderId": "A1001",
  "status": "SIGNED",
  "signedDaysAgo": 3,
  "productCategory": "electronics"
}

Agent 第二次判断:

{
  "type": "CALL_TOOL",
  "toolName": "get_refund_policy",
  "arguments": {
    "category": "electronics"
  }
}

工具返回:

{
  "category": "electronics",
  "returnWindowDays": 7,
  "needDamagePhoto": true,
  "autoRefundAllowed": false
}

Agent 第三次判断:

{
  "type": "FINAL",
  "answer": "你的订单签收 3 天,仍在 7 天售后窗口内。但商品破损需要上传图片凭证,我可以先帮你生成退款申请说明,提交退款前需要你确认。"
}

这就是一个最小 Agent 的运行过程。

它不是一次性回答,而是:

看当前状态
→ 决定查订单
→ 得到订单结果
→ 决定查政策
→ 得到政策结果
→ 判断不能直接退款
→ 给出受边界约束的答案

所以,从代码视角看,Agent 不是让模型直接控制系统,而是让模型提出下一步动作,再由应用程序判断、执行、记录和约束。

四、Agent 的核心不是“自主”,而是工具、状态和边界

一个更工程化的 Agent 定义可以是:

Agent = LLM + Tools + State + Control Loop + Guardrails

拆开看:

LLM 负责理解任务和选择下一步。
Tools 负责连接数据库、订单系统、知识库、搜索服务等外部能力。
State 负责记录任务进展、工具调用历史和中间结果。
Control Loop 负责把模型决策、工具执行和结果反馈串起来。
Guardrails 负责限制模型不能越权、不能乱调用工具、不能直接执行高风险动作。

这里最容易被忽略的是工具调用的安全边界。

Spring AI 官方文档对 tool calling 的说明很清楚:虽然通常说 tool calling 是模型能力,但实际执行工具调用逻辑的是客户端应用。模型只能请求工具调用并提供参数,真正执行工具、返回结果的是应用程序本身;模型并不会直接获得工具背后的 API 权限。

这句话非常关键。

因为它说明 Agent 不是让模型直接控制系统,而是让模型提出行动意图,再由应用层判断是否执行。

比如电商客服 Agent 面对“我的订单能退吗?”这个问题时,它不应该直接回答“可以退”。

更合理的方式是:先查询订单,再查询售后政策,再结合订单状态、商品类目和平台规则生成回复。如果涉及退款提交,就只能生成草稿,不能直接执行。

这才是可上线的 Agent。

五、Agent 的真正风险:从“回答错误”变成“行动越界”

普通大模型回答错,风险主要在内容层。

Agent 一旦接入工具,风险就进入系统层。

它可能查错数据,调用错工具,传错参数,泄露敏感信息,执行不该执行的操作,或者在错误前提下连续行动。

OWASP LLM Top 10 里专门列出了 Prompt Injection、Insecure Plugin Design、Excessive Agency 等风险。其中 Excessive Agency 指的是给 LLM 过多、未受约束的行动自主权,可能破坏可靠性、隐私和信任。

这也是为什么我不赞成一开始就做“全自动 Agent”。Agent 安全不能只靠 prompt,而必须靠工具权限、参数校验、人工确认和审计日志这些系统层设计。

真正的工程顺序应该是:

先让模型会读。
再让模型会查。
再让模型会生成草稿。
再让模型在低风险场景自动执行。
最后才考虑高风险动作的半自动化或自动化。

对于工具权限,我更倾向于分四层:

READ:只读查询,可以自动执行。
例如查询订单状态、查询物流、检索政策文档。

DRAFT:只生成草稿,不真正提交。
例如生成退款说明、工单回复、邮件草稿。

WRITE_REVIEW:会改变系统状态,必须人工确认。
例如提交退款申请、修改用户资料、发送正式邮件。

DANGEROUS:默认禁止。
例如删除数据、批量修改权限、执行任意命令。

如果一个 Agent 系统没有这个权限分层,那它本质上还不能算生产级 Agent,只是一个接了工具的聊天机器人。

六、一个更接近真实项目的 Agent 示例

假设我们要做一个跨境电商客服 Agent。

用户问:

我这个订单已经签收三天了,商品有破损,能不能退?

一个不可靠的 AI 可能会直接回答:

一般情况下,签收七天内可以退货。

这句话听起来合理,但它不一定正确。

因为真实判断至少需要几个条件:

订单是否真实存在?
订单是不是当前用户的?
商品类目是什么?
是否支持无理由退货?
破损是否需要上传凭证?
当前是否超过售后时间?
平台政策和商家政策是否冲突?
是否需要人工客服介入?

所以更合理的 Agent 流程应该是:

用户问题
→ 意图识别:售后 / 退款 / 商品破损
→ 查询订单状态
→ 检索售后政策(RAG 在这里是证据工具)
→ 检查商品类目
→ 判断是否需要图片凭证
→ 生成客服回复
→ 标注证据来源
→ 如果涉及退款提交,进入人工确认
→ 记录整次 Agent Run

在这个流程里,模型不是凭常识回答,而是在工具和证据的约束下完成任务。

这就是 Agent 相比普通聊天机器人的真正区别:它不是凭常识直接回答,而是在工具、证据和权限边界内推进任务。

七、为什么不要一开始做多 Agent

很多 Agent 教程喜欢从多 Agent 开始:

一个产品经理 Agent,一个架构师 Agent,一个开发者 Agent,一个测试 Agent,大家互相讨论,最后输出结果。

这种演示很容易吸引眼球,但工程价值未必高。

多数真实业务问题,不是靠“多几个角色说话”解决的,而是靠更清楚的任务边界、更可靠的工具、更稳定的状态记录和更严格的输出校验解决的。

多 Agent 只有在这些场景下才更有必要:

不同角色确实需要不同职责;
不同 Agent 拥有不同工具权限;
需要一个 Agent 审查另一个 Agent 的输出;
任务路径复杂到单一 workflow 难以维护;
系统需要长期运行和异步协作。

否则,多 Agent 很可能只是增加延迟、成本和调试难度。

所以第一篇不应该从多 Agent 开始,而应该先讲清楚单个 Agent 如何完成任务、如何调用工具、如何记录状态、如何控制边界。

八、我对 Agent 的第一性原则

如果让我用一句话定义 Agent,我不会说它是“自主智能体”。

我更愿意说:

Agent 是一个让大模型在工具、状态和权限边界内完成任务的工程系统。

这个定义不够炫,但更适合真实开发。

因为 Agent 的难点从来不只是“让模型更聪明”,而是:

它能调用什么工具;
它不能调用什么工具;
它每一步是否有依据;
它的工具调用是否可追踪;
它在证据不足时能不能停下来;
它在高风险动作前能不能交给人;
它失败后能不能复盘。

所以 Agent 专题不应该从框架开始,不应该从多 Agent 开始,也不应该从“让 AI 自己干活”开始。

它应该先回答一个更基础的问题:

当我们说要做 Agent 时,我们到底是在做一个聊天机器人,还是在做一个可控的任务执行系统?

如果只是聊天,普通 LLM 就够了。
如果只是查资料,RAG 就够了。
如果路径固定,Workflow 就够了。
如果任务路径不确定,需要工具、状态、反馈和权限边界,才真正进入 Agent。

下一篇,我会解释 Agent 核心术语:ReAct、Tool Calling、State、Memory、Workflow 到底是什么?

参考资料

  • Anthropic:Building effective agents
  • OpenAI Agents SDK:Agent loop、Tools、Sessions、Tracing、Guardrails
  • Spring AI Reference:Tool Calling
  • OWASP LLM Top 10:Excessive Agency
  • ReAct:Synergizing Reasoning and Acting in Language Models
  • Toolformer:Language Models Can Teach Themselves to Use Tools

我是 Ryan,一个专注于可信 AI 应用工程的开发者,我的个人技术博客,研究如何让 AI 生成从“看起来对”走向“有证据、可追溯、可验证”。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐