← 返回文章

ARTICLE

Agenstro 开发记录(一):项目动机

从早期工作流编排的局限出发,说明为何把 agent loop 视作原子化领域函数,并以函数式编程组织可组合、可持久化的工作流。

5 分钟阅读#Agenstro · #Agent · #工作流 · #函数式编程
文章目录

项目的动机

笔者从25年9月开始使用agent进行科研与软件开发,主要使用codex和claud code(glm系模型),早期也使用过memgpt(后改名为letta),langchain等。 最初的目的是希望大模型能够作为一个组建,将一些本来无法流水线化的工作流水线化,例如写论文、写报告、自动做科研等等。 这些尝试大概可以分为如下几个类别:

  • 直接使用llm的json output功能进行开发
  • 使用类似DAG的框架,例如langgraph或者memgpt
  • 使用agent软件,主要是codex和claude code

前两者显而易见的失败了,否则目前agent软件也不会成为当前(25年Q3至现在)的主流方案,究其原因是大模型会不会做一个问题本身是由预训练和后训练决定的,这些才是大模型深层次的skill来源,包括代码编写、漏洞排查、前端设计、再到现在Astra的blender建模能力,均是如此。 很多时候开源社区前脚刚写好的skills,不久之后就被整合到了llm的行为当中。 因此笔者意识到,早期关于工作流编排的诸多问题,根本上是没有想清楚”原子化“的工作单元到底是什么,因此就有了这个项目,其核心理念是:

”把agent loop当作原化的领域函数,借助functional programming的思路编排和持久化工作流“

其中的一些具体的设计思路受到的某数学专家的启发,这一点未来有可能会谈谈。

agent loop 为什么是原子化的工作单元

Agent loop (或者说session loop) 经过一年的发展已经成为了LLM领域的典型工作模式,其由一系列reasoning—>tool call交替进行,当最后一个tool call调用结束之后,agent loop到达终止条件。 这种agent loop的控制结构业内通常称之为agent harness,各大llm研发机构根据自家llm的特性开发了不同的agent harness框架,其中最成功的便是codex和claude code。 Agent harness项目例如opencode、dsh、或者hermes与openclaw,要么是token消耗量过大,要么是不能发挥模型本身的性能。 究其原因在于llm与llm的harness框架本身存在耦合,很多agent loop行为根源上是llm研发机构基于强化学习数据库训练得到的,典型的场景包括但不先于

  • 代码修复
  • 漏洞检查
  • 前端设计
  • 近期Astra的blender场景调用

早期的harness理念是,更多的tool和skills就会给予agent完成复杂任务更高的可能性,并且认为这里面的副作用主要是context长度。 但这样的假设却是忽略了一个基本事实是,llm可能压根不会使用这些tool,即使他们能够给出一个差不多的答案,但在语法的精确性上会存在问题,并且每一个tool包含的潜在信息量也未必在训练数据集当中。 最终的结果是,对于真正复杂的任务,仍然需要人类专家指导,通过多轮次的prompt完成,这就是skills出现的雏形。 但skills能承载的信息量仍然是有限的,多步工作时就会面临模型context上限的问题(推理性能退化,compaction后关键信息丢失)。

也就是说,llm的能力受到上下文的限制,这种限制亦可以说是一种复杂性限制,体现在工作流的多步骤,模块间的相互耦合问题等等。 如果把agent loop当作完成任务的原子单元,核心的工程挑战便落在了如何拆分工作流,以及如何设计每个步骤之间的信息传递协议等问题上。

工作流的稳定性与持续工作难题

工作流编排一个自然的想法是基于DAG(有向无环图)去描述,其中各个物件的对应关系是

  • 节点:对应于任务本身
  • 带方向的边:任务的依赖关系,信息传递的协议
  • 无环:说的是任务之间不允许出现循环依赖

Langchain/Langgraph是实现DAG的一个典型方法,并且目前也支持把agent当作任务的执行单元。 它的边一般通过一个具有一般性的json schema传递,能够给任务设计带来最大的自由度。

但这套框架的问题在于,极其难以管理副作用,一旦agent执行失败,或者输出不符合json schema,就会导致整个任务无法继续进行。 而且这个问题面临本质性的困难,没有人能给出agent运行的边界case,那就几乎不可能给出一个稳定性评估,持续工作也无从谈起。 agent能够在统计意义上,可能以80%的概率完成任务,但只要在多步骤过程中,剩余20%概率就可能炸掉整个流程,这是无法接受的问题。

基于函数式编程的编排思路

既然DAG的思路走不通,为什么不直接把agent calling直接封装为一个函数,然后用函数式编程(Functional programming, FP in short)的的方式管理副作用。 有几个理由:

  • DAG自然的是FP的一个子集,该有的能力FP全有
  • 副作用管理,FP能够显式的处理副作用,保持失败可观测的同时允许程序带着错误继续运行下去。
  • FP的高阶抽象与可组合性质允许了两件事,一个是可证明的能力边界,另一个是可以随着llm的演进同时改变各个组件,包括但不限于agent产品本身,effect控制等。

这一方面上deepseek的harness框架正是这样做的(不过他们是做的agent loop本身,不是工作流编排),甚至把agent loop的运行时(dsh中称作fiber)都做了形式化的抽象。 可以猜测ds在这方面确实想把dsh作为一个能够长期随着llm演化而动态更新的工具。

继续阅读