Run 终止哲学(INV-TERM-01)

wesgine 的 Run 终止设计:无限制,有韧性。引擎不因 counter 阈值主动终止正常运行的任务。


核心原则

引擎不主动终止。

传统 Agent 框架的做法是设置 max_iterations 或 max_tokens,超了就停。wesgine 认为这是错的:


合法终止途径

Run 只在以下情况终止:

途径说明来源
模型自然结束模型回复不含 tool_calls正常
用户中断POST /sessions/{sid}/interrupt用户主动
CycleDetector完全相同的操作 + 完全相同的结果引擎内建
ErrorStreak HITL 超时连续错误 → HITL → 用户不响应引擎内建
BudgetCheckFn外部预算检查返回 Exhausted应用层
Cell StopCell 生命周期管理管理操作

已废弃的终止路径

以下终止机制已被移除:

废弃机制为什么移除
PlanStall无法区分"思考"和"卡住"
ProgressTracker与 CycleDetector 重叠
PlanningPhaseHardLimit任意截断计划阶段
max_iterations 硬限制与终止哲学矛盾

CycleDetector:唯一的引擎内终止源

CycleDetector 检测可证明的死循环:完全相同的操作 + 完全相同的结果。

两阶段协议

首次 CycleTerm
  ↓
自愈(注入纠正消息 + 重置 counter)
  ↓ 自愈失败
第二次 CycleTerm
  ↓
HITL(问用户怎么办)
  ↓ 超时 60s
终止 + 保存进度

工具分类

类别阈值特点
Exploration(read/grep/search)高阈值
Action(edit/write/exec)中等阈值
Plan低阈值

参数变化时 streak /= 2(progress-aware halving)。


ErrorStreak:伪进展检测

与 CycleDetector 互补:

CycleDetectorErrorStreak
检测相同操作重复不同操作持续失败
触发自愈 → HITL直接 HITL
终止HITL 超时HITL 超时

BudgetCheckFn:应用层预算

应用层可注入 BudgetCheckFn:

AppRunRequest{
    BudgetCheckFn: func(usage BudgetUsage) BudgetDecision {
        if usage.TotalTokens > limit {
            return BudgetExhausted
        }
        return BudgetOK
    },
}

返回 BudgetExhausted 时 Run 终止。


Grace Call

预算即将耗尽时,引擎给模型最后一次 LLM 调用:

这是终止哲学的体现:即使要停,也给模型收尾的机会。


Run 限制字段

虽然不主动终止,Run 仍有可观测的限制字段:

字段说明是否触发终止
TokenBudgetToken 预算❌ 仅事件通知
TurnBudget轮次预算❌ 仅事件通知
TimeBudget时间预算❌ 仅事件通知
MaxTokenEstimate最大 Token 估算❌ 上下文压缩参考

这些限制用于:


终态事件保证(INV-TERM-04)

无论哪种终止路径,Run 必须发出终态事件:

事件终止原因
EventDone正常完成 / context_cancelled
EventError错误终止
EventInterrupted用户中断

缺少终态事件 → terminal guard 合成虚假 EventError。


相关文档