AI应用工程:Agent 是如何工作的?——从一次模型调用到可运行的执行循环

假设用户对客服 Agent 说:

shell 复制代码
请帮我取消订单 123。

模型很快返回一段结构化结果:

json 复制代码
{
  "name": "cancel_order",
  "arguments": {
    "orderId": 123
  }
}

日志里已经出现 cancel_order,看起来 Agent 做出了正确决定。可此时查询订单系统,订单 123 仍然是"待发货"。

这不是模型调用失败。恰恰相反,模型已经完成了它在这一轮中的工作:根据用户请求和工具描述,生成一个结构化的 Tool Call。问题在于,提出动作和执行动作不是一回事。

接下来还有一串没有发生的事情:

  • 谁确认订单 123 属于当前用户?
  • 谁校验订单是否仍可取消?
  • 谁判断这项操作是否需要人工审批?
  • 谁真正调用订单服务?
  • 如果订单已经发货或服务超时,谁处理失败?
  • 工具返回结果后,谁决定回复用户还是继续调用其他工具?

Tool Calling 只建立了模型与应用之间的协议接口。要把这个调用请求变成已经发生的业务动作,应用必须接住模型输出,执行工具,再把真实结果送回模型。模型若继续产生新的 Tool Call,这个过程还要重复。

上一篇讨论了为什么模型能力不等于企业生产力。本篇沿着其中的"任务闭环层"继续向内拆:一次模型调用,究竟如何变成一段可以执行、暂停、恢复和结束的 Agent Run?

一、Tool Calling 只完成了"提出动作"

1. 模型返回的是结构化决策

向模型声明工具时,应用通常会提供工具名称、用途说明和参数结构。模型根据当前输入判断是否使用工具;如果需要,它返回工具名称与参数,而不是直接进入订单数据库执行 SQL。

以取消订单为例,模型看到的可以是这样一份工具定义:

typescript 复制代码
const cancelOrder = {
  name: "cancel_order",
  description: "取消尚未发货且属于当前用户的订单",
  parameters: {
    type: "object",
    properties: {
      orderId: { type: "number" }
    },
    required: ["orderId"]
  }
};

工具描述让模型知道"有哪些动作可以选择",参数 Schema 约束它"应该用什么格式提出动作"。模型返回的 namearguments 仅仅是一份结构化请求;真正的函数调用必须由应用侧(Client Tool)接管并执行。OpenAI 与 Anthropic 的 Tool Calling 文档都把这个边界写得很清楚:模型产生调用,应用执行代码,再将 Tool Result 返回模型。^1^^2^

模型在一轮中也不一定只返回 Tool Call。根据 API 和应用约定,它还可能返回最终文本、结构化业务结果,或者多个工具调用。Runtime 必须检查实际输出,而不能假设每次响应都是可以直接展示给用户的答案。

2. 应用把请求变成真实动作

一个 Tool Call 从模型出来后,至少要经过四类处理:

参与者 输入 负责事项 输出 不负责事项
Model 当前 Context、工具定义 生成最终回答或下一步结构化调用 Final Output / Tool Call 不直接保证业务动作成功
Runtime Model Output、Run State 解析、校验、选择分支、维护循环 执行指令或 Run Result 不替代业务系统完成动作
Policy / Approval Tool Call、用户与风险信息 判断允许、拒绝或暂停审批 Policy Decision 不生成业务结果
Tool Executor 已通过校验的参数 调用订单服务、数据库或外部 API Tool Result 不决定完整任务是否结束

回到订单案例。Runtime 首先要确认 cancel_order 是已注册工具,orderId 符合参数 Schema;Policy 再结合当前用户、订单归属与动作风险判断是否放行;Tool Executor 最后才向订单服务发出取消请求。

这个边界也解释了为什么不能简单地说"模型会操作数据库"。对于 Client Tool,动作由用户应用执行;对于部分 Hosted Tool 或 Server Tool,则由模型服务提供方的运行时执行。执行位置可以不同,但都不是"模型权重本身直接连接外部系统"。^2^

3. 一次完整往返包含两次模型交互

Client Tool 的典型过程不是一次请求,而是五个步骤:^1^

sequenceDiagram participant U as 用户 participant A as 应用 / Runtime participant M as Model participant T as cancel_order U->>A: 请取消订单 123 A->>M: 输入 + cancel_order 定义 M-->>A: Tool Call(orderId=123) A->>A: 校验参数、权限与审批策略 A->>T: 执行取消订单 T-->>A: Tool Result(取消成功) A->>M: 原输入 + Tool Call + Tool Result M-->>A: 订单 123 已取消 A-->>U: 最终答复

第一轮 Model Call 产生动作请求;应用执行工具;第二轮 Model Call 读取 Tool Result,才生成"订单已取消"的最终答复。如果工具返回"订单已经发货",模型也应基于这个事实调整回答,而不是继续宣称取消成功。

所以,接入 Tool Calling 不自动等于得到一个 Agent。 它只是让模型能够用结构化格式提出动作。应用还需要执行动作、回传结果,并处理模型可能继续提出的下一个动作。

二、从一次往返到 Agent Run,中间多了一个循环

1. 一次 Model Call 不等于一次 Agent Run

Model Call 的边界很清楚:应用组装 Context,调用模型,取得一次输出。Agent Run 的边界则更长:从收到任务开始,经历若干次模型调用、工具执行与状态更新,直到运行完成、暂停、失败或被取消。

OpenAI Agents SDK 把一个 Run 描述为持续到"真实停止点"的循环:调用模型,检查输出;有 Tool Call 就执行后继续,有 Handoff 就切换处理者,没有后续工具工作且得到最终回答时才返回结果。^3^ Anthropic 对 Agent 的概括更直接:LLM 根据环境反馈在循环中使用工具。^4^

因此,一次 Run 里可能发生:

text 复制代码
Model Call #1 → 查询订单
Tool Result  → 订单存在,尚未发货
Model Call #2 → 取消订单
Tool Result  → 需要人工审批
Pause        → 等待负责人批准
Resume       → 执行取消
Model Call #3 → 生成最终答复
Complete

如果只记录最后一条文本,我们会丢掉真正决定任务结果的过程:模型为什么调用某个工具、工具返回什么、动作是否经过审批、运行从哪里恢复。

2. 最小循环是"决策---执行---反馈---更新"

把具体 SDK 的类名拿掉,最小 Agent loop 只有两个反复发生的核心步骤:

  1. Model Call:模型根据当前 Context 返回 Final Output 或 Tool Call。
  2. Tool Execution:应用执行工具,把 Tool Result 交给下一轮。

Runtime 负责两者之间的分支、状态与边界:

flowchart LR %% 样式定义 classDef runtime fill:#e8f4ff,stroke:#2478e5 classDef model fill:#f0f9eb,stroke:#67c23a classDef tool fill:#fdf6ec,stroke:#e6a23c classDef endnode fill:#fef0f0,stroke:#f56c6c A["读取 State 并组装 Context"]:::runtime B["Model Call"]:::model C{模型输出} D["Complete"]:::endnode E["校验 Tool 与参数"]:::tool F{是否需要审批} G["保存 State 并 Pause"]:::runtime H["Tool Execution"]:::tool I["记录 Tool Result 并更新 State"]:::runtime J["Fail 或受控修复"]:::endnode K["Cancel / Fail"]:::endnode %% 主线正向链路,从上至下分层排布避免交叉 A --> B B --> C %% 分支1:直接结束 C -- Final Output --> D %% 分支2:工具调用链路 C -- Tool Call --> E E --> F F -- 是 --> G F -- 否 --> H H --> I I -.循环回流.-> A %% 异常分支统一右下排布,不横穿主线 E -- 校验失败 --> J H -- 执行异常 --> J A -- 取消或超限 --> K

这里刻意不用"模型思考了什么"解释循环。工程上真正能够记录和复现的是 Model Request、Model Response、Tool Call、Tool Result、State Update、Approval 和 Error。模型内部如何形成输出,不影响 Runtime 对这些公开事件的处理。

3. 环境反馈让下一步建立在事实上

模型产生 cancel_order 时,只能说明它根据已有 Context 判断取消动作可能合适。真实环境可能返回完全不同的结果:

  • 订单取消成功;
  • 订单已经发货,不能取消;
  • 订单不属于当前用户;
  • 订单服务暂时不可用;
  • 动作超过自动处理额度,需要人工审批。

这些结果会改变下一步路径。取消成功后可以生成确认信息;已经发货时要解释限制或转入退货流程;服务超时可能进入受控重试;需要审批时则保存现场并暂停。

Agent 的动态性不是来自"模型可以自由发挥",而是来自下一步路径由模型输出和环境反馈共同决定 。环境结果为模型提供 ground truth,Runtime 则保证这个结果以正确格式进入下一轮。^4^

4. Planning 可以存在,但不是固定方框

复杂任务可能需要显式计划。例如,一个采购 Agent 可以先输出待办列表,再逐项查询库存、比较供应商并发起审批。计划也可以保存在 State 中,执行后更新完成状态。

但在取消订单这类短任务里,模型完全可以每轮根据当前 State 与 Tool Result 选择下一步,不必先调用独立 Planner。现有主流实现也没有共同要求每个 Agent 都必须配置一个 Planning 组件:有的把它视为模型行为,有的用结构化计划实现,有的通过 Orchestrator 或 Graph 显式编排。

更准确的说法是:Planning 是一种可以显式化的运行行为或编排模式,不是最小 Agent 必须拥有的独立组件。 如果系统展示计划,应展示模型明确输出的计划或应用记录,而不是把生成的解释当作模型真实内部推理的完整披露。

三、循环为什么离不开 State?

循环解决了"结果回来后继续调用"的流程问题,但它无法回答两个更关键的工程问题:每一轮应该带上哪些信息? 以及 中断后如何从断点原样恢复?

若每次都把完整历史、所有工具结果塞给模型,Context 会越来越长,敏感信息也可能被不必要地暴露。若什么都不保存,下一轮又会失去任务进度。要拆解这对矛盾,需要区分 Context、State、Session / Thread 和 Memory。下面是本文采用的工作定义,不是某一家厂商的统一术语体系。

1. Context 是本轮模型真正看见的信息

Context 是一次 Model Call 实际收到的信息集合,通常包括 Instructions、经过选择的消息、可用工具定义、与当前决策有关的 State,以及按需检索出的资料。

它不是数据库中所有可用数据,也不等于完整会话历史。Context Window 有容量限制,更重要的是,混入大量无关信息会稀释当前任务真正需要的信号。Context Engineering 的工作,就是决定每一轮把哪些信息交给模型。^5^

OpenAI Agents SDK 也明确区分 Conversation History 与 Run Context:前者会进入模型,后者可以只供应用代码和工具使用。^6^ 当前用户的数据库连接、鉴权对象和内部日志句柄属于 Runtime 依赖,没有必要因为它们"与运行有关"就发送给模型。

2. State 保存任务事实与恢复位置

State 是应用维护的任务事实与运行进度。取消订单时,它可以包含:

typescript 复制代码
interface AgentState {
  runId: string;
  status: "running" | "paused" | "completed" | "failed" | "cancelled";
  turnCount: number;
  events: Array<ModelEvent | ToolEvent>;
  pendingApproval?: {
    call: ToolCall;
    decision?: "approved" | "rejected";
  };
  lastError?: string;
}

State 中既有可能进入下一轮 Context 的信息,例如最近一次 Tool Result;也有只供 Runtime 使用的信息,例如重试次数、审批决定和内部错误。State 是运行拥有的数据,Context 是本轮选择给模型看的数据。

cancel_order 等待审批时,应用应保存 Pending Tool Call、当前轮次和已有事件。审批完成后从这份 State 恢复同一次 Run,而不是把"批准了"伪装成一个全新的用户问题。官方 Agent Runtime 对审批流程也采用"中断并返回可恢复 State"的模式。^7^^8^

3. Session / Thread 组织连续运行

Session 或 Thread 更接近一个组织容器或定位标识:它把多次调用、消息历史和 Checkpoint 归到同一条连续交互中。不同框架的具体语义并不相同,不能把 OpenAI Session 与 LangGraph Thread 当成完全相同的 API。

可以用一个简单关系理解:

名词 作用
State 是某个时刻保存了什么
Checkpoint 是 State 在特定步骤的快照
Session / Thread 帮助 Runtime 找到属于同一连续交互的历史与快照

LangGraph 通过 Checkpointer 保存 Thread 内的 Graph State,用于对话延续、人工介入和故障恢复;OpenAI Agents SDK 则可以通过 Session、Conversation ID 或 Response ID 延续不同类型的会话状态。^3^^9^

4. Memory 保存未来可能再用的信息

Memory 通常指跨步骤或跨会话保留、并在未来按需取回的信息。例如:

  • "用户偏好短信通知"可以进入长期 Memory;
  • "用户常用收货地址"可以在授权后跨会话读取;
  • "订单 123 正等待取消审批"则应属于当前 Run State。

信息被写入 Memory,不代表模型下一轮自动知道它。外部 Memory 必须经过检索、筛选并放入当前 Context,才能直接影响本轮输出。Anthropic 对 Agent Context 的讨论,以及 LangGraph 对 Checkpointer 与 Store 的区分,都体现了这一点:前者处理当前 Thread 的状态连续性,后者保存跨 Thread 的应用数据。^5^^9^

四者的关系可以画成:

flowchart LR %% 样式分类 classDef memory fill:#e1f5fe,stroke:#0288d1 classDef session fill:#f3e5f5,stroke:#7b1fa2 classDef state fill:#fff8e1,stroke:#f57c00 classDef runtime fill:#f1f8e9,stroke:#388e3c classDef model fill:#fef2f2,stroke:#dc2626 %% 数据源 M[(Long-term Memory)]:::memory H[(Session History)]:::session T[(Current State)]:::state %% 中间流程节点 S[Context Builder]:::runtime C[Model Context]:::runtime L[Model Call]:::model O[Model Output]:::model R[Tool Result]:::state U[State Update]:::runtime %% 数据流走向(分层排布,杜绝连线交叉) M -- 按需检索筛选 --> S H -- 裁剪/摘要压缩 --> S T -- 提取本轮相关事实 --> S S --> C C --> L L --> O O --> U R --> U %% 状态回流 & 长期记忆落库分支 U -.更新当前任务进度.-> T U -- 识别长期有效数据,异步写入 --> M
概念 保存什么 典型生命周期 是否直接对模型可见 订单案例
Context 本轮推理所需的选定信息 一次 Model Call 当前请求、可用工具、最近 Tool Result
State 当前任务事实、进度和控制信息 一次 Run,可持久化恢复 按需选择 待审批调用、轮次、执行结果
Session / Thread 连续交互的历史与状态定位 多次调用或多个 Run 其中部分可进入 Context 同一客服会话或任务线程
Memory 未来可能复用的偏好、事实或经验 跨 Run / 跨 Session 否,需取回后进入 Context 用户通知偏好

这个区分的价值不在术语本身,而在数据边界:哪些信息必须让模型看到,哪些只应由 Runtime 保管,哪些需要跨会话保存。

四、谁决定继续、暂停与失败?

模型可以返回 Final Output,也可以建议下一步动作,但 Agent Run 的生命周期不能只交给模型决定。应用还要处理审批、错误、预算、超时和用户取消。

本文用 Continue、Complete、Pause、Fail 和 Cancel 描述这些状态。它们是便于解释 Runtime 的工程归纳,不是所有 SDK 共同采用的标准枚举。

状态 典型触发条件 是否终态 是否可恢复 订单案例
Continue 获得 Tool Result,需要再次调用模型 查询订单成功,继续判断能否取消
Complete 得到最终输出,且没有后续工具工作 通常不再继续 取消成功并生成答复
Pause 等待审批、用户信息或外部事件 等待负责人批准取消
Fail 不可恢复错误、校验拦截或达到限制 视补偿策略而定 参数无效、重试耗尽
Cancel 用户或系统主动终止 通常需显式重开 用户撤回取消请求

1. Complete:运行结束不自动等于业务成功

在最小循环里,模型返回 Final Output 且没有更多 Tool Call,可以作为 Run 的停止点。^3^ 但"模型不再调用工具"和"业务目标已经成功"不是永远等价。

假如订单服务返回"已经发货,无法取消",模型可以正确解释原因并结束 Run。此时运行本身正常完成,取消订单这一业务目标却没有达成。生产系统仍需要独立的任务结果或业务校验,不能只用 finalOutput !== null 统计成功率。

2. Pause:需要外部决定时保存现场

取消、退款、发布、删除等有副作用的动作,常常不能由模型输出直接触发。Runtime 可以让模型继续提出动作,但在执行前根据 Policy 暂停。

暂停时应返回待处理事项和可恢复 State。审批人批准或拒绝后,应用从同一份 State 继续:批准则执行原 Tool Call;拒绝则把拒绝结果记录为 Tool Result,让模型决定如何回复用户。这个过程中不需要重新让模型生成一次取消请求,也不应把 Pause 当成运行失败。^7^^8^

3. Fail:失败处理不能藏在无限重试里

Agent loop 会放大错误处理的重要性,因为每一轮都有新的失败入口:

  • 模型输出无法解析;
  • 工具名称不存在或参数不合法;
  • Guardrail 阻止输入、输出或动作;
  • Tool Executor 超时;
  • 外部服务返回业务错误;
  • 运行达到最大轮次、重试次数或预算。

maxTurns 不是性能优化,而是一条基本控制边界。没有它,模型和工具可能在相同结果之间反复往返。工具失败也不能一律自动重试:查询类动作通常可以安全重试,取消订单等有副作用的动作必须先设计幂等键和结果核验,否则一次网络超时后的自动重试,可能因缺乏幂等键而造成重复执行(如重复扣款或重复取消)。

4. Cancel:应用必须保留强制停止权

用户撤回请求、上游连接断开、运行超时或预算耗尽时,Runtime 都需要能够终止循环。模型可以生成"任务已经完成",也可以建议停止,但应用仍应保留独立的取消信号。

这也是"Agent 自主执行"的边界:自主意味着模型可以在授权范围内动态选择下一步,不意味着 Runtime 放弃控制。运行时掌握审批、资源限制、超时和取消,才能让模型决策进入一个可管理的系统。

stateDiagram-v2 direction LR [*] --> Running : 启动Agent Run %% 主循环迭代 Running --> Running : Tool Result → 组装上下文继续执行 %% 人工审批暂停分支 Running --> Paused : 需要人工审批 Paused --> Running : 审批通过/驳回,恢复执行 %% 模型主动正常结束 Running --> Completed : Model 返回 Final Output %% 异常失败分支 Running --> Failed : 执行异常 / 内容拦截 / 资源超限(超时/预算耗尽) %% 外部强制终止(用户撤回、连接断开等系统取消信号) Running --> Cancelled : 用户撤回 / 上游断连 / 主动取消信号 %% 全部终止态收敛至结束 Completed --> [*] Failed --> [*] Cancelled --> [*]

五、用最小代码复原一个 Agent Runtime

前面分别拆开了 Tool Calling、执行循环、State 和生命周期。把它们放回同一段代码,可以更清楚地看到 Agent SDK 的 run() 隐藏了什么。

下面的 TypeScript 示例不绑定具体模型或框架。callModelexecuteToolsaveStateapprovalPolicy 由外部注入,循环只负责编排它们。为突出主线,本示例假定每轮单次 Tool Call;实际生产环境需额外扩展支持并行多工具调用与结果聚合。

typescript 复制代码
type RunStatus =
  | "running"
  | "paused"
  | "completed"
  | "failed"
  | "cancelled";

type ToolCall = {
  type: "tool_call";
  callId: string;
  name: string;
  arguments: Record<string, unknown>;
};

type ModelDecision =
  | { type: "final"; content: string }
  | ToolCall;

type AgentEvent =
  | { type: "user"; content: string }
  | { type: "model"; decision: ModelDecision }
  | { type: "tool"; callId: string; result: unknown };

type PendingApproval = {
  call: ToolCall;
  decision?: "approved" | "rejected";
};

type AgentState = {
  runId: string;
  status: RunStatus;
  turnCount: number;
  events: AgentEvent[];
  pendingApproval?: PendingApproval;
  finalOutput?: string;
  lastError?: string;
};

type RuntimeDependencies = {
  callModel: (events: AgentEvent[]) => Promise<ModelDecision>;
  executeTool: (call: ToolCall) => Promise<unknown>;
  requiresApproval: (call: ToolCall) => boolean;
  saveState: (state: AgentState) => Promise<void>;
  signal?: AbortSignal;
  maxTurns: number;
};

async function appendToolResult(
  state: AgentState,
  call: ToolCall,
  result: unknown
) {
  state.events.push({
    type: "tool",
    callId: call.callId,
    result
  });
}

async function runAgent(
  state: AgentState,
  deps: RuntimeDependencies
): Promise<AgentState> {
  state.status = "running";

  try {
    while (state.turnCount < deps.maxTurns) {
      if (deps.signal?.aborted) {
        state.status = "cancelled";
        await deps.saveState(state);
        return state;
      }

      // 恢复时先处理暂停中的原 Tool Call,避免让模型重复生成。
      if (state.pendingApproval) {
        const pending = state.pendingApproval;

        if (!pending.decision) {
          state.status = "paused";
          await deps.saveState(state);
          return state;
        }

        if (pending.decision === "rejected") {
          await appendToolResult(state, pending.call, {
            ok: false,
            reason: "rejected_by_reviewer"
          });
        } else {
          const result = await deps.executeTool(pending.call);
          await appendToolResult(state, pending.call, result);
        }

        state.pendingApproval = undefined;
        await deps.saveState(state);
        continue; // 工具结果已回填,重新进入循环调用模型生成后续回复
      }

      state.turnCount += 1;
      const decision = await deps.callModel(state.events);
      state.events.push({ type: "model", decision });

      if (decision.type === "final") {
        state.finalOutput = decision.content;
        state.status = "completed";
        await deps.saveState(state);
        return state;
      }

      if (deps.requiresApproval(decision)) {
        state.pendingApproval = { call: decision };
        state.status = "paused";
        await deps.saveState(state);
        return state;
      }

      const result = await deps.executeTool(decision);
      await appendToolResult(state, decision, result);
      await deps.saveState(state);
    }

    state.status = "failed";
    state.lastError = `maxTurns exceeded: ${deps.maxTurns}`;
    await deps.saveState(state);
    return state;
  } catch (error) {
    state.status = "failed";
    state.lastError =
      error instanceof Error ? error.message : "unknown runtime error";
    await deps.saveState(state);
    return state;
  }
}

async function review(
  state: AgentState,
  decision: "approved" | "rejected",
  deps: RuntimeDependencies
) {
  if (!state.pendingApproval) {
    throw new Error("No pending approval");
  }

  state.pendingApproval.decision = decision;
  await deps.saveState(state);
  return runAgent(state, deps);
}

这段代码没有实现具体模型与订单服务,却保留了最小 Runtime 的关键机制:

  1. ModelDecision 把 Final Output 与 Tool Call 变成显式分支。
  2. while 循环让 Tool Result 能够进入下一轮 Model Call。
  3. AgentState 保存事件、轮次、审批点与运行状态。
  4. pendingApproval 让 Run 从同一 Tool Call 恢复,避免重新生成动作。
  5. maxTurnsAbortSignalcatch 提供失败与取消出口。

为了突出主线,示例省略了 Tool Registry、Schema Validation、幂等键、分布式锁、超时重试、Checkpoint 版本和 Trace。这些不是可有可无的细节,而是生产化 Runtime 需要继续补齐的能力;本篇只证明它们应该接入执行循环的哪个位置。

OpenAI Agents SDK、LangChain / LangGraph 等框架会替我们封装模型适配、Tool Dispatch、循环、Session、Checkpoint、审批或 Trace 的一部分。框架降低了实现成本,但不会消除这些机制。出现重复调用、状态丢失、越权执行或无法恢复时,排查仍然要回到几个基本问题:

  • 模型实际返回了什么?
  • Runtime 选择了哪个分支?
  • 工具是否真正执行,结果是否正确回填?
  • State 在哪一步更新和持久化?
  • Run 为什么继续、暂停或结束?

理解循环不是为了重复造一个 Agent SDK,而是为了知道框架在替我们承担什么,以及系统出错时应该从哪里找证据。

总结:Agent 的核心不是"拥有工具",而是"运行得起来"

回到订单 123。模型返回 cancel_order 时,只提出了动作;Runtime 还要校验参数与权限,在风险边界前暂停审批,调用订单服务,并把真实结果交给下一轮。State 保存这段过程,让 Run 可以暂停和恢复;最大轮次、错误处理和取消信号则防止它无限运行或越过系统边界。

由此可以给出本文的工作定义:

Agent 是一个由 Runtime 组织的应用级执行系统:模型根据当前 Context 产生下一步决策,应用执行动作并更新 State,再依据环境反馈持续推进,直到任务完成、暂停、失败或取消。

这一定义是根据多家官方运行机制做出的工程归纳,不是行业唯一标准。它强调的也不是组件数量,而是四件事能否连起来:模型决策、外部执行、状态更新和边界控制。

这篇文章可以先带走三个判断:

  1. Tool Calling 只是协议接口,不是完整 Agent。
  2. Agent loop 的核心,是 Model Call 与 Tool Execution 根据环境反馈反复推进。
  3. State 与 Runtime 边界决定这个循环能否受控、可恢复地运行。

下一篇会在这个最小执行循环之上,继续讨论 Skill、Workflow、MCP 等能力如何接入,又该如何编排。


Footnotes

  1. OpenAI, "Function calling", platform.openai.com/api/docs/gu... (official-doc) 2

  2. Anthropic, "Tool use with Claude", docs.anthropic.com/en/docs/bui... (official-doc) 2

  3. OpenAI, "Running agents", platform.openai.com/api/docs/gu... (official-doc) 2 3

  4. Anthropic, "Building effective agents", www.anthropic.com/engineering... (official-blog) 2

  5. Anthropic, "Effective context engineering for AI agents", www.anthropic.com/engineering... (official-blog) 2

  6. OpenAI, "Agent definitions", platform.openai.com/api/docs/gu... (official-doc)

  7. OpenAI, "Results and state", platform.openai.com/api/docs/gu... (official-doc) 2

  8. OpenAI, "Guardrails and human review", platform.openai.com/api/docs/gu... (official-doc) 2

  9. LangChain, "LangGraph persistence", docs.langchain.com/oss/python/... (official-doc) 2

相关推荐
钱六两5 小时前
#3、SpringAI 接入deepSeek大模型(喂饭版)
java·spring boot·ai编程
小村儿7 小时前
连载14-实战篇--一个半月,我一个人和 Claude Code 搭出一套数字人工程
前端·后端·ai编程
阿里云云原生7 小时前
AI 时代的 FinOps 必修课:如何利用 Credits 刻度实现大模型流量的精细化治理?
ai编程
名不经传的养虾人8 小时前
从0到1:企业级AI项目迭代日记 Vol.71|系统显示正常,但实际上什么都没发生
数据库·人工智能·ai编程·ai工作流·企业ai
程序员秋天9 小时前
用Spring AI实现多轮对话记忆,别再让AI每次都"失忆"
agent·ai编程
SyMind9 小时前
如何做好 AI 的挂件
llm·ai编程
林小果19 小时前
用 Codex 做一个 API 地址诊断器:Claude Code、Codex、Gemini CLI 的 /v1 排错实战
api·ai编程·codex·claude code·gemini cli·base url·linkagi
就叫飞六吧10 小时前
claude agent、skill 结构参考
ai编程
HjhIron11 小时前
在浏览器中跑DeepSeek-R1:用React+WebGPU实现端侧AI推理
前端·ai编程