【智能体】Loop 的四种设计模式之:Event-Driven Loop(2026 最新版)

Event-Driven Loop

  • 1、引言
  • [2、Event-Driven Loop 到底解决什么问题?](#2、Event-Driven Loop 到底解决什么问题?)
  • [3、Event-Driven Loop 核心原理](#3、Event-Driven Loop 核心原理)
    • [3.1 Event Bus:所有外部世界的"门铃"](#3.1 Event Bus:所有外部世界的"门铃")
    • [3.2 三个必须背下来的工程约束](#3.2 三个必须背下来的工程约束)
  • [4、生产级实现(FastAPI + Durable Workflow + LangGraph)](#4、生产级实现(FastAPI + Durable Workflow + LangGraph))
  • [5、2026 年的关键改进点](#5、2026 年的关键改进点)
    • [5.1 从"HTTP 调一下"到 Durable Execution](#5.1 从"HTTP 调一下"到 Durable Execution)
    • [5.2 幂等与 Outbox:别让 Agent 重复发邮件](#5.2 幂等与 Outbox:别让 Agent 重复发邮件)
    • [5.3 Human-in-the-Loop:高风险动作先等人点头](#5.3 Human-in-the-Loop:高风险动作先等人点头)
  • 6、适用场景与性能基准
  • 7、总结

1、引言

小屌丝:鱼哥,我那个 Agent 现在可猛了------写东西能自己改,数字不对能自己审,我用着贼顺手。

小鱼:那它一天能帮你干多少活?

小屌丝:嗯......基本就我上班的时候,我戳它一下它动一下。我下班关了浏览器,它就跟死了一样。我让它"盯着 GitHub 上那个 issue,有人提就自动复现一下",结果第二天我一看------昨晚三点有人提 issue,它压根没理人家。

小鱼 :废话,你把它当博客客服养呢?它又不会自己睁眼。你得让它被事情叫醒。

小屌丝:被事情叫醒?啥意思?

小鱼 :就是 Event-Driven Loop。Webhook 来了、Cron 到点了、Slack 有人 @ 你、Email 进了收件箱、GitHub 新建了一个 issue------这些外部世界的"动静"全部进到一个事件总线,Agent 监听这些事件,自己爬起来干活,干完还能把结果写回数据库、回个 PR、发个通知。你不戳它,它也在跑。

小屌丝:听着美好。但我上次自己写了个 FastAPI 接 webhook,Agent 跑到一半服务重启了,结果一封确认邮件给客户发了三遍......

小鱼:(点头)这就是为什么这一篇要讲三个工程约束------幂等、持久化、人审。不把这仨搞明白,你的 Event-Driven Agent 不是自动员工,是自动事故制造机。


2、Event-Driven Loop 到底解决什么问题?

对应素材里的"循环 3":

复制代码
事件源(谁在敲门)              总线                 Agent               动作(写回真实世界)
─────────────            ──────────           ──────────          ──────────────
Webhook                ┌──────────┐
Cron 定时任务           │          │
Slack 消息      ───▶   │ Event    │  ───▶  Agent   ──▶  数据库
Email                  │ Bus      │        (执行任务)      文档系统
GitHub issue/PR         │          │                     GitHub PR
监控告警                └──────────┘                     通知系统
...                                                 其他服务

它跟前两层 Loop 的本质区别:

维度 Agent Loop Verification Loop Event-Driven Loop
谁触发 用户一句话 生成完自动审 外部世界任何事件
Agent 是主动还是被动 被动响应一次请求 被动响应一次请求 7×24 常驻,事件来了自动起
状态活多久 一个请求内 一个请求内 跨小时、跨天、跨服务
失败语义 重跑就行 重跑就行 必须保证不重不漏、不重复写
典型场景 查天气写周报 出稿前自审 自动处理工单、监控告警、PR 机器人

一句话总结:Event-Driven Loop = 事件总线 + 常驻 Agent + 持久化执行 + 写回外部系统,让 Agent 从"你问它才答"变成"世界动它就动"。


3、Event-Driven Loop 核心原理

3.1 Event Bus:所有外部世界的"门铃"

事件源在 2026 年基本就这几类:

  • Webhook:GitHub、Stripe、Shopify、内部系统回调;
  • Cron / Scheduler:每天早上 9 点拉昨日报表、每周一汇总周报;
  • IM 消息:Slack / 飞书 / 企业微信群里被 @;
  • Email:收件箱来了新邮件,分类并起草回复;
  • 数据变更:数据库 binlog、CDC、消息队列(Kafka / Redis Stream)。

它们全部归一化成一个事件:

json 复制代码
{
  "event_id": "evt_01J9X...",
  "event_type": "github.issue.opened",
  "source": "github",
  "occurred_at": "2026-09-27T15:02:11Z",
  "payload": { "repo": "acme/web", "issue_number": 123, "author": "xxx" },
  "idempotency_key": "github-issue-opened-123"
}

Agent 订阅自己关心的 event_type,来了就起一次执行。注意 idempotency_key 这个字段,下面会反复用。

3.2 三个必须背下来的工程约束

事件驱动跟你在 Jupyter 里跑一个 notebook 最大的不同,是你不知道进程什么时候会死、消息会不会被投两次、写外部系统会不会写一半崩了。所以三件事必须从第一天就设计进去:

  1. At-least-once 投递:绝大多数消息系统保证"至少投一次",不保证"只投一次"。所以 Agent 对同一个事件可能被唤起两次,必须自己幂等。
  2. Durable Execution(持久化执行):一个 Agent 任务可能要跑 5 分钟、30 分钟,期间你发版重启、容器被杀,任务得能从断点继续,不能从头再来。
  3. 副作用要可回滚 / 可重试:Agent 要回 GitHub 评论、要发邮件、要写数据库------这些动作失败了要能重试,但重试不能重复发。

这三件事不解决,Event-Driven Agent 上线第一天就会给你惊喜:重复邮件、重复 PR、重复扣款。


4、生产级实现(FastAPI + Durable Workflow + LangGraph)

下面这套用一个轻量 durable workflow 引擎的思路(2026 年主流选择是 Temporal、Inngest、Restate;下面用伪代码风格写,重点在结构):

python 复制代码
# event_driven_loop.py
from fastapi import FastAPI, Request, HTTPException
from pydantic import BaseModel
from typing import Any
import hashlib, hmac, json

app = FastAPI()

# 一个最简单的"已处理事件"表,生产里用 Redis/Postgres
PROCESSED_EVENTS: set[str] = set()

class Event(BaseModel):
    event_id: str
    event_type: str
    idempotency_key: str
    payload: dict[str, Any]

# ---------- 1. Webhook 入口:验签 + 幂等 ----------
@app.post("/hooks/github")
async def github_hook(req: Request):
    body = await req.body()
    sig = req.headers.get("X-Hub-Signature-256", "")
    # 验签:防伪造请求打进来
    if not verify_github_signature(body, sig):
        raise HTTPException(status_code=403)

    data = await req.json()
    event = Event(
        event_id=data["delivery"],
        event_type=f"github.{data['action']}",
        idempotency_key=f"github-{data['action']}-{data['repository']['id']}-{data['issue']['number']}",
        payload=data,
    )

    # 幂等:同一个 key 处理过就直接 ACK,别再唤起一次 Agent
    if event.idempotency_key in PROCESSED_EVENTS:
        return {"status": "duplicate_ack"}

    # 扔给 durable workflow 去跑,Webhook 立刻返回,别让 GitHub 等你
    enqueue_durable_workflow("handle_github_issue", event.model_dump())
    return {"status": "accepted"}

# ---------- 2. 真正的 Agent 工作流(durable,每一步都会被持久化) ----------
async def handle_github_issue(event: dict):
    from my_agent import build_issue_agent   # 第 1 篇那个 Agent Loop

    repo = event["payload"]["repository"]["full_name"]
    number = event["payload"]["issue"]["number"]

    # 步骤 A:拉 issue 正文 + 相关代码(durable:失败自动重试这一步)
    issue_body = await github_get_issue(repo, number)

    # 步骤 B:跑 Agent Loop,让它做初步复现 / 分类
    agent = build_issue_agent()
    diagnosis = await agent.ainvoke({
        "issue_body": issue_body,
        "repo": repo,
    })

    # 步骤 C:高风险动作------自动改代码前,先等人点头(HITL)
    if diagnosis["should_open_pr"]:
        await wait_for_human_approval(
            timeout="24h",
            message=f"Agent 建议给 {repo}#{number} 开个修复 PR,是否批准?",
        )

        # 步骤 D:批准了再写 GitHub,用幂等 key 防止重复 PR
        await github_create_pr(
            repo=repo,
            title=f"fix: {diagnosis['title']}",
            body=diagnosis["pr_body"],
            idempotency_key=f"pr-{repo}-{number}",
        )

    # 步骤 E:不管改不改,都回个评论告诉提 issue 的人"我们看了"
    await github_comment(
        repo=repo, number=number,
        body=diagnosis["initial_comment"],
        idempotency_key=f"comment-{repo}-{number}",
    )

# ---------- 工具函数(示意) ----------
def verify_github_signature(body: bytes, sig: str) -> bool: ...
def enqueue_durable_workflow(name: str, payload: dict): ...
async def github_get_issue(repo: str, number: int): ...
async def github_create_pr(**kw): ...
async def github_comment(**kw): ...
async def wait_for_human_approval(**kw): ...

关键设计点:

  • Webhook 入口只做验签 + 幂等 + 入队,立刻返回;真正的 Agent 跑在 durable worker 里;
  • 每个外部写操作(评论、开 PR)都带 idempotency_key,重试不会重复写;
  • 高风险动作(改代码、开 PR)中间插一个 wait_for_human_approval,durable workflow 会把状态挂起,人在 Slack 上点个"批准",第二天回来它接着跑。

5、2026 年的关键改进点

5.1 从"HTTP 调一下"到 Durable Execution

2024 年写 Event-Driven Agent,典型姿势是 FastAPI + Celery + Redis。问题:worker 挂了,任务就丢了;重启后不知道跑到哪一步;要自己写一堆 checkpoint。

2026 年的标准是 Durable Execution 引擎(Temporal / Inngest / Restate / 云厂商 Step Functions):

  • 你写的就是普通的 async def 函数,但每一步的返回值都被自动持久化;
  • 进程挂了,worker 重新起来后从最后一个完成的步骤继续;
  • 长等待(比如等 24 小时人审批)不占任何进程,状态存在引擎里;
  • 自带重试、超时、超时报警、可视化 timeline。

对 Agent 场景的好处是:一个跑了 20 分钟的多步 Agent 任务,你半夜发版重启,它不会丢。 这件事在 2024 年要自己写几百行才能做到。

5.2 幂等与 Outbox:别让 Agent 重复发邮件

事件驱动最经典的事故就是"客户凌晨收到三封一模一样的确认邮件"。根因就一个:消息系统 at-least-once,Agent 自己不幂等。

工程上两个套路:

  • Idempotency Key :每个外部副作用带一个业务主键(比如 comment-{repo}-{issue_number}),写之前先查一遍有没有写过;
  • Transaction Outbox:Agent 决定要"发邮件"这件事,先把事件写进本地 outbox 表(和业务事务一起提交),再由独立进程投递。这样"Agent 状态"和"外部副作用"不会出现一个成功一个失败。

一句话:凡是 Agent 对真实世界的写操作,都要假设它会被调用两次。

5.3 Human-in-the-Loop:高风险动作先等人点头

Event-Driven Agent 最危险的不是"不干活",是"自己把活干了"------比如它自己判断"这个 bug 必须紧急修复",就直接 merge 了 PR、给客户发了退款邮件、在生产库删了一张表。

2026 年的分层做法:

动作风险 处理方式
只读(查数据、拉日志、写草稿) 全自动,直接干
低风险写(回个 issue 评论、写文档) 自动干,事后通知
中风险写(开 PR、发客户邮件) 自动起草,等人点批准
高风险写(merge、退款、删数据、发钱) 必须人审,拒绝自动执行

Durable workflow 的 wait_for_human_approval 就是为这个设计的------任务挂起、状态持久化、审批通过后自动续跑。


6、适用场景与性能基准

场景 推荐度 说明
GitHub / GitLab 机器人(issue 分类、PR 初筛) ⭐⭐⭐⭐⭐ 天然事件源,价值立刻可见
工单 / 客服自动分诊 ⭐⭐⭐⭐⭐ 高频、低风险写、事件驱动
定时报表 / 晨间摘要 ⭐⭐⭐⭐⭐ Cron 是最简单的事件源
监控告警自动诊断 ⭐⭐⭐⭐ 配合 Verification Loop 才敢自动处理
自动下单 / 自动退款 / 自动发钱 ⭐⭐ 必须人审,风险高
毫秒级在线交易 ⭐ 事件队列 + LLM 延迟,扛不住

一组 2026 年参考数字:

  • 单事件端到端延迟(从 webhook 到 Agent 产出):5--30 秒;
  • 单事件成本:0.02 -- 0.10(取决于 Agent 步数);
  • 幂等重复率:真实生产里消息重复投递比例约 0.1%--1%,必须处理;
  • Durable workflow 任务平均时长:几十秒到几十分钟;
  • HITL 审批平均等待:几小时(靠异步挂起,不占资源);
  • 自动处理率:成熟系统能做到 70%--85% 事件全自动闭环,剩下转人工。

7、总结

Event-Driven Loop 把 Agent 从"等你戳的聊天机器人"变成"7×24 盯着世界的数字员工"。但它也是四层 Loop 里最容易出生产事故的一层------因为它真的在写真实世界。

核心记忆点:

  • 事件源千奇百怪,归一化成一个 Event 结构再进总线;
  • At-least-once 是默认现实,所有外部写操作都要幂等;
  • 用 Durable Execution 引擎,别自己写 checkpoint;
  • 高风险动作必须 HITL,"全自动"不是目标,"敢放手"才是;
  • Webhook 入口要薄:验签、幂等、入队,剩下的交给 worker;
  • 这套跑稳了,你就拥有了一个不用睡觉的实习生------然后下一篇我们讲怎么让它自己把自己变得更聪明。

我是小鱼:

  • CSDN 博客专家;
  • AIGC 技术MVP专家;
  • 阿里云 专家博主;
  • 51CTO博客专家;
  • 企业认证金牌面试官;
  • 多个名企认证&特邀讲师等;
  • 名企签约职场面试培训、职场规划师;
  • 多个国内主流技术社区的认证专家博主;
  • 多款主流产品(阿里云等)评测一等奖获得者;

关注小鱼,学习【人工智能与大模型】最新最全的领域知识。

相关推荐
Martina_03211 小时前
AI生成的盔甲换动作后漂移?用6步检查挂点、骨架映射与 Bind Pose
人工智能·游戏·3d·ai·自然语言处理·aigc·游戏策划
Ivanqhz1 小时前
KV Cache
服务器·数据库·人工智能·深度学习·算法
Carl_奕然1 小时前
【智能体】Loop 的四种设计模式之:Hill Climbing Loop(2026 最新版)
人工智能·python·设计模式
Rocky Ding*1 小时前
深度解析LlamaGen核心基础知识
论文阅读·人工智能·深度学习·机器学习·aigc·ai-native·llamagen
hai3152475431 小时前
语言学矩阵原理
人工智能·机器学习·矩阵
Omics Pro1 小时前
~30,000+引用!理论2005,R包2008,多组学集成AI增强
开发语言·数据库·人工智能·算法·机器学习·自然语言处理·r语言
ZzT1 小时前
拆开 Claude Code、Codex 等 11 个 coding agent:没有一个用 LangChain,也没有一个用向量检索代码
人工智能·ai编程·claude
Kstheme1 小时前
受 Karpathy ASD-STE100的启发,我把论文讲解做成了一个开源 Skill
人工智能
EatFan1 小时前
MCP 从概念到落地:Java(Spring AI Alibaba)与 .NET 双栈接入实操对比
java·人工智能·后端·spring·.net·java后端·mcp