# 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 和执行 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 应构建为小型服务族: ```text 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: 契约骨架 只定义最小资源模型和状态机: - `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 创建 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: ```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 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](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。