RFC: CLI adapter 约定 + agent binding 纯数据化 #307

Closed
opened 2026-05-18 04:21:18 +00:00 by xiaoju · 1 comment
Owner

背景

workflow 已经纯数据化(roles、moderator 都是 JSON,存 CAS)。现在需要把 agent binding 也纯数据化,并约定 CLI adapter 的调用协议。

CAS 结构示例

solve-issue workflow 为例,完整的 CAS 节点树:

1. Role Schema 节点

// hash: S1 (type: role-schema)
{
  "type": "object",
  "required": ["repoPath", "defaultBranch", "conventions", "toolchain"],
  "properties": {
    "repoPath": { "type": "string" },
    "defaultBranch": { "type": "string" },
    "conventions": { "anyOf": [{ "type": "string" }, { "type": "null" }] },
    "toolchain": { ... }
  }
}

2. Role 节点

// hash: R1 (type: role)
{
  "name": "preparer",
  "description": "Locates or clones the target repository...",
  "systemPrompt": "You are a **preparer** for a software task...",
  "extractPrompt": "Extract the structured repo preparation result as JSON...",
  "schema": "S1"  // cas_ref → role-schema
}
// hash: R2 (type: role)
{
  "name": "developer",
  "description": "Delegates the actual implementation...",
  "systemPrompt": "You are the **developer**...",
  "extractPrompt": "Extract the developer result as JSON...",
  "schema": "S2"  // cas_ref → role-schema
}
// hash: R3 (type: role)
{
  "name": "submitter",
  "description": "Pushes the branch and opens a PR.",
  "systemPrompt": "You are the **submitter**...",
  "extractPrompt": "Extract the submitter result as JSON...",
  "schema": "S3"  // cas_ref → role-schema
}

3. Agent 节点(新增 🆕

// hash: A1 (type: agent)
{
  "command": "hermes-workflow-agent"
}
// hash: A2 (type: agent)
{
  "command": "cursor-workflow-agent"
}

agent 节点极简 — 只声明 CLI 命令。-t <thread_id>-r <role> 由 engine 统一拼接,不需要在节点里重复。

4. Workflow 节点

// hash: W1 (type: workflow)
{
  "name": "solve-issue",
  "description": "Resolve an issue end-to-end...",
  "roles": {
    "preparer": "R1",   // cas_ref → role
    "developer": "R2",  // cas_ref → role
    "submitter": "R3"   // cas_ref → role
  },
  "moderator": [
    { "from": "__START__", "to": "preparer", "when": null },
    { "from": "preparer", "to": "developer", "when": null },
    { "from": "developer", "to": "submitter", "when": null },
    { "from": "submitter", "to": "__END__", "when": null }
  ]
}

5. 注册表

# ~/.uncaged/workflow/workflow.yaml
workflows:
  solve-issue: W1  # cas hash
  develop: W2
  code-review: W3

6. Thread Start 节点(执行时)

// hash: TS1 (type: thread-start)
{
  "workflow": "W1",        // cas_ref → workflow
  "input": "Fix issue #42: login redirect loop",
  "depth": 0,
  "parentThread": null,
  "agents": {               // 🆕 agent bindings 在这里
    "preparer": "A1",      // cas_ref → agent (hermes)
    "developer": "A2",     // cas_ref → agent (cursor)
    "submitter": "A1"      // cas_ref → agent (hermes)
  }
}

CLI 调用协议

约定

<agent-command> -t <thread_id> -r <role>
  • -t / --thread: thread ID
  • -r / --role: role name
  • stdout: meta JSON(符合该 role 的 schema)
  • stderr: 日志/调试信息(engine 不消费)

执行流

engine 决定下一个 role (via moderator)
  ↓
从 thread-start.agents[role] 拿到 agent hash
  ↓
从 CAS 拿 agent 节点 → 得到 command
  ↓
`<command> -t <thread_id> -r <role>`
  ↓
agent 内部通过 uncaged-workflow 获取:
  - systemPrompt (从 role 节点)
  - extractPrompt (从 role 节点)
  - schema (从 role-schema 节点)
  - thread 上下文 (从 thread 链)
  ↓
agent 执行 LLM 调用,输出结果
  ↓
stdout → meta JSON
  ↓
engine 验证 schema、写入 CAS

关键设计点

  1. agent 节点不在 workflow 里 — workflow 是纯逻辑定义(谁做什么),agent 绑定在 thread-start 里(谁来做)。同一个 workflow 不同次执行可以绑不同 agent。

  2. agent 节点极简 — 只有 command,可选 env。所有上下文通过 uncaged-workflow CLI 获取,不需要在 agent 节点里描述。

  3. stdout 即结果 — agent 输出的 meta JSON 就是唯一接口,engine 负责 schema 验证和 CAS 写入。

  4. agent 可复用 — 多个 role 可以指向同一个 agent hash(如上例 preparer 和 submitter 共用 hermes)。

待讨论

  • agent 节点是否需要 env 字段?(传额外环境变量给 CLI)
  • agent 节点是否需要 timeout 字段?(engine 侧超时控制)
  • CLI 是否需要传 workflow hash?(目前设计里 agent 通过 thread_id 反推 workflow)
  • react trace 怎么传回?(stdout 只有 meta,trace 走哪里?)

小橘 🍊(NEKO Team)

## 背景 workflow 已经纯数据化(roles、moderator 都是 JSON,存 CAS)。现在需要把 agent binding 也纯数据化,并约定 CLI adapter 的调用协议。 ## CAS 结构示例 以 `solve-issue` workflow 为例,完整的 CAS 节点树: ### 1. Role Schema 节点 ```json // hash: S1 (type: role-schema) { "type": "object", "required": ["repoPath", "defaultBranch", "conventions", "toolchain"], "properties": { "repoPath": { "type": "string" }, "defaultBranch": { "type": "string" }, "conventions": { "anyOf": [{ "type": "string" }, { "type": "null" }] }, "toolchain": { ... } } } ``` ### 2. Role 节点 ```json // hash: R1 (type: role) { "name": "preparer", "description": "Locates or clones the target repository...", "systemPrompt": "You are a **preparer** for a software task...", "extractPrompt": "Extract the structured repo preparation result as JSON...", "schema": "S1" // cas_ref → role-schema } ``` ```json // hash: R2 (type: role) { "name": "developer", "description": "Delegates the actual implementation...", "systemPrompt": "You are the **developer**...", "extractPrompt": "Extract the developer result as JSON...", "schema": "S2" // cas_ref → role-schema } ``` ```json // hash: R3 (type: role) { "name": "submitter", "description": "Pushes the branch and opens a PR.", "systemPrompt": "You are the **submitter**...", "extractPrompt": "Extract the submitter result as JSON...", "schema": "S3" // cas_ref → role-schema } ``` ### 3. Agent 节点(新增 🆕) ```json // hash: A1 (type: agent) { "command": "hermes-workflow-agent" } ``` ```json // hash: A2 (type: agent) { "command": "cursor-workflow-agent" } ``` agent 节点极简 — 只声明 CLI 命令。`-t <thread_id>` 和 `-r <role>` 由 engine 统一拼接,不需要在节点里重复。 ### 4. Workflow 节点 ```json // hash: W1 (type: workflow) { "name": "solve-issue", "description": "Resolve an issue end-to-end...", "roles": { "preparer": "R1", // cas_ref → role "developer": "R2", // cas_ref → role "submitter": "R3" // cas_ref → role }, "moderator": [ { "from": "__START__", "to": "preparer", "when": null }, { "from": "preparer", "to": "developer", "when": null }, { "from": "developer", "to": "submitter", "when": null }, { "from": "submitter", "to": "__END__", "when": null } ] } ``` ### 5. 注册表 ```yaml # ~/.uncaged/workflow/workflow.yaml workflows: solve-issue: W1 # cas hash develop: W2 code-review: W3 ``` ### 6. Thread Start 节点(执行时) ```json // hash: TS1 (type: thread-start) { "workflow": "W1", // cas_ref → workflow "input": "Fix issue #42: login redirect loop", "depth": 0, "parentThread": null, "agents": { // 🆕 agent bindings 在这里 "preparer": "A1", // cas_ref → agent (hermes) "developer": "A2", // cas_ref → agent (cursor) "submitter": "A1" // cas_ref → agent (hermes) } } ``` ## CLI 调用协议 ### 约定 ```bash <agent-command> -t <thread_id> -r <role> ``` - `-t` / `--thread`: thread ID - `-r` / `--role`: role name - **stdout**: meta JSON(符合该 role 的 schema) - **stderr**: 日志/调试信息(engine 不消费) ### 执行流 ``` engine 决定下一个 role (via moderator) ↓ 从 thread-start.agents[role] 拿到 agent hash ↓ 从 CAS 拿 agent 节点 → 得到 command ↓ `<command> -t <thread_id> -r <role>` ↓ agent 内部通过 uncaged-workflow 获取: - systemPrompt (从 role 节点) - extractPrompt (从 role 节点) - schema (从 role-schema 节点) - thread 上下文 (从 thread 链) ↓ agent 执行 LLM 调用,输出结果 ↓ stdout → meta JSON ↓ engine 验证 schema、写入 CAS ``` ## 关键设计点 1. **agent 节点不在 workflow 里** — workflow 是纯逻辑定义(谁做什么),agent 绑定在 thread-start 里(谁来做)。同一个 workflow 不同次执行可以绑不同 agent。 2. **agent 节点极简** — 只有 `command`,可选 `env`。所有上下文通过 `uncaged-workflow` CLI 获取,不需要在 agent 节点里描述。 3. **stdout 即结果** — agent 输出的 meta JSON 就是唯一接口,engine 负责 schema 验证和 CAS 写入。 4. **agent 可复用** — 多个 role 可以指向同一个 agent hash(如上例 preparer 和 submitter 共用 hermes)。 ## 待讨论 - [ ] agent 节点是否需要 `env` 字段?(传额外环境变量给 CLI) - [ ] agent 节点是否需要 `timeout` 字段?(engine 侧超时控制) - [ ] CLI 是否需要传 workflow hash?(目前设计里 agent 通过 thread_id 反推 workflow) - [ ] react trace 怎么传回?(stdout 只有 meta,trace 走哪里?) --- 小橘 🍊(NEKO Team)
Author
Owner

Closing: Agent binding redesigned — AgentContext extends ModeratorContext, agents own detail (PR #338-341)

— 小橘 🍊(NEKO Team)

Closing: Agent binding redesigned — AgentContext extends ModeratorContext, agents own detail (PR #338-341) — 小橘 🍊(NEKO Team)
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: uncaged/workflow#307