Skip to content
Zegging's Tech Blog
Go back

一种 LLM Agent Runtime 的形式化模型

RtSBMtΠvendor,tDtCatX(Et,δt)OtURt+1R_t \xrightarrow{\,S_B\,} M_t \xrightarrow{\,\Pi_{\mathrm{vendor},t}\,} D_t \xrightarrow{\,C\,} a_t \xrightarrow{\,X(E_t,\delta_t)\,} O_t \xrightarrow{\,U\,} R_{t+1}

这条复合链描述了一次完整的 Agent Loop:

Runtime 状态生成模型上下文;模型产生输出;Controller 将输出转换为动作;动作作用于外部环境并产生观察;观察最终更新 Runtime 状态。

Runtime 状态:RtR_t

Rt=(Lt,Vt)R_t=(L_t,V_t)

RtR_t 是第 tt 轮开始时,Agent Runtime 保存并可访问的全部内部状态。它可以存储在内存、文件、数据库或对象存储中,但不包含外部环境本身。

  • LtL_t:append-only 事件日志,记录 message、模型输出、tool call、工具原始结果、异常、权限变化和连接变化。
  • VtV_t:当前有效视图,由事件日志归并得到。
Vt=Fold(Lt,Kt)V_t=\operatorname{Fold}(L_t,K_t)

LtL_t 回答“曾经发生过什么”,VtV_t 回答“根据目前已知事件,现在什么仍然有效”。例如,权限授予和权限撤销都会保留在 LtL_t 中,而 VtV_t 只呈现当前有效权限。

VtV_t 不是外部世界的绝对真相。MCP connected 只能表示 Runtime 最近一次观察到连接成功,不保证服务此刻仍然在线。

模型上下文:MtM_t

Mt=SB(Rt),Tokens(Serialize(Mt))BM_t=S_B(R_t), \qquad \operatorname{Tokens}(\operatorname{Serialize}(M_t))\le B

MtM_t 专指第 tt 轮实际进入 LLM 推理的上下文,例如 system message、user message、tool result 和 tool definitions。

SBS_B 是受到 token budget BB 限制的上下文构造策略,可以选择历史、执行 compaction、裁剪大型工具结果或装载当前工具定义。

SBS_B 应保持为纯函数:它只能使用已经存在于 RtR_t 中的信息,不能在构造上下文时偷偷读取文件、查询网络或探测 MCP。新的环境信息必须先通过显式动作产生 observation,再写入 Runtime。

因此:

  • 信息不在 RtR_t:Runtime 已经没有这条信息;
  • 信息在 RtR_t 但不在 MtM_t:本轮没有装载;
  • 信息进入 MtM_t 但未被正确使用:属于模型侧决策问题。

厂商模型:Πvendor,t\Pi_{\mathrm{vendor},t}

模型侧的完整表达是:

Dtπθt,λt(Mt)D_t\sim\pi_{\theta_t,\lambda_t}(\cdot\mid M_t)

θt\theta_t 表示模型权重、版本、隐藏策略和推理实现,λt\lambda_t 表示 temperature、top-p 等推理参数。由于 Agent Runtime 无法观察和控制全部模型侧状态,可以将其化简为厂商黑盒:

πθt,λt完整模型侧描述Πvendor,tRuntime 侧黑盒化简\underbrace{\pi_{\theta_t,\lambda_t}}_{\text{完整模型侧描述}} \equiv \underbrace{\Pi_{\mathrm{vendor},t}}_{\text{Runtime 侧黑盒化简}}

于是:

DtΠvendor,t(Mt)D_t\sim\Pi_{\mathrm{vendor},t}(\cdot\mid M_t)

DtD_t 是模型返回的文本、tool call、结构化输出或拒绝。这里使用 \sim,因为模型输出本质上是条件概率分布中的一次生成结果。

Controller 与动作:CCata_t

at=C(Dt,Vt)a_t=C(D_t,V_t)

模型请求调用工具,不代表工具一定会被执行。Controller 还需要根据 VtV_t 检查:

  • 工具是否已经注册;
  • 参数是否符合当前 schema;
  • 权限是否允许;
  • 是否需要人工批准;
  • 是否触发预算或安全策略。

因此同一个 DtD_t 在不同 Runtime 状态下,可以产生执行、拒绝、请求人工介入或解析失败等不同动作。

环境与观察:EtE_tOtO_t

(Et+1,Ot)=X(Et,at,δt)(E_{t+1},O_t)=X(E_t,a_t,\delta_t)

EtE_t 是 Runtime 之外的真实环境,例如操作系统、代码仓库、数据库、网络、MCP Server 和其他协作者。δt\delta_t 是 Runtime 无法控制的扰动,例如网络中断、进程崩溃或并发修改。

OtO_t 是 Runtime 实际获得的观察,不一定完整描述 Et+1E_{t+1}。例如请求超时后,Agent 可能无法判断远端是否已经完成了有副作用的操作。

Runtime 更新:UU

Runtime 的关键状态转移是:

Rt+1=U(Rt,Ot)R_{t+1}=U(R_t,O_t)

UU 接收当前 Runtime 状态 RtR_t 与本轮观察结果 OtO_t,生成下一轮状态 Rt+1R_{t+1}。它负责决定新信息如何写入、已有状态如何更新,以及哪些事实、计划、权限或连接状态仍然有效。

U:R×ORU:\mathcal{R}\times\mathcal{O}\rightarrow\mathcal{R}

因此,UU 不是简单地保存工具结果,而是 Agent Runtime 的状态演化策略。append-only event log 与当前有效视图只是 UU 的一种实现。

一轮执行可以先记录为:

et=Mt,Dt,at,Ot,εte_t=\langle M_t,D_t,a_t,O_t,\varepsilon_t\rangle

其中 εt\varepsilon_t 表示 Runtime、Controller 或工具执行错误。随后:

Lt+1=Append(Lt,et),Vt+1=Fold(Lt+1,Kt+1),Rt+1=U(Rt,Ot)=(Lt+1,Vt+1).\begin{aligned} L_{t+1}&=\operatorname{Append}(L_t,e_t),\\ V_{t+1}&=\operatorname{Fold}(L_{t+1},K_{t+1}),\\ R_{t+1}&=U(R_t,O_t)=(L_{t+1},V_{t+1}). \end{aligned}

这使模型调用、工具执行、错误与权限变化都可以被审计和回放。

一个简短例子

模型根据 MtM_t 生成 write_file tool call。Controller 查询 VtV_t 后发现写权限已被撤销,因此:

at=C(Dt,Vt)=Reject(permission revoked)a_t=C(D_t,V_t)=\operatorname{Reject}(\text{permission revoked})

这里可以清晰地区分:

  • 模型提出了什么:DtD_t
  • Runtime 实际允许什么:ata_t
  • Runtime 最近知道什么:VtV_t
  • 外部世界真实是什么:EtE_t

Share this post on:

Previous Post
如果把 Agent 的 Context 当成一块需要 GC 的内存
Next Post
新的潮流“创建 Loop 来运行 Agent”,Loop 反而是最不重要的那一环