• 简体中文
  • v6.5.1
  • 多机器

    A3S Code 把多智能体编排表达为代码中的一套语法(grammar),再把由此产生的步骤 放到你希望它运行的任何地方。这一划分沿着框架 / 宿主边界展开,于 [3.4.0] 引入:

    • 框架拥有编排语法和可序列化的数据契约。它从不决定步骤在哪里运行。
    • 宿主拥有放置(placement)、传输和调度——哪个节点执行某个步骤、step 规格如何 送达、以及并发如何映射到集群。

    两者之间唯一的接触点是一个 trait:AgentExecutor

    框架 / 宿主边界

    框架的契约是两个可序列化类型:

    • AgentStepSpec——运行什么,与在哪里运行无关:task_idagentdescriptionprompt,以及可选的 max_stepsparent_session_idoutput_schema
    • StepOutcome——运行一个 spec 的结果:task_idsession_idagentoutputsuccess,以及可选的 structured

    两者都能干净地序列化,因此宿主可以把一个 spec 送到另一个节点,并把 outcome 持久化 到 checkpoint。组合这些 spec 的 combinators 完全针对 AgentExecutor trait 编写, 从不观察步骤实际在哪里运行——所以同一套编排可以从单进程扩展到集群而无需改动。

    AgentExecutor seam

    AgentExecutor 是语法与宿主之间的边界:

    Text
    combinators (parallel / pipeline / resumable)
    -> AgentExecutor::execute_step(spec) -> StepOutcome
    ├─ 内置 TaskExecutor:把步骤作为本地子 agent 运行
    └─ 宿主 executor:把步骤放到远程节点

    内置的 TaskExecutor 把每个步骤作为子 agent 在本地运行——在进程内、基于 Tokio—— 继承会话的 agent 注册表、LLM 客户端、工作区、MCP 工具和 subagent 跟踪器。诸如 集群运行时这样的宿主用自己的 executor 替换它,把步骤分布到集群;combinators 不受影响。

    concurrency_hint()建议性的,不是本地硬上限。本地默认返回会话的 max_parallel_tasks;由调度器支撑的宿主可以返回其集群范围的目标值。因为它是 hint 而非 ceiling,编排得以扩展到单进程之外。

    会话直接暴露内置 seam:

    • AgentSession::agent_executor() 返回一个由会话支撑的 AgentExecutor
    • AgentSession::session_store() 返回会话的 store(在配置了的情况下),可恢复的 combinator 需要它来记录进度。

    下面的 SDK 语法会替你调用 agent_executor();只有在实现或替换自定义 executor 时 你才需要直接使用它们。

    Parallel:屏障式 fan-out

    execute_steps_parallelspecs 在 executor 上 fan-out 并等待全部完成(一个 屏障 / barrier)。结果保持输入顺序,panic 的分支会变成一个失败的 StepOutcome 而不会拖垮整批,并且并发受 executor 的 concurrency hint 限制。

    TypeScript
    const outcomes = await session.parallel([
    {
    taskId: 'a',
    agent: 'explore',
    description: 'survey',
    prompt: 'Map the auth module',
    },
    {
    taskId: 'b',
    agent: 'review',
    description: 'audit',
    prompt: 'Review error handling',
    },
    ]);
    for (const o of outcomes) {
    console.log(o.taskId, o.success, o.output);
    }
    Python
    outcomes = session.parallel([
    {"task_id": "a", "agent": "explore", "description": "survey", "prompt": "Map the auth module"},
    {"task_id": "b", "agent": "review", "description": "audit", "prompt": "Review error handling"},
    ])
    for o in outcomes:
    print(o["task_id"], o["success"], o["output"])

    Pipeline:逐项链路,stage 之间无屏障

    execute_pipeline 让每个 item 独立地流经一条由 PipelineStage 组成的链路。 stage 之间没有屏障——item A 可以处于 stage 3,而 item B 仍在 stage 1——因此 墙钟时间取决于最慢的单条链路,而不是每个 stage 最慢步骤之和。

    一个 stage 是 (ctx) => spec | null 回调,其中 ctx 携带上一步的 outcome 和原始 item。返回一个 spec 以运行下一步,或返回 null 提前停止该 item 的链路;当某步失败 时链路也会停止(后续 stage 只会建立在失败结果之上)。这些桥接fail closed:一个 挂起、返回 null 或抛出的 stage 只会停止它自己的链路。

    Node 的 stage 回调绝不能 throw——把逻辑包在 try/catch 中并在出错时返回 null(与 setBudgetGuard 相同的约束)。挂起超过超时的 stage 会对该链路 fail closed。Python 的 stage 若 raise 会被捕获并当作 null 处理。

    TypeScript
    const outcomes = await session.pipeline(
    ['src/auth', 'src/api'],
    [
    (ctx) => ({
    taskId: 's1',
    agent: 'explore',
    description: 'survey',
    prompt: `Survey ${ctx.item}`,
    }),
    (ctx) =>
    ctx.previous?.success
    ? {
    taskId: 's2',
    agent: 'review',
    description: 'review',
    prompt: `Review: ${ctx.previous.output}`,
    }
    : null,
    ],
    );
    Python
    def survey(ctx):
    return {"task_id": "s1", "agent": "explore", "description": "survey",
    "prompt": f"Survey {ctx['item']}"}
    def review(ctx):
    prev = ctx["previous"]
    if prev and prev["success"]:
    return {"task_id": "s2", "agent": "review", "description": "review",
    "prompt": f"Review: {prev['output']}"}
    return None
    outcomes = session.pipeline(["src/auth", "src/api"], [survey, review])

    Resumable:跨节点恢复

    execute_steps_parallel_resumableparallel 加上一份日志。在每个步骤边界,它把 一个 WorkflowCheckpointworkflowId 为键写入 SessionStore。恢复时它跳过已 完成的步骤,重新派发其余步骤。它只记录成功的步骤,因此失败的步骤会在恢复时重试 ——它的效果尚未完成。

    需要一个 SessionStore。当未配置时,Node 桥接以 "parallelResumable requires a sessionStore" 拒绝;Python 抛出等价异常。

    TypeScript
    import { Agent, FileSessionStore } from '@a3s-lab/code';
    const session = agent.session('/repo', {
    sessionStore: new FileSessionStore('./.a3s/sessions'),
    });
    const outcomes = await session.parallelResumable(
    [
    {
    taskId: 'a',
    agent: 'explore',
    description: 'survey',
    prompt: 'Map the auth module',
    },
    {
    taskId: 'b',
    agent: 'review',
    description: 'audit',
    prompt: 'Review error handling',
    },
    ],
    'release-audit',
    );
    Python
    from a3s_code import Agent, FileSessionStore, SessionOptions
    opts = SessionOptions()
    opts.session_store = FileSessionStore("./.a3s/sessions")
    session = agent.session("/repo", opts)
    outcomes = session.parallel_resumable([
    {"task_id": "a", "agent": "explore", "description": "survey", "prompt": "Map the auth module"},
    {"task_id": "b", "agent": "review", "description": "audit", "prompt": "Review error handling"},
    ], "release-audit")

    因为 checkpoint 是可序列化的,且 executor 是一个参数,宿主可以通过传入另一个节点的 executor,在不同的节点上恢复被中断的工作流——框架迁移运行什么,宿主提供 在哪里运行

    Schema 强制的步骤输出

    携带 output_schema(Node 中为 outputSchema)的 spec 必须返回一个符合该 JSON Schema 的值;经校验的对象落入 StepOutcome.structured。executor 复用结构化输出的 coercion 与 repair 机制。coercion 失败会把该步骤降级为不成功,因此调用方永远不会 把未经校验的文本当作所承诺的对象。

    TypeScript
    const [finding] = await session.parallel([
    {
    taskId: 'classify',
    agent: 'review',
    description: 'classify',
    prompt: 'Classify this defect',
    outputSchema: {
    type: 'object',
    properties: { severity: { type: 'string' }, summary: { type: 'string' } },
    required: ['severity', 'summary'],
    },
    },
    ]);
    if (finding.success && finding.structured) {
    console.log(finding.structured.severity);
    }

    跨机器放置编排步骤

    lane queue 仍然是一种有效的传输——但它现在是AgentExecutor seam 背后的一个选项, 而不是唯一的集成点。要分布工作,宿主针对任何适合其平台的传输(HTTP、消息队列、 任务系统、lane queue、内部 RPC)实现 AgentExecutor::execute_step,把 concurrency_hint() 接到其集群目标,再把该 executor 交给 combinators。语法—— parallel、pipeline、resumable——保持不变;移动的只有放置。

    结果是:coordinator 会话拥有对话、最终合成和发布决策,而它的编排步骤在宿主放置的 任何地方执行,跨节点恢复由可序列化的 checkpoint 承载。

    参见 Orchestration 深入了解 combinator 语法,以及 Persistence 了解 checkpoint store。