Files

248 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AgentRun 架构参考
AgentRun 是面向 UniDesk 与 HWLAB 的共享 Agent 执行面。它包含执行内核、Session、Scheduler 和 Queue。UniDesk Code Queue 的下一阶段收敛方向是被 AgentRun Queue 直接吸收;不做 adapter 过渡、双写或旧 Code Queue API/UI/CLI 兼容层。旧 Code Queue 只保留冻结/归档语义,新任务进入 AgentRun Queue。
## 产品边界
AgentRun 负责通用执行基础设施:
- 创建和跟踪 run
- 接收 `turn``steer``interrupt``resume` 等 durable command
- 将 run 分配给短生命周期 runner
- 归一化 backend event、stdout/stderr、assistant message、tool call 和 terminal status
- 管理 lease、heartbeat、基础设施恢复导致的 retry 语义和 run 可观测性;
- 注册 backend capability,并定义 credential 注入边界;
- 提供 Queue task、attempt、summary、stats、read cursor 和 commander 聚合,替代 UniDesk Code Queue 的新任务入口。
UniDesk 与 HWLAB 是 tenant/client。UniDesk 负责平台入口、provider 清单和旧 Code Queue 归档;新任务队列能力进入 AgentRun Queue。HWLAB 负责实验室任务 policy、设备/硬件语义、operation/audit/evidence 模型和 HWLAB workspace 规则。AgentRun 不判断某个 HWLAB live device mutation 是否被授权,也不判断某个 UniDesk production deployment 是否允许执行;它只执行 tenant policy 已授权的 run 或 Queue task。
每个 run 都必须显式携带隔离字段:
- `tenantId`,例如 `unidesk``hwlab`
- `projectId`,例如 `pikasTech/unidesk``pikasTech/HWLAB`
- `workspaceRef`,用于定位 source/worktree/workspace
- `providerId`,例如 `G14``D601`
- `backendProfile``v0.1` allowlist 为 `codex``deepseek``minimax-m3`Queue 首版废弃旧 MiniMax/OpenCode 直连路线,只允许 Codex/Codex-compatible profile
- `executionPolicy`,包含 sandbox、approval、timeout、network 和 secret scope
- `traceSink`,说明标准化 event 镜像到哪里。
HWLAB 接入时必须显式分离业务 identity 和执行 identityHWLAB `conversationId` / `sessionId` / `threadId` 是业务会话,AgentRun `runId` / `commandId` / `runnerJobId` 是执行尝试,AgentRun `SessionRef` / PVC 是 backend profile 续接状态。HWLAB Workbench 的 project/workspace 字段只能作为 HWLAB metadata 或 `workspaceRef` 子字段,不得写入 AgentRun `projectId`AgentRun `projectId` 仍固定表达 tenant policy 边界,例如 `pikasTech/HWLAB`
架构混乱的临时处理原则:发现 HWLAB provider/session/project/workspace 与 AgentRun tenant/project/run/job 字段混用时,不放宽 manager tenant policy、不改成 fallback backend、不靠 prompt 历史模拟续接。先在目标 runtime 用最小真实请求核对 run payload、runner job env、`SessionRef`、PVC phase、lease 和 command events;必要时热补丁只用于证明单变量修复,随后必须回到源码、CI/CD 和原入口复测。
长期收敛建议:跨仓库 API/schema 应使用不同字段名表达不同层级,例如 `hwlabProjectId` / `agentRunProjectId``hwlabSessionId` / `agentRunSessionId``providerProfile` / `backendProfile``runId` / `sessionId`。客户端和 Web 应同时展示业务 session/thread/provider 与执行 run/job/command,避免 operator 把 replacement runner 当作新业务 session 或把业务 workspace project 当作 AgentRun tenant policy。
## 服务形态
AgentRun 应构建为小型服务族:
```text
agentrun-mgr
公共 RESTful API、durable facts、tenant/policy/idempotency 检查
agentrun-runner
短生命周期 per-run 或 per-attempt executorclaim 一个 run,连接一个 backend,写回 events/status
agentrun-backend-*
Codex/Codex-compatible 执行适配器;Queue 首版不接旧 MiniMax/OpenCode 直连路线
agentrun-queue
task、attempt、summary、stats、read cursor、commander 聚合;输出和 trace 只返回 Session 引用
agentrun-scheduler
后续自动 dispatcher;扫描 pending runs,选择 backend/profile/capacity,创建 runner Jobs
```
Manager 是稳定 API 和审计点。Runner 是执行者,不应成为业务客户端直接调用的公共 API。MVP 阶段 operator 可以人工启动 runner 进程或 Kubernetes Job,但 runner 仍必须从 `agentrun-mgr` claim run,并把所有事实写回 manager。
Backend adapter 隐藏具体工具协议。`v0.1` 和 AgentRun Queue 首版只把 Codex app-server stdio 作为正式执行路径,`codex``deepseek``minimax-m3` 是同一 backend kind 下的 profile/config/SecretRef 选择。跨 backend kind 路由属于后续规格;旧 MiniMax/OpenCode 直连路线不作为 Queue 首版能力。
## v0.1 实现技术栈
AgentRun `v0.1` 自研 runtime 优先使用 Bun + TypeScriptmanager、runner、backend adapter、Codex backend、CLI 和后续 scheduler 都按这一技术栈实现。`scripts/agentrun-cli.ts` 是官方 CLI 入口;复杂 CLI 逻辑进入 `scripts/src/`,服务和 runner 逻辑进入 `src/`。YAML manifest、Tekton/Argo CD 配置、Postgres 和 Kubernetes 仍按各自原生生态管理。
Codex stdio backend 固定采用 Codex CLI app-server JSON-RPC over stdio。实现必须启动受控 `codex app-server --listen stdio://`,执行 `initialize``thread/start``thread/resume``turn/start`,并把 stdout/stderr、notification、tool lifecycle、assistant output 和 terminal/error 状态归一化为 AgentRun events。`codex``deepseek``minimax-m3` 是同一个 backend kind 下的 profile/config/SecretRef 选择;直接 Responses HTTP、OpenAI SDK wrapper、`codex exec` 一次性输出或文本 fallback 不能作为 `v0.1` Codex backend 的正式执行路径。
实现参考优先级:UniDesk Code Queue 的 `src/components/microservices/code-queue/src/code-agent/codex.ts``common.ts`,以及 HWLAB v0.2 的 `internal/cloud/codex-stdio-session.mjs``scripts/code-agent-chat-smoke.mjs``docs/reference/spec-v02-deepseek-proxy.md``docs/reference/code-agent-chat-readiness.md`。AgentRun 复用其协议、trace、redaction、Secret projection、profile overlay、DeepSeek/Moon Bridge 分层诊断和 failure 分类经验,但不复制 tenant 业务规则、环境专用路径、bridge host、namespace 或密钥材料。
## MVP 顺序
AgentRun 必须按纵向切片推进,不要一开始大规模并行开发。
### M0: 契约骨架
只定义最小资源模型和状态机:
- `Run`
- `Command`
- `Event`
- `Runner`
- `Backend`
第一切片只要求 `turn``interrupt``status` 和分页 `events`。不要一开始就做 UI、跨 backend kind 的自动路由、OA/Event/integrations 或自动调度。`v0.1` 可做同一 Codex stdio backend kind 下的显式 profile 选择;Queue 首版可以定义 task/attempt/retry/judge 的数据边界,但最终交互验收必须走真实 CLI。
### M1: 最小 Runner 加一个 Backend
第一份可执行证明不依赖 manager 或 scheduler。Runner 读取本地 run spec,调用一个 backend,并输出标准化 events。
验收标准:
- 一个 `turn` 能通过 backend 执行;
- assistant/output/error events 被归一化;
- terminal status 被写出;
- interrupt 至少有 durable cancellation 路径,backend 支持时再传播到真实进程中断。
第一个 backend 固定选择 Codex app-server stdio,用最窄实现证明真实 Agent 原语。如果 Codex 上游或凭据短暂不可用,可以用 controlled process 或 fake app-server 做自测试,但不能替代综合联调,也不能据此宣称 `v0.1` backend 通过。
### M2: Manager 加 Runner Claim
加入 `agentrun-mgr` 作为 durable fact store 和公共 API。Client 创建 runoperator 或 CLI 用 run id 人工启动 runnerrunner claim、poll commands、append events、heartbeat 并退出。
验收标准:
- run create/query 是 durable 的;
- runner claim 幂等,并拒绝双 owner
- events 是 append-only,并按 seq 分页;
- command ack state 可见;
- heartbeat expiration 可观察。
### M3: 手动 Dispatch CLI
增加 CLI,为指定 run 启动本地 runner process 或 Kubernetes Job。这是 manual dispatch,不是 manager 侧同步编排。Manager 仍拥有事实,runner 仍拥有执行。
验收标准:
- CLI 快速返回 JSON
- job/process identity 和 log path 可见;
- run status 可从 manager 轮询;
- runner 启动失败被报告为基础设施失败,不能静默写成任务成功。
### M4: 自动 Scheduler
只有 M1-M3 稳定后才加入 `agentrun-scheduler`。Scheduler 扫描 pending runs,应用 policy/capacity/backend selection,创建 runner Jobs,并处理 stale lease recovery。Scheduler 不直接执行 backend。
验收标准:
- pending run 自动变为 running
- scheduler restart 不影响已经运行的 runner
- stale lease recovery 留下显式 audit event
- scheduler rollout 不等同于 active run failure。
### M5: Queue 与 Tenant Canary 集成
核心生命周期证明后,再接入 UniDesk 和 HWLAB canary
- UniDesk Code Queue 新任务入口直接收敛到 AgentRun Queue,旧 Code Queue 只归档或只读。
- HWLAB 可以把一个窄范围 Code Agent canary 路由到 AgentRun。
- 每个 run 都必须显式带 tenant policy、workspace、secret scope 和 trace sink。
## RESTful MVP 契约
MVP 只使用短 RESTful HTTP/JSON 请求。长时间 Agent 工作用 durable command resource、run status 和分页 event polling 表示。不要让一个 HTTP 请求等待完整模型 turn。
Manager 公共 API
```http
POST /api/v1/runs
GET /api/v1/runs/:runId
GET /api/v1/runs/:runId/events?afterSeq=0&limit=100
POST /api/v1/runs/:runId/commands
GET /api/v1/runs/:runId/commands/:commandId
GET /api/v1/backends
```
Runner 到 manager 的私有 API
```http
POST /api/v1/runners/register
POST /api/v1/runs/:runId/claim
PATCH /api/v1/runs/:runId/lease
GET /api/v1/runs/:runId/commands?afterSeq=0&limit=20
POST /api/v1/runs/:runId/events
PATCH /api/v1/runs/:runId/status
POST /api/v1/commands/:commandId/ack
```
Runner inbound API 应保持本地/私有且最小:
```http
GET /health
GET /debug/status
```
不要依赖客户端调用短生命周期 runner Pod 地址。该方式在 Job、namespace、host-native backend 和重启场景下都会变脆。
## Command 状态
Command 是 durable resource。`turn``steer``interrupt``resume` 不能实现为 client 到 runner 的同步进程调用。
初始 command 状态机:
```text
accepted -> delivered -> confirmed
accepted -> delivered -> failed
accepted -> expired
```
所有 command 写入都应支持 idempotency key。相同 idempotency key 且 payload hash 相同的重复请求返回既有 command;相同 key 但 payload hash 不同必须显式失败。
## Event 模型
Event 是 append-only,并按 seq 分页:
- `seq` 在单个 run 内单调递增。
- `eventId``(runId, seq)` 支持幂等去重。
- `GET /events?afterSeq=N&limit=M` 是第一阶段观察 API。
- 后续 SSE 可以流式传输相同 event resource,但不能替代 REST polling contract。
最小 event 类别:
- `system`
- `assistant_message`
- `tool_call`
- `command_output`
- `diff`
- `error`
- `backend_status`
- `terminal_status`
## 数据模型方向
`v0.1` 使用 Postgres 作为唯一 durable storefile、sqlite、JSONL 或 Pod 本地目录只能用于临时测试或日志,不作为运行面事实来源。第一版实现可以使用紧凑 schema,但不应把所有事实都隐藏在一个 JSON blob 中。稳定方向是:
- `agentrun_schema_migrations`migration id、checksum 和 applied timestamp
- `agentrun_runs`run identity、tenant/project/workspace/backend policy、status 和 timestamps
- `agentrun_commands`command type、idempotency key、payload hash、state 和 ack timestamps
- `agentrun_events`:按 run 和 seq 索引的 append-only event records
- `agentrun_runners`registered runner identity、placement 和 heartbeat
- `agentrun_backends`backend profile、capabilities、capacity 和 health
- `agentrun_leases`:当前 ownership 和 expiry。
- `agentrun_queue_tasks``agentrun_queue_attempts``agentrun_task_summaries``agentrun_attempt_summaries``agentrun_queue_stats``agentrun_queue_read_cursors``agentrun_queue_judge_runs`Queue task、attempt、summary、stats、read cursor 和 judge durable facts;完整边界见 [spec-v01-queue.md](spec-v01-queue.md)。
Postgres DSN、provider credential 和未来 tenant credential 的分发边界见 [spec-v01-secret-distribution.md](spec-v01-secret-distribution.md)Codex 测试凭据通过 Kubernetes Secret projection 注入 `~/.codex/auth.json``~/.codex/config.toml`source、GitOps、event、trace、日志和 CLI 输出都不得保存 Secret 明文。
## 部署方向
AgentRun 从 `v0.1` 开始按版本 lane 滚动,废弃 `dev/prod` 管理口径。`v0.1` 的固定 source worktree 是 `G14:/root/agentrun-v01`,固定 source branch 是 `v0.1`,固定运行目标是 G14 原生 k3s namespace `agentrun-v01`。后续 `v0.2``v0.3` 必须拥有自己的 branch、source worktree、namespace、GitOps branch、runtime path 和发布验收。
Control-plane service 应是长驻服务;runner 应是短生命周期 Job 或受控 host-native process。Backend adapter 可以作为 pod 或 host-native service 运行,但必须通过 AgentRun 注册 capability 和 health,不能通过临时地址被 ad hoc 调用。
广泛 tenant 使用前,需要先设计 namespace isolation、RBAC、Secret scope、NetworkPolicy 和 ResourceQuota。独立 cluster 是后续成熟选项;第一版应优先在 `agentrun-v01` namespace 内证明服务,除非出现明确隔离 blocker。`agentrun_dev``agentrun_prod` 不再作为当前架构规格或验收目标。
## MVP 非目标
第一版 MVP 不包含:
- 全局替换 HWLAB Code Agent
- 跨 backend kind 的自动多 backend 路由;
- 最小诊断之外的 UI
- 自动扩缩容;
- 跨集群调度;
- SSE/WebSocket 流式输出;
- Event System、OA Event Flow、OA sink、GitHub sink、notification sink 或 integrations 表;
- 迁移旧 Code Queue 历史数据;
- 完整权限系统;
- production rollout 自动化。
第一目标是稳定跑通一条纵向 run 生命周期:create run、人工启动 runner、执行一个 backend turn、append events、观察 final status,并能发出可见的 interrupt/cancel command。