Files
pikasTech-agentrun/docs/reference/spec-v01-agentrun-runner.md
T
2026-05-29 20:52:22 +08:00

119 lines
8.9 KiB
Markdown
Raw 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.
# v0.1 agentrun-runner 服务规格
`agentrun-runner` 是 AgentRun `v0.1` 的短生命周期执行入口。它以 per-run 或 per-attempt 方式运行,必须从 `agentrun-mgr` claim run,调用一个 backend adapter,并把 events、heartbeat、command ack 和 terminal status 写回 manager。
## 在系统中的职责划分
- 作为 Kubernetes Job 或受控 host process 启动;不作为普通业务客户端直接调用的长驻公共服务。
- 从 manager register、claim run、续租 lease、poll commands、ack command、append events、patch status。
- 根据 run 中的 `backendProfile``executionPolicy.secretScope` 调用 backend adapter。
- 根据 manager 解析出的 RuntimeAssembly materialize backend image、profile Secret、session 和初始资源;四要素字段权威见 [spec-v01-runtime-assembly.md](spec-v01-runtime-assembly.md),本文只规定 runner 消费边界。
- 将 backend stdout/stderr、assistant message、tool call、error 和 terminal status 归一化为 manager event。
- 提供可定位的 job/process identity、logPath、attempt id 和 failureKind。
- 不直连 Postgres,不扩大 workspace、network、approval 或 secret scope。
## 内部架构
`v0.1` 默认 runner 形态是 `agentrun-v01` namespace 中的短生命周期 Job,Job 名称建议使用 `agentrun-v01-runner-<runId>-<attempt>`。MVP 允许 CLI 启动受控本地 process,但该 process 仍必须通过 manager API claim/report。
Runner 自研代码优先使用 Bun + TypeScript。Kubernetes Job 和 CLI 启动的 host process 必须进入同一套 TS runner 模块,避免一套 Job 逻辑和一套本地调试逻辑分叉;容器镜像可以直接运行 TS 入口或运行由同一源码构建出的 JS artifact。
Runner 启动参数必须显式包含:
- manager API base URL。
- runId 和 attemptId。
- backendProfile。
- logPath 或 Kubernetes job/pod identity。
- source commit/build metadata。
Runner Secret 只能通过 Kubernetes Secret projection、ServiceAccount/RBAC 或受控 Secret API 读取获得。Codex 测试凭据投影规则见 [spec-v01-secret-distribution.md](spec-v01-secret-distribution.md) 和 [spec-v01-backend-codex.md](spec-v01-backend-codex.md)。
Kubernetes Job runner 必须把 credential source 与 runtime home 分开:Secret volume 只读挂在 `/var/run/agentrun/secrets/...``/home/agentrun``emptyDir` 提供可写空间,`CODEX_HOME` 指向当前 run/profile 的 writable runtime home`AGENTRUN_CODEX_SECRET_HOME` 指向当前 `backendProfile` 对应的只读 projection。runner/backend 在启动 provider 前只复制授权文件,不打印内容。`codex``deepseek` profile 不得共享同一个可写 runtime home,除非它们运行在不同的 per-run Kubernetes Job 且该目录由 Job 独占 emptyDir 提供。
RuntimeAssembly P0 中 `SessionRef` 可以显式为 `null`runner 不得把完整 `CODEX_HOME`、Secret projection 或节点 host path 当作 session store。`ResourceBundleRef` P0 收敛为 Git-onlyrunner 后续实现资源 materialization 时只能 checkout 到允许 workspace 前缀,并记录 commit/tree 摘要,不能把用户上传文件或 env dump 混入 Git-only bundle。
Kubernetes Job runner 必须设置有限保留时间。`v0.1` 默认 `ttlSecondsAfterFinished=86400`,用于保留最近完成 Job 的调试窗口,同时避免长期堆积 `Completed` runner Job 污染运行面观察。该 TTL 是 Job manifest 的运行面属性,不是 CI/CD 门禁;需要延长保留时间时必须通过受控 Job render/input 显式覆盖,并在 issue 或 PR 中说明原因。
## Runner 生命周期
标准状态方向:
```text
starting -> registered -> claimed -> running -> terminal
starting -> registered -> claim_failed
claimed -> running -> backend_failed
claimed -> running -> cancelled
claimed -> lease_lost
```
规则:
- runner 必须先 register,再 claim runclaim 失败不能继续调用 backend。
- lease heartbeat 必须可观察;过期或冲突时写入 failure event 或明确退出原因。
- command 只能从 manager poll;不得从本地文件或临时参数伪造正式 command。
- backend 产生的所有可见输出必须先经过 adapter normalization 和 redaction,再 append 到 managerbackend_status 至少包含 redacted profile/backendKind/protocol 摘要。
- terminal status 上报后 runner 可以退出;退出码与 terminal status 必须一致或在日志中可解释。
## Manager API 交互
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 HTTP 不是业务 API。若实现本地诊断端点,只允许 `GET /health``GET /debug/status`,并且只能暴露在本地或 pod 内部调试面。
## Failure 与 Redaction
Runner 必须把以下失败归类为结构化 failureKind
- `secret-unavailable`SecretRef 缺失、RBAC 拒绝或 Secret projection 不完整。
- `provider-auth-failed`:上游 provider 鉴权失败。
- `provider-unavailable`:上游 provider 返回 HTTP 5xx/503、`Service Unavailable`、携带 5xx 的 `responseStreamDisconnected` 或明确 temporary/provider unavailable 文案;这是外部 provider availability blocker,不得归为本地 `backend-failed`
- `backend-failed`:backend 进程退出、协议错误或返回 terminal error。
- `runner-lease-conflict`claim/lease 被其他 runner 持有。
- `infra-failed`Job 启动、网络、manager API 或文件系统基础设施失败。
- `cancelled`:收到 interrupt/cancel 且已停止执行。
Runner 日志必须实时 flush 到文件或 pod logCLI 启动 runner 时必须返回 logPath 或 job/pod identity。日志、event、trace 和 CLI 输出不得出现 provider credential、`auth.json``config.toml` 内容、DSN password、token 或 URL credential。
## 测试规格
### T1 Runner 启动可见性
阅读 `AGENTS.md`、本文和 [spec-v01-cli.md](spec-v01-cli.md),然后用正式 AgentRun CLI 为一个真实 run 启动 runner。确认 CLI 立即返回 JSON,包含 runId、attemptId、job/process identity、logPath 和后续 poll command;不得等待完整模型 turn。
### T2 Claim 与 lease 冲突
阅读本文和 [spec-v01-agentrun-mgr.md](spec-v01-agentrun-mgr.md),然后对同一个 run 启动两个 runner。确认只有一个 runner claim 成功,失败方输出结构化 failureKind,并且 manager events 中能看到冲突或拒绝原因。
### T3 Backend event round-trip
阅读本文和 [spec-v01-backend-adapter.md](spec-v01-backend-adapter.md),然后用真实 backend 执行一个最短 turn。确认 runner append assistant/output/error/backend_status/terminal_status 中的必要 eventsevent seq 单调,terminal status 可通过 manager 查询。
### T4 Missing Secret failure
阅读本文和 [spec-v01-secret-distribution.md](spec-v01-secret-distribution.md),然后分别用缺失 `codex` SecretRef 与缺失 `deepseek` SecretRef 的 run 启动 runner。确认 runner 不调用 providerrun 失败为 `secret-unavailable` 或等价 failureKind,不 fallback 到另一个 profile,日志和事件不泄露 Secret 值。
### T5 Profile switching
阅读本文和 [spec-v01-backend-codex.md](spec-v01-backend-codex.md),然后按 `codex -> deepseek -> codex` 顺序启动三个真实 runner Job。确认每个 Job 只挂载和复制当前 profile 的 SecretRef`CODEX_HOME` 互相隔离,且前后两个 `codex` run 不受 `deepseek` run 的 config/model/upstream 影响。
## 规格的实现情况
| 规格项 | 状态 | 说明 |
| --- | --- | --- |
| `agentrun-runner` 服务规格 | 已定义 | 本文为 v0.1 runner 权威。 |
| Kubernetes Job runner | 已实现/已通过主闭环 | `runner job` 通过 manager REST 创建 Kubernetes Job,固定使用 `agentrun-v01-runner` ServiceAccount、manager URL、runId/commandId/attemptId、executionPolicy、SecretRef 文件投影、writable Codex runtime home 和有限 TTL;真实 `agentrun-v01` runner Job 已完成 Codex turn。 |
| host process runner | 已实现 | `runner start``src/runner/main.ts` 进入同一套 `runOnce`,可通过 manager register/claim/poll/report 执行自测试。 |
| claim/lease/report client | 已实现 | 已拆出 runner manager API client,覆盖 register、claim、lease heartbeat、poll command、ack、append event 和 terminal statuslive runtime 通过 manager 写入 Postgres durable store。 |
| runner redaction | 已实现主路径 | runner/backend event 和 Job 输出使用 redaction;复杂审计仍按 [spec-v01-validation.md](spec-v01-validation.md) 的人工验收抽查。 |
| `deepseek` profile runner selection | 已实现/已通过主闭环 | Runner Job 和 host runner 已按 run `backendProfile` 选择 matching SecretRef、projection、`CODEX_HOME` 和 backend metadata;真实 Kubernetes Job 已完成 `codex -> deepseek -> codex` 切换联调。 |