AgentSPEX: An Agent SPecification and EXecution Language

Paper: arXiv:2604.13346 Code: ScaleML/AgentSPEX Code reference: main @ 2dc4d707 (2026-04-27)

1. Motivation (研究动机)

现有 LLM agent 的一个核心矛盾是:越长程、越需要分支/循环/工具调用的任务,越不适合只靠一个 system prompt 让模型“自己反应式执行”。论文把当前做法分成两类:一类是 ReAct-style prompting,把任务说明放在一个 prompt 里,让模型随历史上下文增长而自行决定下一步;另一类是 LangGraph、DSPy、CrewAI 等 Python-centric orchestration,把控制流写进 Python 图、pipeline 或 role-based team 中。前者实现简单,但控制流、状态和中间产物都是隐式的;后者结构更强,但 workflow logic 与 Python 代码耦合,非程序员难维护,也不利于版本管理、审阅和快速修改。

AgentSPEX 要解决的具体问题不是“再发明一个 agent benchmark”,而是提供一种可执行的 workflow specification language:用户用 YAML 声明 agent 的步骤、分支、循环、并发、子模块调用和显式状态;harness 负责按规范执行、记录、恢复和验证。这个目标值得研究,是因为复杂 agent 的实际痛点往往不是单步推理,而是长程执行时的 context rot、不可复现、调试困难、失败后不能 resume,以及工作流作者必须同时理解 prompt、Python orchestration 与运行环境。

论文的背景判断是:当任务涉及长输入、多阶段推理、外部工具和大量中间状态时,把 workflow 结构直接塞进 prompt 但不强制执行,反而会增加模型负担。AgentSPEX 的假设是:让模型做语义推理,让解释器执行控制流,可以减少模型同时“理解流程 + 解决问题”的负担。

2. Idea (核心思想)

核心创新是把 agent workflow 变成一种声明式、可执行、可视化、可恢复的 YAML DSL。YAML 文件不是配置附属品,而是 AgentSPEX 的 executable specification:它同时描述任务目标、模型/工具配置、参数、步骤序列、状态变量、控制流和模块组合。执行时,Interpreter 解析 DSL,LLM Executor 只负责每个 task / step 内部的多轮工具循环,Checkpoint/Trace 系统负责可恢复性和可复现性。

与 LangGraph 的关键区别是抽象边界:LangGraph 把 graph、state transition 和 node function 主要放在 Python 中;AgentSPEX 把 workflow logic 提升到 YAML 层,让自然语言 instruction、变量注入和控制流处在同一份可读文件里。与纯 prompt/skill 方法的区别是执行语义:AgentSPEX 不让模型“猜”下一步,而是由 harness 强制执行 ifwhilefor_eachparallelcall 等结构。

Figure 1 解读:左侧是 agent definition:YAML 中显式写出 namegoalconfigworkflow,并包含 for_eachcalltask 等 step type;中间是 visual flow editor,把同一份 YAML 同步成图;右侧是 agent harness,由 Interpreter、LLM Executor、Durability System 和 Sandbox Environment 组成。图中最重要的分工是:YAML/Editor 负责“定义”;Interpreter 负责“按结构调度”;LLM Executor 负责“单步内的工具循环”;Sandbox/MCP 负责“实际工具访问”;Durability 负责“恢复、重放、日志和 verification”。

3. Method (方法)

3.1 Workflow language:轻量但覆盖长程 agent 的核心控制模式

AgentSPEX workflow 的顶层结构包括 namegoal、可选 configparametersworkflow。论文 Figure 2 给出的例子是 topic research:先用 task 生成 search queries 并 save_as: search_queries,再用 call 调用 modules/search_and_summarize.yaml,最后用另一个 task 写 report。这里的关键不是 YAML 语法本身,而是每一步都有明确的输入、输出和状态名,后续步骤通过 {{variable}} 模板读取上下文变量。

论文 Table 1 支持的 constructs 如下:

CategoryConstructs作用
Invocationtask, steptask 开启新 conversation;step 继续 persistent conversation
Control flowif / switch, while, for_each条件分支、带上限循环、遍历列表
Compositioncall调用另一个 workflow 作为 submodule
Concurrencyparallel / gather并发执行步骤或子模块调用
Stateset_variable, increment, input, return显式写变量、累加、用户输入、返回值

taskstep 的差别是 AgentSPEX 的上下文控制核心:task 适合“只把特定中间产物传给下一步”的场景,因为它从新 conversation 开始;step 适合需要连续多轮上下文的场景,因为它保留 conversation history。这个设计把“哪些信息进入下一轮模型上下文”从模型隐式决定改成 workflow 作者显式决定。

3.2 State、composition 与 context visibility

每个 workflow 维护一组 named context variables。步骤可以用 Mustache-style template(如 {{search_queries}})引用变量,用 save_as 保存输出。call 把 workflow 统一成 composable module:一个 workflow 可以调用另一个 workflow,传入 parameters,接收 return value;workflow 也可以注册为 skills/tools,让 agent 在执行中动态调用。论文把这称为 unified submodule abstraction,因为 skills 和 agents 都是 workflow。

直觉上,这相当于把 agent 运行时的“黑箱聊天记录”拆成两层:语义推理由 LLM 完成,结构化状态由 harness 保存。这样做的收益是长程任务不必把所有历史都塞回 prompt;作者可以决定某一步只接收某个 summary、某组 query 或某个 file path。

3.3 Agent harness:Interpreter + Executor + Sandbox + Durability

Harness 的执行流程分四块:

  1. Interpreter:读取 workflow file,验证结构,解析 config/parameters,展开模板变量,然后按 step type dispatch 到对应 handler。嵌套结构(loop、conditional、submodule call)由 Interpreter 递归管理,并给每个 operation 分配层级 step id(例如 3.2.1),供 checkpoint 和 logging 使用。
  2. LLM Executor:对每个 taskstep 运行多轮 tool-calling loop。每一轮把当前 message history 发给模型,执行模型返回的 tool calls,经 MCP client 把结果追加到 history,直到模型不再调用工具或达到 token/tool-call limit。
  3. Sandbox Environment:workflow 在 Docker-based sandbox 中执行,具备 browser、file system,以及超过 50 类工具(file operations、web search、code execution、browser automation 等)。
  4. Durability System:每步完成后保存 checkpoint,包括已完成 step id、当前 context、step-level metrics 和 sandbox state;同时记录 execution trace,可用于 resume 和 selective trace replay。

Figure 3 解读:可视化编辑器左侧是 node palette,中间是 workflow graph,右侧是同步的 YAML editor。图里展示了 deep research agent 的 whilefor_eachparalleltaskset_variable 等嵌套结构;这说明 AgentSPEX 的可视化不是单独的 no-code layer,而是和 YAML spec 双向同步。对 workflow author 来说,图形视图降低理解成本,YAML 视图保留 version-control 和 code review 能力。

Figure 4 解读:dashboard 展示 SWE-Bench Verified run 的 step、iteration、tool calls、token/cost、message timeline、变量表和每轮 tool/result。它的作用不是给论文加 UI 截图,而是支撑长程 agent 的调试:如果某一步失败,用户可以看到是哪次 tool call、哪段 prompt、哪个 context variable 或哪次输出导致的,而不是只拿到一个最终失败结果。

3.4 Formal verification 的角色

AgentSPEX 的 verification 不是说 LLM 输出天然正确,而是说 YAML spec 让 control flow、variable dependency 和 step boundary 显式化,因此可以把 plan/trajectory 翻译成 Lean/Isabelle 等形式系统里的 predicate。Appendix C 用 AI Scientist 中的 extract_single_citation_module 展示:先从 task plan 推断变量应满足的 property,再对执行 trajectory 做 verification。这个方向的价值在于,它把“agent 是否按计划执行”从事后人工读日志,推进到可静态/运行时检查的形式。

3.5 released code 观察与伪代码

Code reference: main @ 2dc4d707 (2026-04-27) — pseudocode and mapping based on this commit

Paper ConceptSource FileKey Class/Function
YAML parsing / workflow validationsrc/harness/parsing/yaml_parser.pyYAMLTaskParser.load_task, _validate_task, _parse_step, _parse_for_each_step, _parse_parallel_step
Step dispatch / interpretersrc/harness/execution/interpreter.pyInterpreter.execute_workflow_step, _dispatch_step
step / task LLM invocationsrc/harness/execution/step_handlers/basic.pyBasicStepsMixin.execute_basic_step, execute_task_step
Control flowsrc/harness/execution/step_handlers/control.pyexecute_for_each_step, execute_conditional_step, execute_while_step, execute_switch_step
Submodule and concurrencysrc/harness/execution/step_handlers/calls.pyexecute_call_step, execute_gather_step, execute_parallel_step
Multi-turn tool loopsrc/harness/execution/llm_executor.pyLLMExecutor.multi_step_tool_call_loop
Checkpoint/resumesrc/harness/checkpoints/checkpoint_manager.pyCheckpointManager.__init__(load_existing=True), is_completed, mark_completed, _write_to_disk
Trace/replaysrc/harness/checkpoints/tracing.pyrecord_llm_iteration, _next_replay_event
Sandbox MCP tool serversrc/sandbox_vm/mcp/server.py, src/sandbox_vm/tools/mcp_server_tool_config.yamlregister_public_functions_as_tools, tool registry config
Visual editoryaml-flow-editor/src/App.tsx, yaml-flow-editor/src/components/nodes/*graph/YAML synchronized editor and node renderers
Formal verificationverifier/AgentVerifier/WorkflowToLean.py, verifier/AgentVerifier/*.leanYAML-to-Lean conversion and workflow predicates
Demo / benchmark workflowsdemo/*/*.yaml, src/benchmarks/*/*_agent.yamldeep research, AI scientist, AI advisor, AIME/ChemBench/ELAIP/SWE/WritingBench workflows

Parser 与 dispatch 的实现逻辑可概括为:

def load_and_dispatch_workflow(path, context, args, checkpoint_manager):
    task_data = YAMLTaskParser().load_task(path)          # yaml.safe_load + schema validation
    config = YAMLTaskParser().get_config_with_defaults(task_data)
    context.update(task_data.get("parameters", {}))
 
    for step_number, step_data in enumerate(task_data["workflow"], start=1):
        if checkpoint_manager and checkpoint_manager.is_completed(str(step_number)):
            continue
        output, tokens = interpreter.execute_workflow_step(
            step_data=step_data,
            context=context,
            step_number=step_number,
            args=args.with_config(config),
            checkpoint_manager=checkpoint_manager,
        )
        if checkpoint_manager:
            checkpoint_manager.mark_completed(str(step_number), output=output, context=context)

task / step 的实现差别在 conversation history:

def execute_llm_invocation(kind, step, context, args):
    instruction = expand_template_variables(step["instruction"], context)
    save_as = step.get("save_as")
 
    if kind == "step":
        messages = ensure_conversation_history(context, args)  # persistent history
    else:  # kind == "task"
        messages = []                                         # fresh conversation
 
    output, token_count = llm_executor.multi_step_tool_call_loop(
        step_id=step.get("name"),
        instruction=instruction,
        message_history=messages,
        tool_config=EffectiveToolConfig.compute(tools, context, step),
    )
 
    if save_as:
        context[expand_template_variables(save_as, context)] = try_parse_python_literal(output)
    return output, token_count

parallel / gather 的实现不是 prompt 里“请并行”,而是在 handler 中用 isolated context copy 和 ThreadPoolExecutor 并发执行:

def execute_parallel_step(parallel_spec, context, args):
    futures = []
    with ThreadPoolExecutor(max_workers=len(parallel_spec["steps"])) as pool:
        for i, child_step in enumerate(parallel_spec["steps"]):
            child_context = copy.deepcopy(context)
            futures.append(pool.submit(execute_workflow_step, child_step, child_context, f"parallel.{i}", args))
 
        outputs = [None] * len(futures)
        for i, future in enumerate(as_completed(futures)):
            output, tokens = future.result()
            outputs[i] = output
 
    if "save_as" in parallel_spec:
        context[parallel_spec["save_as"]] = outputs
    return outputs

Durability 的实现重点是 step-level checkpoint 与 trace event 对齐:

def durable_step(step_id, step_data, context):
    if checkpoint_manager.is_completed(step_id):
        return checkpoint_manager.get_substep_output(step_id)
 
    before = snapshot(context)
    output, tokens = interpreter.execute_workflow_step(step_data, context, step_id)
    trace.record_llm_iteration(step_id=step_id, input_context=before, output=output, tokens=tokens)
    checkpoint_manager.mark_completed(step_id, output=output, context=context)
    return output

论文公式与 released code 实现差异:这篇论文主要是系统/DSL 论文,没有训练目标或数学 loss;我没有发现需要在公式与代码之间对齐的核心算法公式。需要注意的实现细节是,README 示例里提到 workflows/quickstart.yaml,而 main@2dc4d707 的实际 demo/benchmark YAML 主要位于 demo/*src/benchmarks/*;笔记中的 workflow/code mapping 以实际仓库路径为准。

4. Experimental Setup (实验设置)

4.1 Demos

论文提供三个 ready-to-use agents:

  • Deep Research:输入用户 query,生成 Markdown report,模仿 OpenAI Deep Research / Gemini Deep Research 这类闭源产品。workflow 通过 breadth 控制每层搜索 query 数,通过 depth 控制 follow-up query 层数;每层生成 targeted queries,并行执行 search,抽取中间 findings。
  • AI Scientist:基于 Yu et al. (2025) 的实现,分为 Stage 1 Thinker 和 Stage 2 Writer。Thinker 做 safety classification、query generation、OpenAlex related-work retrieval、idea generation/refinement;Writer 顺序写论文段落,同时并行 citation workers 搜索并插入 references。
  • AI Advisor:输入 proposal/paper,先 parse 文档并切成 semantic chunks,再把每个 chunk 总结成 structured JSON,最后合成包含 summary、novelty、significance、soundness、strengths、weaknesses、recommendations 的 rubric-based review。

4.2 Benchmarks / datasets / metrics

论文在 7 个 benchmark 上报告 pass@1 accuracy,除特别说明外使用 full test set:

DomainBenchmark# ProblemsEvaluation
Software EngineeringSWE-Bench Verified500sb-cli / hidden unit tests
MathematicsAIME 202530Math-Verify
ChemistryChemBench90Exact Match
ChemistrySciBench chemistry subsets213Exact Match
ChemistryMMLU-Pro StemEZ physical chemistry216Exact Match
Generative WritingWritingBench120LLM-as-Judge, 5 criteria, 10-point scale
Paper UnderstandingELAIPBench403Exact Match

Baselines:多数 benchmark 对比 CoT 与 ReAct。CoT baseline 把必要信息放在单个 prompt 中;ReAct baseline 把 AgentSPEX workflow 放进初始 prompt,但不强制逐步执行,让模型自行解释 workflow 并决定 tool calls。AgentSPEX workflows 由作者手写,并借助 coding assistants。

模型设置:science、math、ELAIPBench 主要使用 GPT-5;WritingBench 使用 Claude-Sonnet-4.5-Thinking;SWE-Bench Verified 使用 Claude-Opus-4.5 与 Claude-Opus-4.6,reasoning effort 为 high,temperature=1.0。训练配置不适用:AgentSPEX 是 execution framework 论文,不训练新模型;仓库中的可复现实验入口是 src/benchmarks/*/*_agent.yamlscripts/run_agent.sh,而不是 training launch script。

5. Experimental Results (实验结果)

5.1 Main benchmark results

BenchmarkCoT / prior baselineReAct / prior baselineAgentSPEX
SciBench85.92%87.79%90.61%
StemEZ82.87%84.72%86.57%
ChemBench78.90%77.80%83.30%
AIME 202594.60% without tools / 99.60% with Python100.0%
ELAIPBench37.22%33.80%43.70%
WritingBench79.90%80.30%81.00%
SWE-Bench Verifiedmini-SWE-agent 76.20%Live-SWE-agent 74.60%77.10%

最强证据来自需要长输入或多步协调的任务:ELAIPBench 从 CoT 37.22% 提到 43.70%,ChemBench 从 CoT 78.90% / ReAct 77.80% 提到 83.30%。论文正文解释为:ReAct 虽然看到同一份 workflow,但没有 harness 强制执行,模型必须同时解释 workflow 结构和解决任务;AgentSPEX 把控制流交给 interpreter,可以减少这种额外负担。表 2 与正文有一个小表述细节:ChemBench 的 83.30% 相对 ReAct 是 +5.50 pp,相对 CoT 是 +4.40 pp;正文写“+5.5%”时对应的是 ReAct 差值。

5.2 SWE-Bench model-version robustness

SWE-Bench Verified 的附录表显示,AgentSPEX 在 Claude-Opus-4.5 到 4.6 的变化中更稳定:

AgentClaude-Opus-4.5Claude-Opus-4.6Δ
mini-SWE-agent76.8%75.6%-1.2
Live-SWE-agent78.0%71.2%-6.8
AgentSPEX77.2%77.0%-0.2

这支持论文关于“Python prompt/control-flow 强耦合会对模型行为漂移敏感”的论点:当模型版本变化时,如果 prompt、控制流和 orchestration logic 交织在代码中,可能需要同步改 prompt 与 Python;AgentSPEX 把 workflow 结构放在 YAML spec 中,模型升级时行为更可控。

5.3 User study and framework comparison

用户研究包含 23 名参与者;每人看到两个实现同一 agentic behavior 的 workflow,一个用 AgentSPEX,一个用 LangGraph,并评价 interpretability 与 adoption preference。定性结果:参与者更常把 AgentSPEX 描述为 “accessible to non-coders” 和 “easier to understand”;LangGraph 则被认为 “customizable” 和 “more rigorous”。关键限制也在这里:多数参与者更愿意用 LangGraph 构建 complex workflow / 复杂多步 workflow,说明 AgentSPEX 的可读性优势并不自动转化为复杂工程信心。

框架对比表中,AgentSPEX 是唯一同时标记 Natural Language、Explicit Context、Visual Editor 三项为 ✓ 的方法;AutoGen/DSPy 三项均为 ✗,CrewAI 只有 Natural Language 为 Partial,LangGraph w/ LangFlow 有 Visual Editor 但没有 Natural Language 和 Explicit Context,PDL 有 Natural Language 且 Explicit Context 为 Partial。

5.4 Limitations and future work

论文没有列出传统意义上的 failure-case ablation,但从 discussion 可以归纳出三类限制。第一,AgentSPEX workflows 仍需要人工设计,论文也说 workflows are written manually with coding assistants;自动写 workflow 是 future work。第二,用户研究显示复杂 workflow 的可定制性信心仍不如 LangGraph。第三,formal verification 目前更多是潜力展示;要真正覆盖 agent execution 的语义正确性,还需要更完整的 predicate system、runtime checks 和外部工具验证。

未来方向包括:formal verification of agent execution、训练模型自动写/使用 workflows、把 end-to-end agentic training pipelines 纳入框架、增强 multi-agent orchestration,以及通过 context-compression 和更强抽象支持 long-context / longer-horizon tasks。