Files
pikasTech-agentrun/docs/reference/spec-v01-runtime-assembly.md
T
2026-06-11 02:18:41 +08:00

33 KiB
Raw Blame History

v0.1 装配 SPECRuntimeAssembly

本文是 AgentRun v0.1 runner/backend 启动前的权威装配 SPEC。所有会进入运行时容器、进程、文件系统或环境变量的执行输入,都必须先落到本文定义的装配模型,再由 manager/runner 渲染为受控 Job 输入;不得在 CLI、Queue、runner Job、issue 过程或临时热补丁中绕过装配模型直接拼接 credential、host path 或隐式环境。

RuntimeAssembly 只回答一个问题:一次 run 到底用哪份 backend/env 镜像、哪个 profile/credential scope、哪份 session、哪份代码、初始 prompt、skill 和工具 credential。BackendImageRefProfileRefSessionRefResourceBundleRef 仍是四个一等运行时要素;credential 注入不是第五个杂项要素,而是挂在 ProfileRefResourceBundleRef 或 tool scope 上的 SecretRef 装配引用。初始 prompt 与 skill 注入也不是第五条运行时路径,它们属于 ResourceBundleRef 指向的 Git-only 非敏感内容。

最简四要素

v0.1 只保留四个一等要素:

要素 最小字段 v0.1 含义 不包含
BackendImageRef source 或已解析 image Aipod env image Dockerfile source 与最终 digest-pinned backend/runner 镜像。 API KEY、profile config、用户代码、session 文件、可变 image tag。
ProfileRef profilesecretRef provider profile 和 API KEY/配置 SecretRef。 backend 镜像、session、repo 文件、GitHub/业务工具 credential。
SessionRef sessionIdnull backend 会话文件持久化引用;P0 可以为 null API KEY、完整 CODEX_HOME、Git workspace。
ResourceBundleRef kind="gitbundle"repoUrlbundles[]、可选 ref / commitId / promptRefs / requiredSkills 初始代码/文件输入、工具目录、skill 目录、required skill 校验和稳定初始 promptP0 固定 Git-only gitbundle,默认从 repo/ref 解析实际 commit。 上传文件、对象存储 artifact、inline env、Secret value、会话历史、旧 inline seed、inline skill manifest。

P0 最小 JSON 形态:

{
  "backendImageRef": {
    "source": {
      "kind": "env-image-dockerfile",
      "repoUrl": "git@github.com:pikasTech/agentrun.git",
      "commitId": "0000000000000000000000000000000000000000",
      "dockerfilePath": "deploy/container/Containerfile"
    },
    "image": "127.0.0.1:5000/agentrun/agentrun-mgr-env@sha256:..."
  },
  "profileRef": {
    "profile": "codex",
    "secretRef": { "name": "agentrun-v01-provider-codex", "keys": ["auth.json", "config.toml"] }
  },
  "sessionRef": null,
  "resourceBundleRef": {
    "kind": "gitbundle",
    "repoUrl": "git@github.com:pikasTech/unidesk.git",
    "bundles": [
      { "name": "tools", "subpath": "tools", "target_path": "tools" },
      { "name": "skills", "subpath": "skills", "target_path": ".agents/skills" }
    ],
    "promptRefs": [],
    "requiredSkills": [{ "name": "dad-dev" }]
  }
}

executionPolicyobservabilityPolicy、tenant identity、network、GC、failureKind、provenance、resource limit、tool credential scope、初始 prompt 装配和 skill 装配都不是新的运行时要素;它们分别挂在四要素或 run policy 上,并且必须能追溯到 SecretRef、Git repo/ref、实际 materialized commit、path/hash、配置引用或显式 null/deferred 状态。

装配对象与 credential 归属

任何 credential 注入都必须先归类,再进入对应装配路径:

credential 类别 装配归属 运行时投影 规则
Provider credential ProfileRef / executionPolicy.secretScope.providerCredentials[] profile-scoped 只读 Secret projection,再复制到 per-run writable CODEX_HOME 只服务 codex/deepseek/minimax-m3/dsflash-go backend profiledsflash-go 额外包含 model-catalog.json;缺失为 secret-unavailable,不得 fallback。
Git resource credential ResourceBundleRef.credentialRef 只服务 resource materialization 的 Git fetch/checkout 只能用于拉取 ResourceBundleRef.repoUrl 对应代码,不得暴露给 agent shell 作为通用 GitHub token。
Tool credential executionPolicy.secretScope.toolCredentials[] 由 runner 按 tool scope 投影为文件或 env,并只暴露给当前 run/command 允许的工具 用于 GitHub PR、issue、UniDesk SSH passthrough、artifact registry 等 agent shell 工具能力;不等同于 AgentRun integration,不触发 GitHub sink/OA/Event 之类外部动作记录。
Short-lived execution context runner-job transientEnv 单次 Job envresponse/dry-run/event 只显示 name/hash 只用于业务 dispatcher 生成的短期或 owner-scoped runtime context,以及 manager 受控默认值补齐的非敏感服务地址;不得承载 provider credential、GitHub token、UniDesk SSH client token 或长期 SSH key。

toolCredentials 是装配 SPEC 中的受控扩展槽位,用于把 agent 运行时需要的外部工具授权从“临时 env”收敛为 SecretRef。v0.1 支持 env projection 与只读 volume projectionenv 用于 GH_TOKENUNIDESK_SSH_CLIENT_TOKEN 这类单 key 工具变量,volume 用于 GitHub SSH 目录等文件型凭据。例如:

{
  "toolCredentials": [
    {
      "tool": "github",
      "purpose": "pull-request",
      "secretRef": {
        "namespace": "agentrun-v01",
        "name": "agentrun-v01-tool-github-pr",
        "keys": ["GH_TOKEN"]
      },
      "projection": { "kind": "env", "envName": "GH_TOKEN" }
    },
    {
      "tool": "unidesk-ssh",
      "purpose": "ssh-passthrough",
      "secretRef": {
        "namespace": "agentrun-v01",
        "name": "agentrun-v01-tool-unidesk-ssh",
        "keys": ["UNIDESK_SSH_CLIENT_TOKEN"]
      },
      "projection": { "kind": "env", "envName": "UNIDESK_SSH_CLIENT_TOKEN" }
    },
    {
      "tool": "github",
      "purpose": "github-ssh",
      "secretRef": {
        "namespace": "agentrun-v01",
        "name": "agentrun-v01-tool-github-ssh",
        "keys": ["id_ed25519", "known_hosts", "config"]
      },
      "projection": { "kind": "volume", "mountPath": "/home/agentrun/.ssh" }
    }
  ]
}

规则:

  • toolCredentials 只能保存 SecretRef、tool、purpose、projection intent 和 redacted metadata,不保存 Secret value。
  • manager 只校验引用形态和 tenant/policy 边界,不读取 Secret value 后存库。
  • runner 渲染 Job 时只能按当前 run 的 secretScope 投影被授权的 tool credential;不能枚举 namespace 内所有 Secret。
  • dry-run manifest、runner job record、event、trace、日志和 CLI 输出只能显示 tool、purpose、SecretRef 名称/key、projection kind 和 valuesPrinted=false
  • GitHub PR 能力属于 agent shell/tool 运行能力,不是 AgentRun Queue integration,也不要求新增 GitHub sink、OA sink、notification 或 Event Flow。
  • tool=unidesk-ssh 只允许投影 Secret key UNIDESK_SSH_CLIENT_TOKEN 到同名 env。该 token 是 UniDesk frontend /ws/ssh 的 scoped client tokenroute allowlist 由 UniDesk frontend 配置约束;它不得携带 provider token、主 server SSH key 或完整 frontend 登录态。
  • projection.kind="volume" 只能挂载到 /home/agentrun/ 下的路径,不能包含 ..runner Job 必须用只读 Secret volume mount,不得把文件型凭据复制进 event、logs 或 Queue task。
  • GitHub SSH 能力应使用文件型 SecretRef,例如 id_ed25519known_hostsconfig 投影到 /home/agentrun/.ssh;它仍只属于当前 run/command 的工具能力,不是 manager 自身 GitHub 写入权限。
  • tool=unidesk-ssh 所需的 UniDesk endpoint 不属于 SecretRef。runner-job env 必须具备 UNIDESK_MAIN_SERVER_IPUNIDESK_MAIN_SERVER_HOSTUNIDESK_FRONTEND_URL 三者之一;调用方可以通过 transientEnv 显式传入,若未传入,manager 可以从受控默认配置自动补齐非敏感 endpoint env。
  • manager 自动补齐 endpoint 时只追加 env name/value 到本次 runner Job,不把 value 写入 run、command、event 或 result 明文;trace/response 只能显示 env name、count、hash 和 valuesPrinted=false。若 run 请求了 tool=unidesk-ssh,但调用方和 manager 默认都没有 endpointrunner-job 创建必须在装配阶段返回结构化 schema-invalid,不能让 agent 进入 turn 后靠 prompt 猜 endpoint。
  • 发现 agent shell 缺少 ghcurl、UniDesk SSH passthrough token 或其他工具凭证时,只能记录为装配能力缺口;不得用 transientEnv 或 issue 评论里的明文 token 绕过。

HWLAB v0.2 承接口径

HWLAB v0.2 原有 Code Agent 已经验证了 profile、session、workspace 和 Secret 的基本边界。RuntimeAssembly 需要把这些边界固化为 AgentRun 自身四要素,避免 runner 继续依赖 HWLAB cloud-api Pod 内路径或本地进程状态。

HWLAB v0.2 基线能力 HWLAB 参考入口 RuntimeAssembly 承接字段 承接规则
provider profile 可切换 internal/cloud/code-agent-contract.ts ProfileRef.profileProfileRef.secretRef deepseekminimax-m3dsflash-gocodex 只选择 profile/config/SecretRef/model catalog,不复制 backend 协议;缺失 Secret 必须失败,不 fallback。
Codex app-server thread 复用 internal/cloud/codex-stdio-session.tsinternal/cloud/code-agent-session-registry.ts SessionRef.sessionIdconversationIdthreadId AgentRun 保存 backend thread/session 摘要;不保存 API KEY、auth.jsonconfig.toml 或完整 CODEX_HOME
固定 /workspace/hwlab 代码上下文 internal/cloud/code-agent-contract.ts ResourceBundleRef.repoUrlref / workspaceRef.branch、materialized commitId 用 Git-only repo/ref checkout 取代 HWLAB Pod 内固定路径;runner checkout 到隔离 workspace,并在 event/result 记录实际 commit。
writable CODEX_HOME 与 Secret 投影分离 docs/reference/code-agent-chat-readiness.md ProfileRef + runner runtime home Secret 只读投影,复制到当前 run/profile writable runtime homeprofile 间不共享。
runner/image 可追溯 HWLAB live build/source metadata BackendImageRef.image runner/backend image 必须可追溯 digest/source commit,不能由调用方任意传未受控镜像。

HWLAB Workbench 的 project/workspace 不属于 RuntimeAssembly 四要素,也不是 AgentRun projectId。这些业务字段只能作为 metadata 或 workspaceRef 的 HWLAB 子字段进入 runAgentRun policy 字段仍以 tenantId / projectId / providerId / backendProfile 为准。HWLAB providerProfile 在 RuntimeAssembly 中只映射为 ProfileRef.profile 和 run backendProfile,并应由显式 HWLAB session 继承,不能从 stale workspace fallback 覆盖。

四要素边界

BackendImageRef

  • BackendImageRef.source 是 env image Dockerfile source,来自 AipodSpec spec.imageRef 或受控 runtime defaultkind 固定为 env-image-dockerfile,最小字段为 repoUrl、完整 commitId 和仓库内相对 dockerfilePath
  • #146 的 Aipod 装配决策要求 source 先写入 AipodSpec,再进入 Queue dispatch / Session turn / runner Job 解析;不得由 prompt、payload、临时 CLI 参数、可变 image tag 或 dispatcher 当前 rollout commit 隐式决定 runner 镜像。
  • BackendImageRef.image 是 source 解析后的 digest-pinned image,必须来自 CI/CD artifact catalog、GitOps manifest 或 manager allowlist;客户端不能在 run payload 中传任意可变镜像。
  • runner Job 创建前必须先用 source 解析 env image identity,并优先从 artifact catalog / registry 复用已有 digest;未命中只能返回明确 build-required 或进入受控 CI/CD,不能在普通任务容器内现装依赖。
  • v0.1 可以继续使用现有 agentrun runner 镜像,不要求立即拆独立 backend image。
  • 验收时必须能追溯实际 Deployment/Job image digest、source commit、Dockerfile path、env identity 和 reuse/build 状态。
  • runner 镜像必须是 work-ready 执行环境:基础 CLI、Bun/Node/npm、Git/SSH/GitHub CLI、kubectl、curl、ripgrep 和 AgentRun 生产依赖必须在 env image 构建阶段进入镜像或受控预装层。普通任务不得在运行时用 aptapkbun installnpm install 或等价命令补装基础环境。
  • workReady capability 摘要必须出现在 manager health、runner job dry-run/response、queue dispatch response 和 runner startup event 中;摘要只能包含版本、工具名、版本号、依赖策略和 valuesPrinted=false,不得输出 env value、token 或 Secret 文件内容。
  • runner 启动后必须先执行短 smoke:镜像层检查 bunnodenpmgitsshghrgcurlkubectlArtificer/UniDesk 工具型 gitbundle 装配后再检查 trantransapply_patch。缺失时必须快速 infra-failed,不能把问题留给 prompt 内排查。
  • 项目依赖不属于默认 runtime preflight。AgentRun 自身 node_modules 固定为镜像层 /opt/agentrun/node_modulesboot 后只 symlink 到源码 checkout;业务 repo 的 bun install/npm install 只能由显式任务、派生镜像或受控 workspace cache 承担,不能成为每个 Aipod/Queue task 的默认前置。

ProfileRef

  • profile 在 v0.1 只允许 codexdeepseekminimax-m3dsflash-go
  • secretRef 只保存 Secret 名称和 key,不保存值。
  • 当前 profile 只能读取当前 profile 的 SecretRef;缺失必须 secret-unavailable,不能 fallback 到另一个 profile。
  • dsflash-gosecretRef.keys 必须包含 auth.jsonconfig.tomlmodel-catalog.jsonlegacy 调用方漏传 model-catalog.json 时由 manager/runner 按 profile capability 归一补齐 projection,但不能降低运行时 readiness 校验。
  • profile Secret 只读投影,backend 需要可写目录时复制到 per-run/profile runtime home。

SessionRef

  • P0 允许 sessionRef=null,表示不持久化 backend session 文件。
  • 面向 HWLAB v0.2 原有长会话能力,SessionRef 是承接 Code Agent thread 复用的核心字段:需要支持 conversationId/sessionId/threadId 到 backend session identity 的稳定映射。
  • thread 复用只认标准 threadId:单个 command 显式提供 payload.threadId 时优先使用,否则使用 SessionRef.threadId。协议字段、events、result 和 session record 都以该字段为唯一 thread identity;缺失标准 threadId 就按新 thread 启动并在 result/sessionRef 中回写标准字段。
  • 一旦启用 session,必须只保存 backend session/cache,不保存 API KEY、auth.jsonconfig.toml 或完整 CODEX_HOME
  • session 文件目录必须和 profile credential、Git workspace 分开。
  • runner 启动时,有 SessionRef 则执行 thread/resume,没有 SessionRef 则执行 thread/start;profile 切换不得复用另一 profile 的 session。
  • v0.1 先定义边界;持久 session store、TTL、GC 和 resume 验收按 spec-v01-hwlab-manual-dispatch.md 分阶段推进。

v0.1.1 SessionRef 持久化(per-session RWO PVC 直接挂载)

v0.1 的 P0 把 SessionRef 收敛为「只持久化 sessionId/threadId/metadata」。v0.1.1 必须把 SessionRef 升级为真正持久化,让 codex app-server thread / resume 跨 runner pod 重建继续成功,且「PVC 不删就随时 resume」是硬验收。

边界:

  • 每个 session 绑定一个 RWO PVCagentrun-v01-session-<sessionId>,固定 namespace agentrun-v01、StorageClass 走 AGENTRUN_SESSION_STORAGE_CLASS(默认 local-path)、默认容量 1Gi。
  • runner Job 必须在 ${CODEX_HOME}/<codex_rollout_subdir> 位置把 PVC 直接挂载到 runner podauth.jsonconfig.tomlstate_*.sqlitememories/tmp/skills/ 仍由 emptyDir 父目录提供,不持久化。
  • 完整 CODEX_HOME 不进入 PVCprofile Secret 投影仍走 agentrun-v01-runner-secret-reader,与 session 持久化路径分离。
  • runner 启动时把 PVC 名、namespace、mount path、codex rollout subdir 写入 envAGENTRUN_SESSION_PVC_NAMEAGENTRUN_SESSION_PVC_NAMESPACEAGENTRUN_SESSION_PVC_MOUNT_PATHAGENTRUN_CODEX_ROLLOUT_SUBDIR),backend adapter 不需要直接读 k8s API。
  • codex_rollout_subdir 走 env,默认 sessions,codex CLI 升级改子目录时只改该 env,不改 runner/backend 装配。
  • POST /api/v1/sessions 创建 session 时同步创建 PVCPOST /api/v1/runs/:runId/commands 命中已有 session 且 storage_kind='evicted' 时短路返回 session-store-evicted,不创建 runner Job。
  • runner pod 删除或旧 lease 过期后的 replacement runner 只改变执行尝试 identity,不改变 RuntimeAssembly 的 SessionRefProfileRefResourceBundleRef。验收时应证明 replacement run/job 仍使用同一 SessionRef.sessionIdthreadIdProfileRef.profile 和 PVC;不能通过新 session、新 profile 或历史 prompt 拼接来制造 resume 表象。
  • GC 循环(默认 5min,可调 AGENTRUN_SESSION_GC_INTERVAL_MS)扫到 expires_at 过 + 无 active run 的 session 删 PVC。
  • runner Job 启动后把 PVC 摘要(pvcName/pvcPhase/storage_size_bytes/storage_files_count/storage_sha256/storage_updated_at)通过 POST /api/v1/sessions/:id/storage/refresh 写回 managermanager 不读 PVC 内容,只读摘要。

禁止路径:

  • 不引入「runner 启动后 copy/restore」path,撤掉的 copy 方案不允许复活(PR #78 已回退 replacement 逻辑,本节同样禁止任何「持久化卷 + 热修脚手架」变体)。
  • 不允许 fake thread/resume:completed,PVC 真的存在且 codex 真的能 resume 才算通过。
  • 不写 fallback、不写 replacement、不拼接历史。thread/resume 失败时按 spec-v01-backend-codex.md T7 直接失败;只有 AGENTRUN_SESSION_PVC_NAME 已设 + codex 报 no rollout found for thread id 时升级为 session-store-evicted,用于上层区分「PVC 被删」与「真协议错误」。

ResourceBundleRef

  • P0 固定 kind="gitbundle",输入只依赖 Git repo/ref 与 bundles[]runner 从 resourceBundleRef.ref、run 的 workspaceRef.branchHEAD 解析实际 commit,再用该 materialized commit 作为内容身份。
  • commitId 是可选 pin 或历史请求 hint;提供时必须是 full commit sha,但 HWLAB gitbundle 默认不得依赖 cloud-api/CI/CD rollout 注入的 commitId。
  • bundles[] 每一项只允许 { name?, repoUrl?, ref?, commitId?, subpath, target_path };缺省 repo/ref/commit 继承顶层解析结果。
  • gitMirror 可把 GitHub repo URL 改写到受控 mirror read URLevent/result 必须同时记录原始 repoUrl、实际 fetchRepoUrlmirrorUsedmirrorBaseUrl,不能只显示理论 repo。
  • subpath 必须留在 checkout 内,target_path 必须留在 runner workspace 内;runner 按 subpath -> target_path 复制文件或目录。
  • credentialRef 只用于拉取私有 Git repo,不等同于 backend API KEY。
  • 不支持上传文件、对象存储 artifact、任意 ConfigMap 文件袋、inline seed 或旧字段;旧 toolAliasesskillRefsworkspaceFilessubdirsparsePaths 输入必须直接 schema-invalid。
  • requiredSkills[] 只接受 { "name": "<skill-name>" } 这类声明式元数据;runner 只能在 gitbundle 已复制的 .agents/skills/<name>/SKILL.md 中校验,不接受正文、host path、SecretRef、旧 skillRefs 或模型默认 skill fallback。
  • 面向 HWLAB 手动调度 canary,默认 bundle 把 repo 的 tools/ 复制到 workspace tools/,把 skills/ 复制到 workspace .agents/skills/event/result 必须记录 repo、requested ref/commit、实际 materialized commit、checkout tree、bundle 列表、workspace 摘要、tools、skillDirs 和 requiredSkills 摘要。

tools 目录

runner 对 workspace tools/ 做统一装配:顶层带 shebang 的脚本会被 chmod +xtools/ 会暴露到 PATH。如果 runtime 配置了单独的 AGENTRUN_RESOURCE_BIN_PATH,runner 只能在该目录写入执行原始 workspace tool 的 shim,不能复制 tool 文件导致 dirname "$0"、相对 import 或辅助源码解析到 bin 目录。非 shebang 文件是随 bundle 复制的源码、测试或辅助文件,不作为可执行工具发现,也不触发 schema-invalid。短命令名称来自 repo 内真实文件,例如 tools/hwpodrepo tool 本身承担业务 wrapper 语义。

AgentRun 自身仓库必须提供 tools/trantools/transtools/apply_patch,用于承接 UniDesk frontend /ws/ssh 的 scoped client-token 透传。runner 只通过 executionPolicy.secretScope.toolCredentials[] 投影 UNIDESK_SSH_CLIENT_TOKEN,并通过调用方 transientEnv 或 manager 受控默认值注入非敏感 UNIDESK_MAIN_SERVER_IPUNIDESK_MAIN_SERVER_HOSTUNIDESK_FRONTEND_URL;工具不得读取 provider token、主 server SSH key 或完整 frontend 登录态。tran --help 必须输出 JSON,并列出当前支持的最小开发面:host/host workspace scriptargv、普通 ssh-like 命令、host workspace apply-patchk3s kubectlk3s script、k3s workload argv/script 和 k3s workload apply-patch。runner 侧 apply-patch 只把 stdin patch 和相邻 tools/apply_patch helper 传到目标 route 执行,不接触或回显 Secret 值;uploaddownload 和 Windows route 未实现时必须显式 unsupported-operation,不能静默改走不受控 shell 拼接或 token fallback。

promptRefs

promptRefs 用于按同一个 materialized gitbundle checkout 的 path 装配初始 prompt。它承载业务域稳定 runtime/developer instruction,例如某个项目的标准入口、禁止路径和工具使用纪律;它不承载用户本轮 message,也不承载历史会话。

最小形态:

{
  "name": "hwlab-v02-runtime",
  "path": "internal/agent/prompts/hwlab-v02-runtime.md",
  "inject": "thread-start",
  "required": true
}

规则:

  • path 只能是 bundle 内相对路径,不能是绝对路径,不能包含 ..
  • inject 的 v0.1 默认和唯一正式语义是 thread-start:只有没有既有 threadId、runner 执行 thread/start 的第一条 turn 会注入;已有 SessionRef.threadId 或 command payload.threadId 并执行 thread/resume 时不得再次注入。
  • 多个 promptRefs 按数组顺序拼装;单个 prompt 和总 assembled prompt 必须有大小上限,超限返回 prompt-unavailableprompt-too-large,不能静默截断成新语义。
  • prompt 文件内容进入 Codex turn input,但 event/result 只输出 namepathsha256bytesinjectrequiredinjected=true/false,不得默认输出全文。
  • promptRefs 不得读取 Secret、env、token、profile config 或 session 文件;需要 credential 的内容必须通过 ProfileReftoolCredentialstransientEnv 的正式路径装配。
  • promptRefs 缺失且 required=true 时,run/command 必须 blocked;不得 fallback 到用户 prompt、旧硬编码 prompt、模型默认 system prompt 或历史上下文拼接。

skill 目录

skill 只来自 gitbundle 复制进 workspace 的 .agents/skills/<name>/SKILL.md。runner 发现直接子目录中的 SKILL.md 后,把 .agents/skills 暴露给 backend,并在 initial prompt 中加入有界 skill facts。多文件 skill 的 references/scripts/ 和后续新增文件跟随目录一起复制;event/result 只输出 skill name、manifest path 摘要、hash、bytes、summary 和来源 bundle 摘要,不输出大段 manifest 正文。

若调用方声明 requiredSkills[]runner 必须在 backend 启动前逐项校验 .agents/skills/<name>/SKILL.md 已由 gitbundle 物化。缺失时 run/command blockedfailureKind 为 required-skill-unavailableblocker details 至少包含 required、missing 和 available 摘要;不得读取镜像默认 skill、host path、ConfigMap、用户长 prompt 或旧 skillRefs 作为替代。

初始 prompt 与 session 边界

初始 prompt 装配只发生在新 thread 的首轮 turn。后续 turn 的历史上下文必须由 Codex stdio 原生 thread/resume 恢复;AgentRun 不得为了补 prompt、补 skill facts 或修复 stale thread 而拼接旧用户消息、旧 assistant 回复、旧 skill 列表或旧业务事实。thread/resume 失败时按 spec-v01-backend-codex.md 直接失败,不启动替代 thread/start

最简装配顺序

  1. Manager 根据 run 解析四要素引用。
  2. Manager 根据 executionPolicy.secretScope 解析 provider/tool SecretRef 和 resource credential 引用;只保存引用,不读取值。
  3. Manager 或 runner Job render 只使用解析后的 image、SecretRef、sessionRef、Git commit 和 projection intent。
  4. Runner materialize profile Secret 到 writable runtime home。
  5. Runner materialize tool credential 到该 run 允许的 env/file projection;未实现的 tool scope 必须显式 failed/blocked,不能静默跳过后让 agent 自己猜凭据。
  6. Runner materialize kind="gitbundle" resource bundle 到 workspaceP0 未实现时必须显式 blocked,不能猜测 host path。
  7. Runner 按 bundles[] 复制目录或文件,准备 workspace tools/、发现 .agents/skills,校验 requiredSkills,读取并校验 promptRefs,写入有界 assembly event。
  8. Runner 启动 backend,并在 event 中记录 imageRef source、env identity、image digest、reuse/build 状态、profile、SecretRef 名称/key、tool credential scope、sessionRef、repoUrl、requested ref/commit、materialized commit、bundles、promptRefs、requiredSkills、tools 和 skillDirs 摘要。

任何一个要素缺失或不合法,都必须按该要素失败;不得静默 fallback。

v0.1 验收标准

A1 BackendImageRef 验收

  • 实际 manager Deployment 和 runner Job 使用 digest-pinned image。
  • event、CLI 或诊断输出能看到 imageRef source、env identity、image digest 和可追溯 GitOps/catalog 条目。
  • run payload 不能传任意 image 字符串;Aipod 只能声明 env image Dockerfile sourcedispatch 解析后才进入 runner job image。
  • 启动 Aipod 时命中已有 env identity 必须 reuse digest-pinned image;不得触发任务内 apt/apk/bun install/npm install

A2 ProfileRef 验收

  • codex run 只挂载 agentrun-v01-provider-codex
  • deepseek run 只挂载 agentrun-v01-provider-deepseek
  • minimax-m3 run 只挂载 agentrun-v01-provider-minimax-m3
  • dsflash-go run 只挂载 agentrun-v01-provider-dsflash-go,并包含 auth.jsonconfig.tomlmodel-catalog.json
  • codex -> deepseek -> minimax-m3 -> dsflash-go -> codex 切换后,CODEX_HOME、SecretRef、backend_status、model catalog 不互相污染。
  • 删除或缺失 deepseek/minimax-m3/dsflash-go SecretRef 时必须 secret-unavailable,不能 fallback 到 codex
  • 所有输出不得包含 Secret value、auth.jsonconfig.tomlmodel-catalog.json 明文。

A2b Tool credential 验收

  • GitHub PR、issue、UniDesk SSH passthrough 或其他 shell/tool 授权只能通过 executionPolicy.secretScope.toolCredentials[] 的 SecretRef 装配进入 runner。
  • CLI、Queue task、runner job response、dry-run manifest、event 和日志不得输出 token、SSH private key 或 credential 文件正文。
  • env projection 和 volume projection 都必须能在 runner Job dry-run 中看到 SecretRef 名称/key 和 projection kindvolume projection 必须显示只读 mount path。
  • 缺少 tool credential 时,run/command 必须返回可判定的 secret-unavailabletenant-policy-denied 或明确 blocker,不能伪装成 agent 业务失败。
  • transientEnv 不得用于 GitHub token、UniDesk SSH client token、长期 SSH key、provider API key 或其他 provider/tool 可复用 credential。HWLAB dispatcher 生成并限定 owner/HWPOD/runtime scope 的 HWLAB_API_KEY 可以作为单次 runner Job runtime context 进入 transientEnv,但正式 Kubernetes Job 必须通过 per-job Secret 和 valueFrom.secretKeyRef 投影,不能作为 pod spec plain env valueAgentRun 不保存、不解释、不回显其明文。

A3 SessionRef 验收

  • P0 若未启用 sessionrun/manifest 必须显式表现为 sessionRef=null 或 equivalent deferred 状态。
  • runner Job 不得把完整 CODEX_HOME、Secret projection 或 host path 当成 session store。
  • 后续启用 session 前,必须补充真实验收:session 目录不包含 API KEY 或 profile credential。

A4 ResourceBundleRef 验收

  • P0 ResourceBundle 只能是 kind="gitbundle"repoUrl + resolved ref/materialized commit + bundles[]
  • commitId 若作为可选 pin 出现必须是 full sha;默认 HWLAB 路径以 repo/ref 解析,不使用 cloud-api artifact revision 当内容来源。
  • checkout 只能进入允许 workspace 前缀,不能覆盖 /app、Secret projection、profile runtime home 或 session 目录。
  • run payload 不携带文件正文、env dump、Secret value 或大型 artifact。
  • 若提供 bundles[],必须能看到每个 subpath -> target_path 的复制摘要;旧字段输入必须 schema-invalid。
  • 若启用 gitMirror,必须能看到 GitHub URL 被改写到 mirror fetchRepoUrl;非 GitHub URL 必须保留原 fetch URL 并显示 mirrorUsed=false
  • 若提供 promptRefs,必须能看到每个 prompt 的 name/path/sha256/bytes/inject,新 thread 首轮 initialPromptInjected=trueresume turn initialPromptInjected=false
  • 若 bundle 复制了 .agents/skills,必须能看到 skillDirs 聚合摘要、skill 名称、manifest hash/bytes 和来源 bundle;若提供 requiredSkills,必须看到成功路径的 requiredSkills hash/bytes,以及缺失路径的 required-skill-unavailable blocker。不能显示模型默认 skill 列表当作业务 skill。

A5 综合验收

一次真实 runner Job 或 dry-run manifest 必须能同时回答:

  1. 用哪一个 image digest。
  2. 用哪一个 profile 和 SecretRef。
  3. 是否使用 session;若不用,必须明确为 null/deferred。
  4. 使用哪一个 Git repo/ref,以及最终 materialized 到哪一个 full commit;若 P0 尚未 materialize,必须明确为 deferred,不能隐式使用 host path。
  5. 是否装配 gitbundle bundles、workspace tools、初始 prompt、skillDirs 和 requiredSkills;若提供,必须能回答 name/path/hash/bytes/inject/required 和是否注入,不能只依赖模型默认 prompt 或默认 skill registry。
  6. 是否装配 tool credential;若需要 GitHub PR 能力,必须能回答 tool、purpose、SecretRef 和 projection kind,不能只在运行时 shell 中偶然存在 token。

实现状态

要素 v0.1 状态 说明
BackendImageRef 部分实现 CI/CD 已使用 digest-pinned runtime image;当前 runner/backend 仍复用 agentrun 镜像。
ProfileRef 已实现/待 dsflash-go 真实主闭环 codexdeepseekminimax-m3 已通过 SecretRef、writable runtime home 和真实 stdio turn 验证;MiniMax-M3 已通过 HWLAB 显式 session 原入口复测。dsflash-go 已补齐 SecretRef/model catalog 装配、自测试和 legacy key 归一,仍需完成真实 runtime 与 HWLAB 原入口复测;后续只允许作为 profile/config/SecretRef/model catalog 选择,不新增直连 backend。
SessionRef 已实现最小持久化 manager 持久化 sessionId/conversationId/threadIdrun 创建会解析既有 sessionrunner 按 threadId resumesession 不保存 credential 文件,TTL/GC 后续细化。
SessionRef v0.1.1 已实现/已通过 HWLAB v0.2 原入口复测 manager 持久化 sessionId/conversationId/threadId + 每个 session 绑 RWO PVCagentrun-v01-session-<sessionId>),runner Job 把 PVC 直接挂到 ${CODEX_HOME}/<codex_rollout_subdir>codex app-server 自己落盘;runner pod 删除后 replacement runner 仍复用同一 SessionRef/PVC/thread,禁止 copy/restore、replacement threadId 和 fake resume。
ResourceBundleRef 已实现 kind="gitbundle" materialization/promptRefs/tools/skillDirs/requiredSkills 装配 repoUrl + ref/materialized commit + bundles[] 已进入 run schema 和 runner checkoutworkspace 受 AGENTRUN_WORKSPACE_ROOT 限制,event/result 记录 requested ref/commit、actual commit、tree/workspace/bundles 摘要;gitMirror 会把 GitHub URL 改写到受控 mirror 并记录 fetchRepoUrl/mirrorUsedtools/ PATH、promptRefs thread-start 注入、.agents/skills 目录发现和 required skill 校验已实现。
toolCredentials 已实现 env 与 volume projection GitHub PR、GitHub SSH 和 UniDesk SSH passthrough 等 agent shell/tool 授权通过装配 SPEC 的 SecretRef 进入 runnerv0.1 支持 tool=githubtool=unidesk-ssh、`projection.kind=env
transientEnv 已实现 per-job SecretRef 投影 Queue dispatch 和 runner-job API 支持短期 runtime env;正式 Kubernetes Job 先创建本次 Job 专属 Secret,再用 valueFrom.secretKeyRef 注入 runner envresponse/event/trace 只显示 env names、Secret metadata 和 valuesPrinted=false