最新资讯
reddit.com OpenAI 称 Astra 仅满足 10% 安全任务标准 dev.to FreeToken:在自有 GPU 上运行前沿 MoE 模型及其内存需求 dev.to 当 AI Agent 说“完成”时,究竟完成了什么? dev.to 部署 Underdog Bark 3.0 Pro:逐字转写、自定义后端与分块设置 dev.to 为艰难对话构建 AI:五个 Agent、一条安全正则与一位盲评监督者 techcrunch.com Palo Alto Networks 洽谈以 5 亿美元收购 AI Agent 安全初创公司 Clutch theinformation.com 黄仁勋被要求就涉华间谍指控向国会作简报 www.infoq.com Edera 推出 Object Capability Bounded Authority,试图将凭证与 AI Agent 工作负载隔离 wechat 这波杀疯了!旗舰级模型不限量、1个月视频额度免费领 bloomberg.com AI 抛售蔓延至信用市场,软银领跌亚洲美元债 dev.to 如何在专用 GPU 服务器上用 OpenAI 兼容 API 部署 LLM dev.to 审计 153 份 Claude Code 与 Codex 会话记录:User-Agent 与 URL 中的邮箱泄露
多元动态
登录 注册
智能体 dev.to · @Staff Systems Lab

设计确定性 AI Agent 循环:架构、验证与可重放状态机

原文 我的收藏

文章指出朴素 Agent 循环在生产环境中的典型失败:重复失败工具调用导致死循环、工具输出 schema 微变时幻觉参数、中间输出违反领域不变量,并造成 API 成本与信任损耗。作者认为根因是把 Agent 当作确定性函数却以非确定性方式执行状态变更,主张引入边界校验、确定性循环与可重放状态机架构。

AI推荐理由 针对朴素 Agent 循环在生产中的失败模式(无限循环、参数幻觉、违反领域不变量),提出确定性循环、边界校验与可重放状态机架构;问题定义清晰,属可复用的架构思路,但为概念性文章,未提供实现或基准。

70

正文

Designing Deterministic AI Agent Loops: Architecture, Verification, and Replay State Machines Most software engineers building with Large Language Models (LLMs) eventually hit the exact same wall: the naive agent loop problem. You start with a straightforward loop: User gives a prompt. LLM selects a tool to call. Runtime executes the tool. Result is appended to context. Repeat until LLM emits a final response. In demos, this works brilliantly. In production, it breaks in infuriatingly subtle ways. The agent gets stuck in infinite loops repeating failing tool calls, hallucinates arguments when tool output schema changes slightly, or produces intermediate outputs that violate domain invariants—costing hundreds of dollars in API credits while degrading user trust. The core issue is architectural: we treat AI agents like deterministic functions, while executing their state mutations non-deterministically without real boundary validation. To move from fragile AI prototypes to mission-critical infrastructure, we must treat the agent runtime as a Finite State Machine (FSM) with isolated verification gates and event-sourced replay capabilities. In this article, we'll design and build a deterministic, production-ready AI agent execution runtime in TypeScript, step by step. The Fallacy of Prompt-Based Verification A common fix for agent unreliability is "prompt-based self-correction"—telling the LLM in the system prompt: "If your tool execution fails, reflect on your mistake and try again." This fails in production for three distinct reasons: Context Pollution: Every failed tool call and hallucinated response degrades the context window. As context length increases, attention degrades, making subsequent corrections less reliable. Non-Idempotent Side Effects: If an agent executes an API payload half-correctly (e.g., creating a user record but failing to send an email), blindly re-prompting the model can lead to duplicated mutations. Unbounded Halting Problem: Without strict structural boundaries, the agent's retry space is unbounded. It will burn tokens trying variations of invalid state transitions. The Solution: The OPVC Pipeline Architecture Instead of relying on the LLM to govern its own control flow, we decouple execution into four deterministic phases: Observe, Propose, Verify, Commit (OPVC). flowchart TD A[State Machine Engine] -->|1. Observe Current State| B[Context Assembly] B -->|2. Propose Action| C[LLM Planner] C -->|Candidate Transition| D{3. Verification Gate} D -->|Invalid / Invariant Violations| E[Synthesize Error Event] E -->|Inject Guidance| A D -->|Valid Transition| F[4. Commit Execution] F -->|Execute Tool / Mutate State| G[Append Event to Journal] G --> A Observe: Read current state and active constraints from a read-only event journal. Propose: LLM emits a single candidate state transition (a structured tool invocation proposal). Verify: A deterministic runtime gate (Zod schemas, AST parsers, domain invariants) inspects the proposal before execution. Commit: If passed, the execution layer runs the tool, appends the result to an immutable journal, and advances the state machine. Implementing a Verifiable Agent Runtime Let's construct a type-safe runtime that enforces this architecture. 1. Defining the Core State & Event Contracts First, we establish strict typed contracts for our execution journal and tool schemas using Zod and TypeScript. import { z } from "zod"; // Representing immutable events in our agent's history export type AgentEvent = | { type: "USER_INPUT"; payload: string; timestamp: number } | { type: "ACTION_PROPOSED"; tool: string; args: unknown; timestamp: number } | { type: "VERIFICATION_FAILED"; error: string; timestamp: number } | { type: "ACTION_COMMITTED"; tool: string; result: unknown; timestamp: number } | { type: "AGENT_HALTED"; reason: string; timestamp: number }; export interface AgentState { history: AgentEvent[]; status: "IDLE" | "AWAITING_PROPOSAL" | "VERIFYING" | "EXECUTING" | "COMPLETED" | "FAILED"; consecutiveFailures: number; maxRetries: number; } // Definition for a verifiable tool export interface VerifiableTool { name: string; description: string; schema: z.ZodSchema; // Deterministic guard checking business logic beyond pure JSON schema validation guard?: (input: TInput, history: AgentEvent[]) => { valid: boolean; reason?: string }; execute: (input: TInput) => Promise; } Enter fullscreen mode Exit fullscreen mode 2. Building the Verification Gate The Verification Gate acts as an intermediate firewall between the model's output and your downstream services. export class VerificationGate { constructor(private tools: Map) {} public verify( toolName: string, rawArgs: unknown, history: AgentEvent[] ): { success: true; validatedArgs: any } | { success: false; error: string } { const tool = this.tools.get(toolName); if (!tool) { return { success: false, error: `Tool '${toolName}' does not exist.` }; } // 1. Schema / Type Validation const parseResult = tool.schema.safeParse(rawArgs); if (!parseResult.success) { return { success: false, error: `Schema mismatch for tool '${toolName}': ${parseResult.error.message}`, }; } // 2. Business Invariant / Guard Validation if (tool.guard) { const guardResult = tool.guard(parseResult.data, history); if (!guardResult.valid) { return { success: false, error: `Invariant guard failed for '${toolName}': ${guardResult.reason}`, }; } } return { success: true, validatedArgs: parseResult.data }; } } Enter fullscreen mode Exit fullscreen mode Notice the secondary guard step: schema parsing verifies structural soundness, but guards verify semantic invariants (e.g., "cannot withdraw an amount greater than the current balance calculated from state history"). 3. The State Machine Runtime Now we wire this into a deterministic loop runner that manages state transitions cleanly: export interface LLMProvider { proposeAction( history: AgentEvent[], availableTools: Array ): Promise; } export class DeterministicAgentEngine { private state: AgentState; private tools: Map = new Map(); private verifier: VerificationGate; constructor( private llm: LLMProvider, tools: VerifiableTool[], maxRetries = 3 ) { tools.forEach((t) => this.tools.set(t.name, t)); this.verifier = new VerificationGate(this.tools); this.state = { history: [], status: "IDLE", consecutiveFailures: 0, maxRetries, }; } public async run(userInput: string): Promise { this.appendEvent({ type: "USER_INPUT", payload: userInput, timestamp: Date.now() }); this.state.status = "AWAITING_PROPOSAL"; while (this.state.status !== "COMPLETED" && this.state.status !== "FAILED") { if (this.state.consecutiveFailures >= this.state.maxRetries) { this.state.status = "FAILED"; this.appendEvent({ type: "AGENT_HALTED", reason: `Exceeded max consecutive verification failures (${this.state.maxRetries}).`, timestamp: Date.now(), }); throw new Error(`Agent halted: Too many invalid action attempts.`); } // PHASE 1 & 2: OBSERVE & PROPOSE const toolDescriptions = Array.from(this.tools.values()).map((t) => ({ name: t.name, description: t.description, })); const proposal = await this.llm.proposeAction(this.state.history, toolDescriptions); if ("finalAnswer" in proposal) { this.state.status = "COMPLETED"; return proposal.finalAnswer; } this.appendEvent({ type: "ACTION_PROPOSED", tool: proposal.tool, args: proposal.args, timestamp: Date.now(), }); // PHASE 3: VERIFY this.state.status = "VERIFYING"; const verification = this.verifier.verify( proposal.tool, proposal.args, this.state.history ); if (!verification.success) { this.state.consecutiveFailures++; this.appendEvent({ type: "VERIFICATION_FAILED", error: verification.error, timestamp: Date.now(), }); this.state.status = "AWAITING_PROPOSAL"; continue; // Loop back; LLM sees the explicit VERIFICATION_FAILED event } // PHASE 4: COMMIT this.state.status = "EXECUTING"; this.state.consecutiveFailures = 0; // Reset counter on valid proposal const targetTool = this.tools.get(proposal.tool)!; try { const result = await targetTool.execute(verification.validatedArgs); this.appendEvent({ type: "ACTION_COMMITTED", tool: proposal.tool, result, timestamp: Date.now(), }); this.state.status = "AWAITING_PROPOSAL"; } catch (execError: any) { this.appendEvent({ type: "VERIFICATION_FAILED", error: `Tool execution runtime error: ${execError.message}`, timestamp: Date.now(), }); this.state.status = "AWAITING_PROPOSAL"; } } throw new Error("Engine terminated unexpectedly."); } private appendEvent(event: AgentEvent) { this.state.history.push(event); } public getJournal(): readonly AgentEvent[] { return Object.freeze([...this.state.history]); } } Enter fullscreen mode Exit fullscreen mode Enabling Deterministic State Replay for Debugging One of the biggest pain points in agent operations is debugging production errors. When an agent fails on step 7 of an enterprise workflow, how do you reproduce it locally when LLM responses are inherently stochastic? Because our runtime uses an event-sourced journal, we can implement Deterministic Replay Mocking. export class ReplayLLMProvider implements LLMProvider { private proposalPointer = 0; constructor(private recordedJournal: AgentEvent[]) {} async proposeAction(): Promise { // Advance to next recorded PROPOSED action in the event log while (this.proposalPointer 1, compact redundant failure events into a single summary frame before passing context to the LLM planner. Common Architectural Pitfalls Pitfall 1: Mutating External State Inside the Verification Phase Never allow verification functions to alter database state or call mutation endpoints. Verification functions must be pure functions operating only on the proposed payload and historical state. Pitfall 2: Circular Repair Loops If the LLM makes an error and the verification error message is vague (e.g., Invalid input), the LLM will repeatedly propose variations of the exact same broken input. Fix: Ensure your VerificationGate returns actionable structural guidance: // BAD ERROR RESPONSE "Invalid argument for refund." // GOOD ERROR RESPONSE "Invariant Failure: Parameter 'amount' ($150) exceeds maximum order total ($100). Re-evaluate refund limits." Enter fullscreen mode Exit fullscreen mode When to Use This Pattern Use explicit OPVC State Machine architectures when: Your agent has tool access to systems with irreversible side effects (SQL databases, payment APIs, Cloud infrastructure). You operate in domain-constrained environments (Healthcare, Finance, Internal Ops tools). You require compliance audit logs of every internal thought/validation step. Skip this complexity when: Building simple stateless Q&A chatbots. Operating in pure read-only context environments where errors have zero side effects. Summary Checklist for Production AI Agents [ ] Isolate Tool Schemas: Use strict Zod / JSON schemas on all tool inputs. [ ] Enforce Semantic Guards: Implement code-level invariant checks beyond simple data-type checking. [ ] Bounded Retry Loops: Set strict threshold limits for consecutive verification failures to prevent token burn. [ ] Event-Sourced Logging: Store state transitions as discrete, typed events to enable offline replay debugging. By treating AI agents not as magic autonomous entities, but as probabilistic components operating inside deterministic state machines, we construct AI systems that scale reliably in production environments.

来源报道 · 1 篇 · 以下链接均前往原始媒体

← 返回精选动态 原文

更多内容