14 KiB
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.1allowlist 为codex、deepseek与minimax-m3;Queue 首版废弃旧 MiniMax/OpenCode 直连路线,只允许 Codex/Codex-compatible profile;executionPolicy,包含 sandbox、approval、timeout、network 和 secret scope;traceSink,说明标准化 event 镜像到哪里。
HWLAB 接入时必须显式分离业务 identity 和执行 identity:HWLAB 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 应构建为小型服务族:
agentrun-mgr
公共 RESTful API、durable facts、tenant/policy/idempotency 检查
agentrun-runner
短生命周期 per-run 或 per-attempt executor;claim 一个 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 + TypeScript:manager、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: 契约骨架
只定义最小资源模型和状态机:
RunCommandEventRunnerBackend
第一切片只要求 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 创建 run;operator 或 CLI 用 run id 人工启动 runner;runner 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:
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:
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 应保持本地/私有且最小:
GET /health
GET /debug/status
不要依赖客户端调用短生命周期 runner Pod 地址。该方式在 Job、namespace、host-native backend 和重启场景下都会变脆。
Command 状态
Command 是 durable resource。turn、steer、interrupt 和 resume 不能实现为 client 到 runner 的同步进程调用。
初始 command 状态机:
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 类别:
systemassistant_messagetool_callcommand_outputdifferrorbackend_statusterminal_status
数据模型方向
v0.1 使用 Postgres 作为唯一 durable store;file、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。
Postgres DSN、provider credential 和未来 tenant credential 的分发边界见 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。