☰
【智能体】Loop 的四种设计模式之:Event-Driven Loop(2026 最新版)
2026/10/6 2:43:43 网站建设 项目流程

Event-Driven Loop

  • 1、引言
  • 2、Event-Driven Loop 到底解决什么问题?
  • 3、Event-Driven Loop 核心原理
    • 3.1 Event Bus:所有外部世界的"门铃"
    • 3.2 三个必须背下来的工程约束
  • 4、生产级实现(FastAPI + Durable Workflow + LangGraph)
  • 5、2026 年的关键改进点
    • 5.1 从"HTTP 调一下"到 Durable Execution
    • 5.2 幂等与 Outbox:别让 Agent 重复发邮件
    • 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 LoopVerification LoopEvent-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)。

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

{"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;下面用伪代码风格写,重点在结构):

# event_driven_loop.pyfromfastapiimportFastAPI,Request,HTTPExceptionfrompydanticimportBaseModelfromtypingimportAnyimporthashlib,hmac,json app=FastAPI()# 一个最简单的"已处理事件"表,生产里用 Redis/PostgresPROCESSED_EVENTS:set[str]=set()classEvent(BaseModel):event_id:strevent_type:stridempotency_key:strpayload:dict[str,Any]# ---------- 1. Webhook 入口:验签 + 幂等 ----------@app.post("/hooks/github")asyncdefgithub_hook(req:Request):body=awaitreq.body()sig=req.headers.get("X-Hub-Signature-256","")# 验签:防伪造请求打进来ifnotverify_github_signature(body,sig):raiseHTTPException(status_code=403)data=awaitreq.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,别再唤起一次 Agentifevent.idempotency_keyinPROCESSED_EVENTS:return{"status":"duplicate_ack"}# 扔给 durable workflow 去跑,Webhook 立刻返回,别让 GitHub 等你enqueue_durable_workflow("handle_github_issue",event.model_dump())return{"status":"accepted"}# ---------- 2. 真正的 Agent 工作流(durable,每一步都会被持久化) ----------asyncdefhandle_github_issue(event:dict):frommy_agentimportbuild_issue_agent# 第 1 篇那个 Agent Looprepo=event["payload"]["repository"]["full_name"]number=event["payload"]["issue"]["number"]# 步骤 A:拉 issue 正文 + 相关代码(durable:失败自动重试这一步)issue_body=awaitgithub_get_issue(repo,number)# 步骤 B:跑 Agent Loop,让它做初步复现 / 分类agent=build_issue_agent()diagnosis=awaitagent.ainvoke({"issue_body":issue_body,"repo":repo,})# 步骤 C:高风险动作——自动改代码前,先等人点头(HITL)ifdiagnosis["should_open_pr"]:awaitwait_for_human_approval(timeout="24h",message=f"Agent 建议给{repo}#{number}开个修复 PR,是否批准?",)# 步骤 D:批准了再写 GitHub,用幂等 key 防止重复 PRawaitgithub_create_pr(repo=repo,title=f"fix:{diagnosis['title']}",body=diagnosis["pr_body"],idempotency_key=f"pr-{repo}-{number}",)# 步骤 E:不管改不改,都回个评论告诉提 issue 的人"我们看了"awaitgithub_comment(repo=repo,number=number,body=diagnosis["initial_comment"],idempotency_key=f"comment-{repo}-{number}",)# ---------- 工具函数(示意) ----------defverify_github_signature(body:bytes,sig:str)->bool:...defenqueue_durable_workflow(name:str,payload:dict):...asyncdefgithub_get_issue(repo:str,number:int):...asyncdefgithub_create_pr(**kw):...asyncdefgithub_comment(**kw):...asyncdefwait_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博客专家;
  • 企业认证金牌面试官;
  • 多个名企认证&特邀讲师等;
  • 名企签约职场面试培训、职场规划师;
  • 多个国内主流技术社区的认证专家博主;
  • 多款主流产品(阿里云等)评测一等奖获得者;

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询