前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
原理篇
面经篇
AI 面试
自检篇
每日一题
  • 综合
    • 综合题型
    • 其他问题
    • 设计模式
    • 思维导图
    • 学习路线
  • 前端基础
    • HTTP
    • 浏览器
    • 计算机基础
  • 进阶学习
    • NPM工作流
    • Docker
    • Canvas
    • Node学习指南
    • 前端综合文章
  • 其他
    • Handbook
    • 职场话题
    • CSS可视化
小程序题库
公众号动态
博客动态
AI 热点
开发者导航
基础篇
进阶篇
高频篇
精选篇
手写篇
原理篇
面经篇
AI 面试
自检篇
每日一题
  • 综合
    • 综合题型
    • 其他问题
    • 设计模式
    • 思维导图
    • 学习路线
  • 前端基础
    • HTTP
    • 浏览器
    • 计算机基础
  • 进阶学习
    • NPM工作流
    • Docker
    • Canvas
    • Node学习指南
    • 前端综合文章
  • 其他
    • Handbook
    • 职场话题
    • CSS可视化
小程序题库
公众号动态
博客动态
AI 热点
开发者导航
返回 AI 情报前线
All News · 全部资讯3542
  • MIT 缺失学期课程 2026 版发布
  • 171 个 LLM 时间线:2017-2026 完整演进
  • 过度依赖 AI:程序员如何自救
  • AI 大规模重构代码库的真实结果复盘
  • macOS 轻量化 Linux 虚拟机工具发布
  • LLM在生产环境中的可靠性成本权衡
  • Claude Code高效工作流:规划与执行分离
  • Claude IDE为什么选择Electron框架
  • 多模态模型在机器人任务中的应用
  • LLM模型如何集成至芯片中
  • Cord:分层Agent系统的协调框架
  • Claws:LLM Agent系统的新通用抽象
  • LangChain Deep Agents构建推理助手
  • Unsloth 免费微调:HF 提供免费计算资源
  • llama.cpp等本地推理项目入驻Hugging Face
  • Cmux 终端工具:Ghostty 垂直标签管理器
  • Gemini 3.1 Pro 发布:专为复杂任务设计
  • 测量 AI Agent 自主性:Anthropic 实践研究
  • AI 时代程序员核心竞争力:批判而非只会生成
  • Anthropic 禁用第三方订阅认证:API 政策重大调整
  • 从并发编程到 AI Agent:生产级架构设计
  • Cursor 与 Copilot 深度对比:AI 编程工具实战评测
  • 企业 AI Agent 失败诊断:新基准测试工具发布
  • AI 编码工具如何重塑程序员的写作和认知方式
  • MLH 收购开发者社区 DEV.to,投资开发者生态
  • 关于 LLM 数据使用的公开质疑
  • Gradio 新功能:一行代码快速部署 Web 界面
  • Cursor 更新:CLI 云端交付与 ASCII 图表渲染
  • DEV 推出多 Agent 系统实战教育课程
  • Anthropic 发布 Claude Sonnet 4.6 新一代模型
  • 用 LLM 实现魔法风云会对战系统
  • Apple Silicon 本地 RAG:毫秒级响应,无需后端
  • AI 眼镜编码体验:新硬件的真实表现
  • AI 时代最值得练的技能:删代码而非写代码
  • Cursor 更新:插件系统、异步 Agent、沙箱控制
  • LLM 安全实战:AI 总结、多语言防护与防护栏设计
  • Claude 隐藏 AI 操作引发争议:开发者强烈反弹
  • 通义千问 3.5:原生多模态 Agent 能力发布
  • 2 年 AI 编程实战总结:配对编程最真正改善质量
  • AI 威胁什么:打破软件开发的技能垄断
  • LLM推理加速的两个实用技巧
  • AI Agent自主发文事件回顾
  • 数据工程完全指南开源发布
  • Claude Code/Codex新增云资源部署技能
  • Claude接入笔式绘图仪的创意集成
  • Claude Code全栈开发必知三点
  • LLM Agent成本的二次方陷阱
  • Claude和Codex开放自定义计算内核
  • Moltis:具备记忆和自扩展能力的 AI 助手框架
  • Anthropic 融资 300 亿美元,估值达 3800 亿
  • Gemini 3 推理模式升级,应对科学和工程难题
  • 已加载 51 / 3542
8.0
热点
AI SCORE
技术实践2026-02-19 06:37

从并发编程到 AI Agent:生产级架构设计

Hacker News · georgeguimaraes.com#Agent#并发#架构
Editor brief · 编辑速览

总结传统并发编程的最佳实践如何应用于 AI agent 系统,涵盖可靠性、扩展性等核心问题。

文章思维导图
Knowledge map
拖拽缩放
Full translation

完整中文译文

后续:本文在 Hacker News 上收到了一些合理的质疑。我写了一篇后续文章回应其中三个最有力的批评:《Elixir/BEAM 并不能解决 AI 智能体的所有问题》。

最近,José Valim 发表了《为什么 Elixir 是 AI 最佳编程语言》,引用了一项腾讯研究表明 Elixir 在 20 种语言中实现了最高的 LLM 代码补全率。Claude Opus 4 在 Elixir 问题上得分 80.3%,而排名第二的 C# 为 74.9%。

但其中有一个比「LLM 能写好 Elixir」更深层的论点:1986 年 Erlang 引入的 Actor 模型,就是 AI 在 2026 年重新发现的 AI 智能体模型。Python AI 生态正在构建的每一个模式(隔离的状态、消息传递、监督层级、故障恢复)在 BEAM 虚拟机上都已经存在。而且它已经在电信交换机、WhatsApp 和 Discord 上大规模运行了数十年。

我在新一代(New Generation)从事智能商务基础设施的开发。在此之前,我在一家独角兽级巴西金融科技公司推出了一个为超过 300 万商户服务的完整 AI 栈。两个系统都运行在 Elixir 上。以下是为什么这不是一个文艺青年的语言选择。这是一种架构必然性。

30 秒请求问题

传统 web 框架是为请求耗时毫秒级的世界设计的。用户点击、服务器查询数据库、渲染 HTML、在 100ms 以内响应。Rails、Django、Laravel:都是为这种模式优化的。

AI 智能体打破了这种模型。当用户向智能体提问时,响应需要 5 到 30 秒。智能体调用 LLM、等待流式 token、可能调用工具、再次调用 LLM、流出更多 token。一个"请求"可能涉及三次往返 LLM API、两次数据库查询和一次网络搜索。整个时间连接都保持打开。

现在乘以 1 万个并发用户。每一个都持有一个开放连接 15+ 秒。传统的每请求一线程框架会崩溃。你需要异步、需要并发性、需要在不大量消耗内存的情况下持有数千个长生命周期的连接。

BEAM 就是为此而生的。爱立信设计它用于电话呼叫:最初的长生命周期连接。每个呼叫都保持状态、运行数分钟,系统需要并发处理数百万个。BEAM 轻量级进程大约 2KB。你可以生成数百万个。每一个都有自己的堆、自己的垃圾收集器,并被抢占式调度,所以没有单个进程能够独占 CPU。

Node.js 也能处理得相当不错,感谢它的事件循环和异步模型。但有关键的不同之处:

单线程 vs 抢占式调度。Node.js 运行在一个线程上(worker 线程除外)。如果一个智能体执行 CPU 密集型工作(分词、大型响应的 JSON 解析、嵌入计算)就会阻塞该进程上所有其他智能体。BEAM 在其轻量级进程之间抢占式地每 4000 次约简(reductions)切换一次。没有进程能够饿死其他进程。

进程隔离。在 Node.js 中,异步处理器中一个未处理的异常可能导致整个进程崩溃,影响所有连接。在 BEAM 上,每个智能体是一个隔离的进程,有自己的内存。一次崩溃不影响任何其他东西。

垃圾回收。Node.js 有全局停止 GC 暂停,影响所有连接。BEAM 按进程进行垃圾回收:微小、增量、无法察觉。在 1 万个并发智能体会话时,这很重要。

原生分布式。需要扩展到多台机器?BEAM 进程可以透明地跨节点通信。在 Node.js 中,你需要设置 Redis pub/sub、消息队列或自定义集群。

Phoenix(Elixir 的 web 框架)已经为实时应用处理这种模式。Phoenix Channels 和 LiveView 经常在单台服务器上持有 100,000+ 并发 WebSocket 连接。AI 智能体聊天会话只是另一个长生命周期的连接。从运行时的角度来看没有什么特别的。

每个人都在重新发明的模式

看看主要 Python AI 智能体框架正在构建的内容,你会看到一个模式。

Langroid 对此最明确。他们的 README 说多智能体范式是"受 Actor 框架启发的"。智能体是"消息变换器",通过直接消息传递进行通信。这几乎就是 Actor 模型的字面意思。

LangGraph 采取不同的方法:智能体是有状态图中的节点,共享状态通过 reducer 流动。他们在内部将这些称为"状态机"。核心抽象是一个 StateGraph,其中节点读写共享状态,条件边控制流。

CrewAI 将智能体组织成"团队",通过任务输出传递和委托进行协调。当一个智能体完成一项任务时,其输出成为下一个的上下文。智能体还可以相互委托子任务。启用时,团队中的所有智能体共享内存(短期、长期、实体)。

然后是 AutoGen。微软的框架在 v0.2 中以对话驱动开始:智能体以定义的模式交换消息(两智能体聊天、组聊、顺序聊天)。但当他们为 v0.4 重建它时,他们直接采用了他们称之为"事件驱动 Actor 框架"的方案,具有异步消息传递和运行时管理的智能体生命周期。措辞很有意思:他们独立地发现了 Actor 模型,因为问题要求它。

他们有多接近?AutoGen 0.4 的智能体通过消息通信、有运行时管理的生命周期、可以跨进程分布式运行。这听起来像 Actor。但在幕后,它是单线程的 Python asyncio。没有抢占式调度、没有按智能体的垃圾回收、没有监督树、没有"让它崩溃"恢复。他们的消息层是同步 RPC(请求/响应)和异步 pub/sub(事件)的混合体,这很实用但不是真正 Actor 的干净消息传递语义。这是 Actor 模型作为追求,而不是作为运行时。他们在一个本身不支持这些的语言上构建抽象。

每个框架都采取不同的路径,但他们都在聚合到同一组问题上:

智能体如何通信? 消息传递(Langroid、AutoGen 0.4)、共享状态(LangGraph)或任务输出链接(CrewAI)。

你如何编排工作流? 状态图(LangGraph)、任务序列(CrewAI)、对话模式(AutoGen)或任务循环(Langroid)。

你如何处理故障? LangGraph 有重试策略和检查点。其他框架依赖应用级 try/except。

你如何管理智能体生命周期? AutoGen 0.4 的运行时创建和跟踪智能体实例。其他框架大多将此留给开发者。

现在将这些与 OTP(Erlang 开放电信平台)比较,该平台在 1998 年为电信交换机正式化,需要处理数百万个并发呼叫且零停机:

这些的每一个都是 BEAM 上的已解决问题。不是作为库。而是作为运行时。隔离状态、消息传递、监督、故障恢复、进程注册表、事件广播、分布式通信:所有都内置在运行时中。

让它崩溃(以及为什么这对 AI 智能体完美)

这是 BEAM 哲学付出代价的地方。

AI 智能体本质上是非确定性的。LLM 调用每次返回不同的结果。工具调用不可预测地失败。速率限制无警告地触发。上下文窗口溢出。JSON 解析中断,因为模型幻觉出了无效语法。超时发生,因为 API 提供商日子不好过。

在 Python 中,你通过防守式编码处理这个。每个 LLM 调用都包装在 try/except 中。每个工具调用都有重试逻辑。你构建错误状态管理、回退链、指数退避。成功路径在错误处理层下消失。

# Python 的方式:防守式包装一切
try:
    response = await llm.chat(messages)
except (RateLimitError, TimeoutError, JSONDecodeError) as e:
    logger.error(f"LLM call failed: {e}")
    response = fallback_response()
# 对每个工具调用、每个 API 请求、每个解析步骤重复。

BEAM 的"让它崩溃"哲学采取相反的方法。你不是预期每个故障模式,而是写成功路径并让进程崩溃。监督者检测到崩溃并以干净状态重启进程。系统的其余部分不受影响。

# Elixir 的方式:写成功路径,监督其余部分
defmodule AIAgent do
  use GenServer

  def handle_call({:ask, question}, _from, state) do
    response = LLM.chat(state.messages ++ [question])
    tool_result = Tools.execute(response.tool_call)
    final = LLM.chat(state.messages ++ [response, tool_result])
    {:reply, final, %{state | messages: state.messages ++ [question, final]}}
  end
  # 无 try/catch。如果 LLM 超时、返回垃圾
  # 或工具崩溃:进程崩溃。
  # 监督者以干净状态重启它。
end

defmodule AgentSupervisor do
  use Supervisor

def init(_) do children = [ {AIAgent, name: :research_agent}, {AIAgent, name: :coding_agent}, {AIAgent, name: :review_agent} ] # One crashes? Restart just that one. Others keep working. Supervisor.init(children, strategy: :one_for_one) end end


这对 AI 智能体至关重要,因为你无法预测非确定性系统的所有故障模式。无论写多少防御性代码,都不可能覆盖 LLM 给你带来意外的每一种方式。模型可能会用一种你没有预料到的语言返回响应,可能会调用一个不存在的工具,也可能陷入无限的自我纠正循环。

有了监督树,你就不需要预测这些故障。你只需要定义恢复策略:重启智能体、使用不同参数重启智能体、重启整个对话,或者在尝试 N 次后放弃。其余工作由运行时处理。

在 LangGraph 中,你需要借助外部基础设施才能获得同等的可靠性。而在 Elixir 中,只需几行代码和运行时即可实现。

## 热代码替换:无停机更新智能体

BEAM 支持热代码加载。你可以在不停止系统的情况下,将新代码部署到正在运行的系统中。正在运行的进程会继续执行旧代码,直到它们准备好切换,然后无缝采用新版本。

想想当你需要在生产环境中更新智能体行为时会发生什么:

- 发现边缘情况后,你优化了系统提示词
- 你需要向智能体的工具集中添加一个新工具
- 你想更改智能体决定何时升级给人工处理的决策逻辑
- 你需要修复智能体解析 LLM 响应方式中的错误

在 Python 部署中,你需要重启进程。所有正在进行的对话都会中断,用户会断开连接,活跃对话也会丢失。你要么接受这种中断,要么构建复杂的蓝绿部署基础设施,并实现状态序列化和会话排空。

在 BEAM 上,你可以部署新代码,正在运行的智能体会在处理下一条消息时采用它。一个正处于协商过程中的智能体,会使用旧代码完成当前轮次,再使用新代码处理下一条消息。连接不会中断,状态不会丢失,也不会产生停机时间。

Ericsson 构建这一能力,是因为你不可能对一百万名电话用户说:“我们正在更新交换机,请稍候。”同样的原则也适用于 AI 智能体:你不可能让一千个正在执行任务的智能体停下来重启。

AI 工作负载正在从单次推理转向长期运行的多智能体系统。编码智能体会并行启动数十个子智能体;客户支持智能体会一边调用内部 API,一边进行持续数分钟的对话;研究智能体会跨多个模型协调搜索、综合与验证;商业智能体会自主协商价格并执行交易。McKinsey 预测,到 2030 年,仅 AI 智能体参与撮合的全球商业交易规模就可能达到 3 万亿至 5 万亿美元。

这些场景有一个共同点:你需要能够处理数千个并发智能体的基础设施,每个智能体都拥有自己的状态,能够异步通信、优雅地处理故障并自动恢复。这并非假想中的工作负载,而是当今每一个严肃的智能体部署实际呈现的样子。

这正是 BEAM 当初被构建出来要解决的问题。Ericsson 需要以五个九的可用性路由数百万通电话。电话呼叫是参与方之间的对话,需要维护状态、满足严格的延迟要求,而且单个呼叫可以失败,却不能拖垮整个交换机。把“电话呼叫”替换成“智能体会话”,两者的需求完全相同。

## 尚存的缺口(以及我们如何填补它们)

我最初关于这个话题的“争议观点”指出,Elixir 生态系统在 AI 智能体方面存在两个缺口:消息交换工具和可测试性。

消息交换方面的缺口已经基本补齐。Elixir 的 LangChain 库提供了用于受控执行智能体的分步模式;尽管名字如此,但它的设计相当出色,理应建立自己的声誉。ReqLLM 则为 LLM 集成提供了更轻巧灵活的替代方案。Jido 提供了一个完整的智能体框架。Phoenix Channels 和 PubSub 能够大规模处理智能体之间的实时通信。

可测试性则是我一直在通过 Tribunal 解决的问题。Tribunal 是一个面向 Elixir 的 LLM 评估框架,可与 ExUnit 集成:

```elixir
test "agent response is faithful to context" do
  response = MyAgent.answer("What's our return policy?", context: @policy_doc)

assert_faithful response, @policy_doc
  refute_hallucination response
  refute_bias response
end

目标是让测试 AI 智能体像测试其他任何 Elixir 代码一样自然。因为智能体就是进程,而进程是可测试的。

能否在 Python 或 TypeScript 中重新实现这一切?

一个很自然的质疑是:“当然,BEAM 拥有这些能力,但我们难道不能在 Python 或 TypeScript 中构建它们吗?”

人们已经尝试过了。下面是你会遇到的问题。

**Python:**GIL 阻碍了轻量级进程的真正并行执行。asyncio 为你提供了并发能力,却没有隔离性:所有协程共享同一块内存空间,一个行为不当的协程就可能破坏其他所有协程的状态。它没有逐协程垃圾回收机制,因此一个大量占用内存的智能体会影响整个进程。至于监督机制?不过是增加了额外步骤的 try/except。你无法在不从头重建的情况下,以干净状态重启一个协程,也无法透明地完成这一过程。即使是取消了 GIL 的 Python 3.13,相关库和框架也需要很长时间才能完成适配。

**TypeScript/Node.js:**得益于事件循环,它在并发方面表现得更好,但从根本上说仍然是单线程的。虽然存在工作线程,但它们是重量级的操作系统线程,而不是仅占 2KB 的进程。它没有抢占式调度:一个 CPU 密集型操作就会阻塞所有任务。没有热代码替换,也没有内置的跨节点分布式能力。

还有一些人尝试在现有虚拟机之上构建 Actor 运行时。JVM 上的 Akka 最为接近,它具备完善的监督树和位置透明的 Actor。Microsoft Orleans 则把虚拟 Actor 引入了 .NET。两者都印证了同一个观点:要让 Actor 良好运作,你需要运行时层面的深度支持;而这两个项目都投入了大量工程工作,才近似实现 BEAM 开箱即用的能力。

坦率地说,只要投入足够多的工程资源,你大概可以实现其中 70% 的能力。剩下的 30%——抢占式调度、逐进程垃圾回收、热代码替换,以及智能体之间真正的故障隔离——需要运行时层面的支持。你无法把这些能力强行附加到一种从设计之初就没有考虑它们的语言上。这并不是对 Python 或 TypeScript 的批评,只是因为它们原本就不是为此而构建的。

令人不安的事实

令人不安的事实是:你并不是在构建什么全新的东西。你只是在用一种并非为此设计的语言,重新构建电信基础设施。

业界已经开始注意到这一点。越来越多的团队先用 Python 为智能体制作原型,然后在生产阶段使用 TypeScript 重写。背后的理由非常实际:Node.js 更擅长处理并发连接,其异步机制更加成熟,而且面向无服务器和边缘环境的部署也更简单。据观察,近期相当一部分 YC 智能体创业公司在生产技术栈中选择了 TypeScript,而不是 Python。但正如上文所述,Node.js 只解决了一半问题。你获得了更好的并发能力,却仍然没有进程隔离、监督机制或容错能力。你只是用一组稍微好一些的局限,替换了原先的局限。

BEAM 正是为这一问题设计的,而 Elixir 让它变得易于使用。

我并不是说所有人都应该用 Elixir 重写自己的智能体系统。但如果你正准备从零开始构建一个新系统,尤其是需要以生产级可靠性处理数千个并发智能体的基础设施,那么你或许应该看看这项已经解决此类问题 40 年的技术。而且 Elixir 比你想象中更容易上手:语法简洁、工具链出色,LLM 编写 Elixir 代码的表现也非常好。

接下来从哪里开始

  • José Valim 的《Why Elixir is the Best Language for AI》介绍了 Elixir 对 LLM 友好的这一面
  • Elixir 的 LangChain 是该生态系统中最出色的 LLM 集成库
  • Jido 是一个基于 OTP 原则构建的完整智能体框架
  • Bumblebee 让你可以直接在监督树中运行 Transformer 模型
  • 我的 awesome-ml-gen-ai-elixir 列表涵盖了整个生态系统
Original source

本文由 AI 翻译整理自 Hacker News · georgeguimaraes.com,原文版权归原作者所有。

阅读英文原文
上一篇
Anthropic 禁用第三方订阅认证:API 政策重大调整
下一篇
Cursor 与 Copilot 深度对比:AI 编程工具实战评测