为Loop Engineering装刹车

一、相关知识

从Prompt Egineering->Context Engineering->Loop Engineering,AI应用的构建范式正在发生深刻转移。本质是:将系统的控制权从"概率性的大模型"剥离,交还给"确定性的工程系统"。

大模型是油门,提供智能和创意; Loop系统是刹车与方向盘,负责兜底、纠偏、导航。

Loop Engineering愿景:不用在手动敲Prompt,而是设计一个自动发现工作、分配任务、交叉检查、持久记忆的闭环系统。


二、微观执行与宏观编排

拆解两个概念:

  • Agent Loop(微观执行层):包裹在大模型外围的 while True 逻辑,解决单个 Agent 怎么稳定跑完一次任务这一问题,它是发动机。
  • Loop Engineering(宏观编排层):多 Agent 调度、外部工具对接、长期状态记忆的系统架构,解决怎么让 Agent 体系脱离人工值守、长期自主运转 ,它是整车工程。

三、生产级Agent Loop遵守的工程准则

  • 硬边界熔断和独立裁决:不依赖模型主动停下,终止权必须交给代码硬预算与独立校验逻辑。
python 复制代码
@dataclass
class HardBudget:
    max_turns: int = 50       # 最多多少轮
    max_seconds: int = 600    # 超时
    max_tokens: int = 200_000 # token 预算
    max_cost_usd: float = 5.0 # money 预算

指纹去重并且将进度哈希(防止死循环和幽灵循环):同一参数调用超阈值判死循环;连续多轮上下文哈希不变判空转。

python 复制代码
def detect_infinite_retry(run: AgentRun, call: ToolCall, *, repeat_threshold: int = 5) -> tuple[bool, str]:
    fp = sha256(json.dumps({"name": call.name, "params": call.params}, sort_keys=True))
    count = run._fingerprint_counter.get(fp, 0) + 1
    run._fingerprint_counter[fp] = count
    if count > repeat_threshold: return True, f"Dead loop: '{call.name}' called {count}×"
    return False, ""

class ProgressMonitor:  # 幽灵循环检测:内部维护滑动窗口 hash,连续不变则 raise
    def check(self, run: AgentRun) -> None: ...
  • 提议-裁决分离与权限门禁:将模型降级为提议者,用工程代码做最终决策和权限拦截。
python 复制代码
def validate_tool_call(call: ToolCall, registry: ToolRegistry) -> tuple[bool, str]:
    if call.name not in registry: 
      return False, f"工具 {call.name} 不存在"
    # ... 参数类型强校验略
python 复制代码
@dataclass
class ToolCallPolicy:
    highRiskTools: set[str] 
    def decide(self, call: ToolCall, user_context: UserContext) -> str:
        if call.name in self.highRiskTools: 
          return "ask" 
        # 权限上下文注入:强制追加当前用户的数据权限范围
        call.params["scope"] = user_context.data_scope 
        return "allow"
  • 显示状态机与上下文防挤压:拒绝隐式循环,用分层上下文防止指令失忆,让系统可观测、可调试。
python 复制代码
class RunState(StrEnum):
    RUNNING = "running"; 
    SUSPENDED = "suspended"; 
    COMPLETED = "completed"
    FAILED = "failed"; 
    CANCELLED = "cancelled"

class RunPhase(StrEnum):
    PREPARE = "prepare"   # 组装上下文(L0-L3分层防挤压)
    THINK = "think"       # 等模型输出
    DECIDE = "decide"     # 独立裁决意图
    EXECUTE = "execute"   # 执行工具(串行/并行由 ToolRunner 决定)
    DONE = "done"         # 目标达成,循环终止
  • 持久化可恢复:用细粒度的CheckPoint替代聊天记录,确保系统在崩溃后可以原地续跑
python 复制代码
class CheckpointStore(Protocol):
    async def save(self, run: AgentRun) -> None: ...   # 框架保证原子写入
    async def load(self, run_id: str) -> AgentRun | None: ...

# 在 AgentLoop 构造时注入;每轮 EXECUTE 结束后自动触发
loop = AgentLoop(..., checkpoint_writer=store.save, checkpoint_loader=store.load)

Checkpoint 具体存在哪里?

常见的存储方案有以下几种:

存储介质 适用场景 特点
PostgreSQL / MySQL 生产环境中的 Agent 状态持久化 事务可靠,支持按会话或任务查询
Redis 高频状态缓存、短期恢复 读写快,但需要配置持久化;通常不单独承担长期可靠存储
SQLite 单机 Agent、个人助理应用 部署简单,适合轻量场景
对象存储 大型上下文、文件、执行产物 适合保存大体积数据,通常由数据库记录引用

例如,你可以在 PostgreSQL 中设计一张 agent_checkpoints 表:

agent_checkpoints 表结构示例

|-----------------|---------------------|
| 字段 | 含义 |
| thread_id | 会话或任务的唯一标识 |
| checkpoint_id | 检查点 ID,区分不同版本 |
| state | 当前执行状态,例如消息、变量、任务进度 |
| step | 执行到哪个节点或步骤 |
| status | 运行中、等待、完成或失败 |
| created_at | 检查点创建时间 |

这只是一个简化的自定义设计,实际框架可能会采用不同的数据结构,也可能将状态拆分为多张表。

  • 同步和隔离:在概率模型之上构建确定性的协调机制,用工作空间隔离和串行化写入防止并发冲突

四、完整落地代码

python 复制代码
# ── 所有运行状态的唯一容器(宪法三:显式状态机) ──
@dataclass
class AgentRun:
    run_id: str; task: str
    state: RunState = RunState.RUNNING
    phase: RunPhase = RunPhase.PREPARE
    turn_count: int = 0
    input_tokens: int = 0; output_tokens: int = 0; cost_usd: float = 0.0
    messages: list[Message] = field(default_factory=list)
    tool_history: list[ToolCall] = field(default_factory=list)
    pending_tool_call: ToolCall | None = None
    _fingerprint_counter: dict[str, int] = field(default_factory=dict)  # 死循环检测
    _retry_counter: dict[str, int] = field(default_factory=dict)        # 红绿灯重试计数
    fault_class: str | None = None; last_error: str | None = None       # 崩溃现场

# ── 5 条宪法的汇聚点:AgentLoop ──
class AgentLoop:
    def __init__(self, llm, dispatcher, *, budget, checkpoint_writer, checkpoint_loader, ...):
        self._runner = ToolRunner(dispatcher)   # 宪法五:串行/并行路由 + 红绿灯重试
        self._progress = ProgressMonitor()      # 宪法一:幽灵循环检测

    async def _loop_events(self, run: AgentRun):
        while True:
            # 宪法一:硬边界熔断 + 幽灵循环检测(每轮最先执行,越权必断)
            check_budget(run, self._budget)
            self._progress.check(run)

            # 宪法三:上下文分层防挤压(系统指令 > 当前状态 > 知识 > 历史)
            # ContextManager 负责:超长时摘要压缩历史、系统区永不压缩
            run.phase = RunPhase.PREPARE
            system, messages_to_send = await self._context_manager.prepare(run)

            # 宪法三:THINK 阶段 → 将组装好的上下文送给 LLM
            run.phase = RunPhase.THINK
            response = await self._llm.complete(messages_to_send, system=system, tools=...)
            run.turn_count += 1; run.add_tokens(response)

            # 宪法一 & 宪法二:独立裁决(防幻觉终止)
            run.phase = RunPhase.DECIDE
            if response.stop_reason == "end_turn":
                # 铁律:模型说做完不算,goal_verifier 验证才算。
                # 宏观层面 Claude Code 的 Stop Hook 也是同理:
                # 将终止权从"执行模型"交给"校验模型"(Maker/Checker 分离)。
                if await self._goal_achieved(run):
                    run.state = RunState.COMPLETED; yield RunCompletedEvent(run); return
                run.messages.append(Message(role="user", content="目标尚未达成,请继续。"))
                continue

            # 宪法二 & 宪法五:批量执行(含死循环检测、幂等注入、审批拦截、并行/串行、红绿灯重试)
            run.phase = RunPhase.EXECUTE
            async for event in self._runner.run_batch(run, response.tool_calls):
                yield event

            # 宪法四:每轮执行结束后写 Checkpoint(挂了接着跑)
            if self._write_checkpoint:
                await self._write_checkpoint(run)
相关推荐
kaixin_啊啊1 小时前
【零基础学AI】第 9 章——安装 Python 和开发工具
人工智能·python
雨滴AI自动化测试2 小时前
想让你的自动化测试接入AI,这一步必须要有。
python
用户7624117567052 小时前
第八章 异常处理及程序调试
python
源图客2 小时前
Python环境安装与PyCharm的第一个项目
开发语言·python·pycharm
朝朝辞暮i2 小时前
VLA 系统学习第 20 课——Diffusion Policy 为什么要先给动作加噪,再学习把噪声去掉?
人工智能·python·深度学习·transformer·vla
郝学胜_神的一滴2 小时前
Numpy数据处理详解 02:玩转高性能数组,告别低效循环
人工智能·python
全栈弄潮儿2 小时前
Python实战第3期:输入输出与字符串操作
python·agent
goehou2 小时前
MCP 传输方式实战:stdio、Streamable HTTP、WebSocket 该选哪个
python·llm·agent·教程·mcp
用户0332126663673 小时前
如何快速拆分超大 Excel 文件【Python 教程】
python·excel