docs(agent-runner): align runner protocol boundaries

This commit is contained in:
huanghuoguoguo
2026-05-29 22:41:10 +08:00
parent 471d9d68b2
commit 9e9bfbfb3d
15 changed files with 504 additions and 399 deletions

View File

@@ -14,7 +14,7 @@
-`AgentRunAPIProxy.state` — get/set/delete API
- ✅ EventLog / Transcript / ArtifactStore — host 事实源
- ✅ PersistentStateStore — 持久化状态存储
-`max-round` 已从协议实体中移除,只在 Pipeline adapter 中处理
-`max-round` 已从协议实体中移除;如某 runner 仍需要类似历史窗口参数,应作为 runner binding config 由插件 manifest 暴露,而不是 Host / Pipeline 协议字段
- ✅ 外部 harness context projection 已用 Claude Code runner 做 MVP 验证context 文件、skill 投影、MCP 配置和 host-owned resume state
## 1. 设计原则
@@ -37,7 +37,11 @@
### 1.2 不再把 `max-round` 作为目标设计
Pipeline adapter 的 `max-round` 配置可以在运行时被读取并转换为某种默认 bootstrap policy不应继续作为 AgentRunner 协议的核心概念。
`max-round` 这类历史窗口参数不应继续作为 AgentRunner 协议或 Pipeline adapter 的核心概念。
如果某个 runner 仍需要“最多读取多少轮历史”这样的策略参数,应由该 runner 在自己的 manifest/config schema 中声明,并作为 binding config 存到 `ctx.config` / `runner_config`。Host 只提供 history pull API、cursor、hard cap 和权限边界runner 自己决定是否读取、读取多少、如何截断和压缩。
当前 official local-agent 方向是通过 Host history API 拉取 transcript并由 runner 自己管理模型上下文。它不依赖 Pipeline adapter 下发的 `max-round` / bootstrap 窗口。
新协议不应该问“LangBot 每轮裁几轮历史给 agent”而应该问
@@ -128,7 +132,7 @@ context:
- 自管 runtime`bootstrap: current_event`
- 简单 HTTP runner`bootstrap: recent_tail`
- Pipeline adapter 的 `max-round` 可映射为 `recent_tail` 配置,但不再作为协议字段扩展。
- runner 如果需要 `recent_tail` 策略,应通过自己的 binding config 声明窗口大小Host 不把 `max-round` 作为通用协议字段扩展。
## 3. ContextAccess
@@ -331,7 +335,7 @@ LangBot core 不应内置官方 agent 的业务流程:
**已完成(当前分支)**
-`max-round` 在 Pipeline adapter 中处理(不影响协议实体)
-`max-round` 不再是协议字段;类似历史窗口策略属于 runner binding config而不是 Host / Pipeline 通用语义
- ✅ 新 runner 默认不收到历史窗口
-`AgentRunContext` 增加 `context` / cursor / access capabilities
-`AgentRunAPIProxy` 增加 history / events / artifacts / state API

View File

@@ -377,7 +377,7 @@ Proxy 是 runner 访问 host 能力的唯一入口:
-`PipelineAdapter` — Query → Event + Binding
-`AgentBinding` 抽象
-`AgentEventEnvelope` 抽象
-`max-round` 从目标设计中移除,只在 Pipeline adapter 中处理
-`max-round` 从目标协议中移除;类似历史窗口参数若仍需要,应由具体 runner 的 manifest/config schema 暴露为 binding config
-`PersistentStateStore` — 持久化状态存储
-`EventLogStore` / `TranscriptStore` / `ArtifactStore`
- ✅ history / artifact / event 的受限拉取 API

View File

@@ -1,6 +1,6 @@
# Agent Runner 插件化当前实现与收尾计划
> 2026-05-29 状态说明:本文档是实现推进计划和历史上下文,不是最新验收结论的唯一来源。当前设计入口见 [README.md](./README.md),协议边界见 [PROTOCOL_V1.md](./PROTOCOL_V1.md),进度见 [PROGRESS.md](./PROGRESS.md)最新本地 smoke 见 [PHASE1_QA_REPORT_2026-05-29.md](./PHASE1_QA_REPORT_2026-05-29.md)。
> 2026-05-29 状态说明:本文档是实现推进计划和历史上下文,不是最新验收结论的唯一来源。当前设计入口见 [README.md](./README.md),协议边界见 [PROTOCOL_V1.md](./PROTOCOL_V1.md),进度见 [PROGRESS.md](./PROGRESS.md)下一轮测试入口见 [PHASE1_QA_ACCEPTANCE_MATRIX.md](./PHASE1_QA_ACCEPTANCE_MATRIX.md)。
本文档面向实现 agent用来把当前 AgentRunner 插件化实现推进到可迁移状态。
@@ -188,10 +188,11 @@ Protocol v1 context 的稳定字段:
Pipeline adapter 的 `prompt` 和公开业务变量不进入顶层协议字段:
- effective prompt -> `ctx.adapter.extra["prompt"]`
- filtered params -> `ctx.adapter.extra["params"]`
- `max-round` working window -> `ctx.bootstrap.messages`
- 同一窗口也可出现在 `ctx.adapter.adapter_messages`,供 adapter 消费方读取
- legacy/effective prompt 可以暂存到 `ctx.adapter.extra["prompt"]`,但 official
runner 不应把它当作行为契约
- `max-round` working window 可以保留在 Pipeline adapter 兼容层,但 official
`local-agent` 不消费该 bootstrap/window
- packaging 元数据 -> `ctx.runtime.metadata.context_packaging`
现阶段不要把新的压缩或 token-budget 裁剪塞回 Pipeline stage。Pipeline 只负责入口适配;完整历史和长期上下文由 EventLog / Transcript / pull APIs / future ContextCompressor 支撑。
@@ -301,6 +302,10 @@ api.create_temp_artifact(name: str, content_type: str, ttl_seconds: int) -> Arti
注意:旧的 unrestricted proxy action 必须二次校验,不能只靠 context 声明。AgentRunner 可用资源应来自 `ctx.resources`,不是插件 runtime 的全局能力。
本阶段不接入 sandbox/skills也不预留 runner 可见字段。后续相关分支合并后,
执行、文件、skill、MCP 等能力应先由 Host 侧封装成普通 tool再通过
`ctx.resources.tools` 进入 runnerrunner 不应识别或硬编码执行环境 provider。
资源裁剪要尽量通用,不应只写死 local-agent
- `model-fallback-selector` 授权 primary/fallback LLM。
@@ -486,7 +491,7 @@ async def run_from_query(query: pipeline_query.Query) -> AsyncGenerator[Message
- SDK `AgentRunContext` 保持 event-first`event/input/delivery/resources/context/state/runtime/config/bootstrap/adapter`
- LangBot context builder 只从 `AgentEventEnvelope + AgentBinding` 写入稳定协议字段。
- Pipeline adapter effective prompt 写入 `ctx.adapter.extra["prompt"]`把公开业务变量写入 `ctx.adapter.extra["params"]`
- Pipeline adapter 可以把公开业务变量写入 `ctx.adapter.extra["params"]`legacy/effective prompt 若保留在 `ctx.adapter.extra["prompt"]`也只属于 adapter metadata
- 保持 `ctx.config` 只表达静态绑定配置。
### Step 2增强宿主 AgentRun proxy action
@@ -506,7 +511,8 @@ async def run_from_query(query: pipeline_query.Query) -> AsyncGenerator[Message
### Step 4local-agent parity
- 使用 `ctx.adapter.extra["prompt"]` 而不是重新读取 `ctx.config["prompt"]`
- 使用静态绑定配置 `ctx.config["prompt"]`,不读取 `ctx.adapter.extra["prompt"]`
- 通过 Host history API 拉取 transcript不读取 `ctx.bootstrap.messages``ctx.adapter.adapter_messages`
- 当前 user message 从 `ctx.input.contents` 构造,保留多模态内容。
- RAG 只替换/插入文本部分,不丢图片/文件。
- streaming/non-streaming 默认跟随 `runtime.metadata.streaming_supported`
@@ -519,7 +525,7 @@ async def run_from_query(query: pipeline_query.Query) -> AsyncGenerator[Message
- 插件无输出时按 runner failed 处理。
- timeout/deadline 覆盖 plugin runtime、模型调用和外部 runner 调用。
- runner 协议错误转受控错误。
- 覆盖 local-agent 行为 parity普通回复、流式、工具、多步工具、KB、rerank、多模态、PromptPreProcessing
- 覆盖 local-agent 用户可见行为普通回复、流式、工具、多步工具、KB、rerank、多模态、绑定 prompt、history API
### Step 6官方 runner 迁移

View File

@@ -183,7 +183,10 @@ LangBot core 不应为了 local-agent 保留业务编排逻辑。local-agent 的
- `ctx.runtime.metadata.streaming_supported`:当前 adapter 是否能消费流式输出。
- 宿主代理 action模型、工具、知识库、rerank 调用必须通过 `run_id` 校验资源权限。
`max-round` 可作为 Pipeline adapter 的历史配置输入。如需适配 Pipeline 行为,可以把 `max-round` 转成 local-agent 插件自己的 bootstrap/history policy不要把它提升为 LangBot host 的目标协议字段。
`local-agent` 不应消费 Pipeline adapter 生成的 `max-round` / `bootstrap`
窗口,也不应读取 `ctx.adapter.extra.prompt`。它应从绑定配置读取静态
`prompt`,并通过 Host history API 拉取 transcript。Pipeline adapter 可以继续为旧入口
保留 `max-round` 兼容逻辑,但这不是 official local-agent 的行为契约。
建议 local-agent manifest 使用 hybrid 或 self-managed context
@@ -203,6 +206,17 @@ context:
这表示LangBot 只给当前事件和 context handleslocal-agent 自己决定是否拉取历史、是否搜索、
何时摘要、如何构造最终 prompt。
### 6.1 Native Execution / Skills 后续接入
本阶段不把 sandbox/skills 做成 AgentRunner 协议字段,也不预留 runner 可见字段。
后续 sandbox/skills 分支合并后命令执行、文件操作、skill、MCP managed process
等能力应先由 LangBot Host 封装成 scoped tools再通过 `ctx.resources.tools`
暴露给 runner。
这让 local-agent 只消费授权后的 Host 基础设施,而不是直接持有宿主机执行能力。
Claude Code / Codex 这类外部 harness runner 仍可先保留自己的执行模型,但要在文档和
配置中明确它们是否使用 LangBot 提供的工具投影。
## 7. 外部 runner 插件要求
外部平台 runner 迁移时遵循:
@@ -221,6 +235,9 @@ Claude Code、Codex、Kimi Code 这类 runner 不一定通过 LangBot 的模型/
- LangBot 授权后的资源应被投影为 harness 可读的 context 文件、MCP 配置、skill 目录、环境变量或 CLI 参数。
- 外部 session id、workspace、checkpoint 等跨轮次指针应写入 Host state 或 plugin storage插件实例本身保持无状态。
- CLI / subprocess runner 必须处理 timeout、取消、空输出、非零退出和 stderr 映射。
- 如果外部 harness 选择使用 LangBot 托管执行能力,它应通过 scoped MCP/tool
投影消费 Host 授权资源;否则它属于 external harness mode不能声称具备
LangBot-managed 执行隔离。
- 外部 harness 的 permission mode、allowed/disallowed tools、MCP 配置只是一层执行约束LangBot 仍负责调用前的资源授权、路径策略、secret 过滤和审计。发布级要求见 [SECURITY_HARDENING.md](./SECURITY_HARDENING.md)。
## 8. Claude Code runner 当前形态
@@ -260,12 +277,12 @@ Claude Code runner 当前把 LangBot event-first context 投影给外部 harness
- `codex-agent` 可通过 WebUI Debug Chat 调用本机 Codex CLI读取 LangBot event context并把 Codex `thread_id` 写入 host-owned state
- 对需要代理的本地运行环境,`codex-agent` 可通过 binding config 的 `environment-json` 显式传递非 secret 环境变量
见 [PHASE1_QA_REPORT_2026-05-29.md](./PHASE1_QA_REPORT_2026-05-29.md)。
下一轮测试入口见 [PHASE1_QA_ACCEPTANCE_MATRIX.md](./PHASE1_QA_ACCEPTANCE_MATRIX.md)。
### 8.4 当前限制
- 不是发布级安全边界实现。
- 默认只做本地 CLI 调用,不实现完整 sandbox/workspace 生命周期。
- 默认只做本地 CLI 调用,不实现完整执行隔离或 workspace 生命周期。
- 不实现 issue-centric 队列、复杂 workflow engine 或长期任务调度。
- 不代表 Codex 发布级能力或 Kimi runner 已完成;当前只验证外部 harness runner 的协议形态。
@@ -290,6 +307,6 @@ Claude Code runner 当前把 LangBot event-first context 投影给外部 harness
- 旧 runner 配置能无损复制到新 `runner_config[id]`
- LangBot 主聊天路径不再通过 `RequestRunner` 执行业务 runner。
- 官方插件测试覆盖非流式、流式、错误、timeout、配置缺失。
- `local-agent` 插件能完成模型 fallback、tool calling、知识库检索、多模态输入、prompt preprocessing 后的有效 prompt 消费、rerank。
- `local-agent` 插件能完成模型 fallback、tool calling、知识库检索、多模态输入、静态绑定 prompt 消费、history API 拉取、rerank。
- `claude-code-agent` 或同类 code-agent harness runner 能消费 event-first context、投影 scoped resources、保存 external session state并通过 WebUI Debug Chat smoke。
- 对外行为与旧内置 local-agent runner 保持一致;代码结构不需要相同。

View File

@@ -1,194 +1,245 @@
# Agent Runner 插件化 Phase 1 QA 验收矩阵
# Agent Runner QA 指南
本文档用于指导测试 agent 验收 Phase 1Agent Runner 插件化是否已经达到旧内置 runner 的对外效果
本文档是 agent-runner 插件化下一轮测试的唯一 QA 入口。它合并并取代旧的 Phase 1 验收矩阵与 2026-05-18 / 2026-05-29 两份本地 QA 报告
Phase 1 的目标是让当前聊天 Pipeline 在选择插件化 AgentRunner 后,用户可感知行为与旧内置 runner 保持一致。Phase 2/EBA 不纳入本轮验收
目标不是保留完整历史流水账,而是指导测试 agent 用最小但高价值的路径判断当前分支是否仍然健康
本文档是当前分支兼容性验收矩阵,不代表目标架构边界。目标协议以 [PROTOCOL_V1.md](./PROTOCOL_V1.md) 为准Pipeline 是兼容入口,`messages` 只是 optional bootstrapLangBot 不默认 inline 全量历史。
## 1. 测试边界
## 1. 验收边界
当前主线验证的是 AgentRunner Protocol v1
本轮必须验收:
```text
event -> binding -> runner.run(ctx) -> result stream
```
- Pipeline 仍按现有消息入口运行。
- Runner 由插件提供,并通过 `AgentRunOrchestrator` 调用。
- `local-agent` 插件达到旧内置 local-agent 的主要行为 parity。
- 官方外部 runner 插件至少完成 smoke 验收。
- 外部 harness runner当前以 Claude Code MVP 为代表)至少完成一次 WebUI smoke验证 event-first context、资源投影和 state handoff。
- 旧 Pipeline 配置兼容,新配置可保存并生效。
- 权限裁剪、错误隔离、运行状态更新不破坏主流程。
本指南验证:
本轮不验收:
- Host 能通过当前 Pipeline adapter 进入 event-first `run(event, binding)` 主链路。
- Runner 来自插件 registry而不是旧内置 runner 分支。
- `local-agent` 能消费 Host 模型、工具、知识库、history、state、artifact 等基础设施。
- 外部 harness runnerClaude Code / Codex能消费 event-first context并把 session / working directory 等指针写回 host-owned state。
- 错误、权限裁剪、无输出、timeout 等路径不会破坏主聊天流程。
- EBA EventBus。
- EBA EventRouter。
- 消息撤回、群成员加入、好友申请等非消息事件的真实接入。
- `action.requested` 平台动作执行。
- 新平台 API 权限模型。
本指南不验证:
上述非目标只允许检查协议预留是否存在,不允许作为 Phase 1 阻塞项
- Runtime Control Plane v2
- EventGateway / EventRouter 完整落地。
- 发布级 path isolation、secret filtering、MCP allowlist、资源配额和 workspace cleanup。
- 所有外部服务 runner 的真实凭据联调。
这些属于后续能力或发布门槛,分别见 [RUNTIME_CONTROL_PLANE_V2.md](./RUNTIME_CONTROL_PLANE_V2.md) 与 [SECURITY_HARDENING.md](./SECURITY_HARDENING.md)。
## 2. 状态定义
测试 agent 只能使用以下状态:
测试报告只使用以下状态:
| 状态 | 含义 |
| --- | --- |
| PASS | 按本矩阵步骤执行,所有通过条件满足,并记录证据。 |
| FAIL | 环境可用,但功能行为不满足通过条件。 |
| BLOCKED | 因缺少密钥、外部服务不可用、账号/OAuth 未完成、测试数据缺失等环境问题无法执行。必须写清阻塞原因。 |
| N/A | 当前插件或平台明确不支持该能力。必须引用 manifest capability、文档或配置说明。 |
| PASS | 按步骤执行,用户可见行为和日志证据都满足通过条件。 |
| FAIL | 环境可用,但行为不满足通过条件。 |
| BLOCKED | 凭据、CLI、外部服务、测试数据或本地配置缺失导致无法执行。必须写清阻塞原因。 |
| N/A | 当前 runner 或平台明确不支持该能力。必须引用 manifest、文档或配置说明。 |
不能使用“看起来正常”“大概通过”“未完全测试”等模糊状态。
不能使用“看起来正常”“大概通过”“基本没问题”等模糊状态。
## 3. 总体验收条件
## 3. 执行顺序
Phase 1 可以关闭的最低条件
推荐按以下顺序执行,前一层失败时不要继续扩大测试面
- 所有 P0 case 必须 PASS
- `local-agent` 的 P1 parity case 必须 PASS除非该能力旧内置 runner 也不支持,此时可标 N/A
- 官方外部 runner smoke case 至少对已具备凭据和服务的插件 PASS缺凭据的插件可标 BLOCKED但必须保留配置页面截图或日志说明
- 没有会导致主聊天路径不可用、插件 runtime 崩溃、Pipeline 配置丢失、权限绕过的未解决 FAIL
- 所有 FAIL/BLOCKED 都必须记录复现步骤、日志位置、截图或请求/响应摘要
1. Host / SDK / runner 单测
2. WebUI 登录与 Pipeline Debug Chat 基础 smoke
3. `local-agent` 高价值场景
4. Claude Code / Codex 外部 harness smoke
5. 权限和错误路径补充检查
6. 汇总 PASS / FAIL / BLOCKED并给出下一步建议。
推荐测试前先运行:
用户可见流程必须通过 WebUI 或真实消息平台验证。API / curl 只能作为诊断证据,不能单独让 UI case PASS。
## 4. 必跑基线
### 4.1 单测基线
在 LangBot 仓库运行:
```bash
uv run --frozen pytest tests/unit_tests/agent
```
Host 侧 agent runner 单测不通过时,不应进入 UI parity QA。
如果本次改动只触及默认配置或 API service也至少补跑相关目标测试例如
## 4. 证据要求
```bash
uv run pytest tests/unit_tests/api/test_pipeline_service_defaults.py
```
每个 case 至少记录
通过条件
- agent 单测全 PASS或失败项已确认与本次 agent-runner 路径无关。
- 若失败来自 `context_builder``orchestrator``session_registry``resource_builder``plugin/handler.py` 的 run action 权限路径,不应进入 UI smoke。
### 4.2 环境基线
`langbot-skills` 做环境检查:
```bash
cd "$LANGBOT_SKILLS_REPO"
bin/lbs env doctor
bin/lbs case list
```
`LANGBOT_SKILLS_REPO` 指向当前工作区里的 `langbot-skills` 仓库。优先使用已有 case而不是临时发明测试路径。
推荐首批 case
- `webui-login-state`
- `pipeline-debug-chat`
- `local-agent-basic-debug-chat`
- `local-agent-rag-debug-chat`(改动涉及 RAG / knowledge
- `local-agent-plugin-tool-call-debug-chat`(改动涉及 tool / resource policy
## 5. WebUI 主链路 Smoke
### 5.1 Runner registry
步骤:
1. 打开 WebUI Pipeline 配置页。
2. 查看 AI runner 下拉列表。
3. 选择 `plugin:langbot/local-agent/default`
4. 保存并刷新页面。
通过条件:
- runner 选项来自插件 registry。
- 保存后配置仍为 `ai.runner.id` + `ai.runner_config[id]`
- `runner_config` 表示 binding config不表示插件实例状态。
- 插件没有循环重启或 metadata 加载失败。
### 5.2 主聊天路径
步骤:
1. 使用绑定 `plugin:langbot/local-agent/default` 的 Pipeline。
2. 在 Debug Chat 发送确定性普通文本。
3. 查看 WebUI 回复和后端日志。
通过条件:
- 用户可见回复正常。
- 后端日志显示走 `AgentRunOrchestrator` / `RUN_AGENT`
- 不走旧内置 local-agent 主执行分支。
- conversation transcript 写入用户消息和助手消息。
## 6. `local-agent` 高价值测试
只保留最能覆盖架构边界的场景。
| ID | 场景 | 操作 | 通过条件 |
| --- | --- | --- | --- |
| LA-01 | 绑定 prompt | 配置 system prompt 后发送文本。 | runner 使用 `ctx.config.prompt`,不读取 `ctx.adapter.extra["prompt"]`;回复体现绑定 prompt。 |
| LA-02 | history API | 连续两轮对话,第二轮引用第一轮 marker。 | runner 通过 Host history API 或自管上下文读取历史,不依赖 bootstrap window。 |
| LA-03 | 流式 / 非流式 | 分别用支持流式和关闭流式的路径发送文本。 | 流式 UI 不重复、不空白;非流式只输出最终消息。 |
| LA-04 | 工具调用 | 绑定测试工具,发送会触发工具的 prompt。 | `ctx.resources.tools` 只包含授权工具;工具调用 started/completed最终回复包含工具结果。 |
| LA-05 | RAG | 绑定测试知识库,发送命中文档的 prompt。 | `ctx.resources.knowledge_bases` 包含所选知识库runner 通过授权 API 检索;回复使用检索内容。 |
| LA-06 | 多模态 | 发送图片输入。 | `ctx.input.contents` 保留图片;支持视觉模型时正常处理,不支持时受控失败。 |
| LA-07 | fallback / 错误 | 模拟 primary 模型失败或 runner 抛错。 | fallback 或 `run.failed` 行为受控;后续请求不受影响。 |
| LA-08 | 无输出保护 | 测试 runner 完成但不产出消息。 | 不产生空白成功回复;按受控失败或明确缺陷处理。 |
Rerank、remove-think、文件输入等场景只在本次改动直接涉及时补测不作为每轮必跑项。
## 7. 外部 Harness Runner Smoke
这些测试用于验证 Claude Code / Codex 这类自管 runtime 能走同一条 Host 协议路径。若本机没有 CLI、登录态或代理配置标记 BLOCKED不要伪造 PASS。
### 7.1 Claude Code runner
步骤:
1. 确认 `claude` CLI 在 LangBot runtime host 上可执行。
2. 绑定 `plugin:langbot/claude-code-agent/default`
3. 使用保守权限模式和确定性 prompt。
4. 在 Debug Chat 执行一次真实 smoke。
5. 检查 context / skill / MCP projection 和 host-owned state。
通过条件:
- WebUI 可见回复包含预期 sentinel。
- context JSON schema 为 `langbot.agent_runner.external_harness_context.v1` 或当前文档声明的等价 schema。
- context 包含 event、input、delivery、resources、context、state。
- 如启用 skills / MCP投影路径和配置可被 Claude Code 读取。
- `external.session_id` / `external.working_directory` 写入 host-owned state。
- CLI missing、nonzero exit、timeout、empty output 都转成受控 `run.failed`
### 7.2 Codex runner
步骤:
1. 确认 `codex` CLI 在 LangBot runtime host 上可执行。
2. 绑定 `plugin:langbot/codex-agent/default`
3. 如需要代理,使用 binding config 的 `environment-json` 显式传入。
4. 在 Debug Chat 执行一次真实 smoke。
5. 检查 JSONL 事件、last message、host-owned state。
通过条件:
- WebUI 可见回复包含预期 sentinel。
- Codex JSONL 至少包含 thread/session 起始事件、agent message、turn completed。
- `external.session_id` / `external.working_directory` 写入 host-owned state。
- timeout/cancel 不遗留 orphan CLI 子进程。
- CLI missing、nonzero exit、timeout、empty output 都转成受控 `run.failed`
### 7.3 API 型外部 runner
Dify、n8n、Coze、DashScope、Langflow、Tbox 等外部服务 runner 不作为每轮必跑项。只有在本次改动触及对应 runner 或凭据已经可用时执行 smoke。
通过条件:
- runner 可选,配置可保存。
- 请求成功,或外部服务错误被清晰返回。
- 外部服务凭据缺失时标记 BLOCKED并记录缺失项。
## 8. 权限与隔离补充
以下优先用单测 / targeted fixture 覆盖,不要求每次通过 UI 人工构造恶意 runner。
| 场景 | 推荐证据 |
| --- | --- |
| 未授权模型调用被拒绝 | `plugin/handler.py` run action 权限测试或目标单测。 |
| 未授权工具调用被拒绝 | `ctx.resources.tools` 与 host action 拒绝日志。 |
| 未授权知识库检索被拒绝 | `ctx.resources.knowledge_bases` 与 host action 拒绝日志。 |
| run_id 结束后复用被拒绝 | session registry 注销测试。 |
| 插件身份不匹配被拒绝 | `caller_plugin_identity` mismatch 测试。 |
| storage/state scope 越权被拒绝 | state/storage proxy 单测。 |
如果这些单测失败,不能用 WebUI 正常回复替代。
## 9. 证据要求
每轮测试报告至少记录:
- LangBot commit、SDK commit、相关 runner 插件 commit。
- Pipeline UUID/name、runner id、runner config 摘要。
- WebUI 截图或浏览器操作记录。
- 后端日志中对应 query id/run id 的关键行。
- 对外部 runner记录外部服务响应摘要或错误码
- 外部 harness runner,记录 context 文件、MCP/skill 投影、外部 session id / working directory state 和 CLI 错误摘要。
- Pipeline UUID/name、runner id、关键 runner config 摘要。
- WebUI 截图或 Playwright 操作记录。
- 后端日志中对应 query id / run id 的关键行。
- `langbot-skills` case/report 路径
- 外部 harness runner context 文件、session idworking directoryCLI 错误摘要。
- FAIL/BLOCKED 的复现步骤和归属仓库建议。
用户可见流程必须通过 WebUI 或真实消息平台验证。API/curl 只能作为诊断证据,不能单独让 UI case PASS。
报告结论必须回答:
## 5. P0 环境与主链路
- 是否建议继续进入下一阶段测试。
- 是否存在主聊天路径阻塞。
- 是否只是凭据 / 外部服务 / 本机 CLI 缺失导致 BLOCKED。
- 是否需要进入 [SECURITY_HARDENING.md](./SECURITY_HARDENING.md) 的发布级验收。
| ID | 场景 | 步骤 | 通过条件 |
| --- | --- | --- | --- |
| P0-ENV-01 | LangBot 服务可用 | 启动后端和前端,打开 WebUI。 | WebUI 可登录/访问;后端无启动异常;插件系统按配置启用。 |
| P0-ENV-02 | 插件 runtime 可用 | 查看插件列表或后端日志。 | runtime 已启动;官方 runner 插件处于可用状态;无循环重启。 |
| P0-ENV-03 | Runner registry 可发现插件 runner | 打开 Pipeline AI runner 配置。 | runner 下拉列表来自插件 registry至少能看到 `plugin:langbot/local-agent/default`;若安装了 Claude Code runner还应看到 `plugin:langbot/claude-code-agent/default`。 |
| P0-ENV-04 | 默认 Pipeline 可创建 | 新建 Pipeline 或读取默认 Pipeline。 | 默认配置使用 `ai.runner.id``ai.runner_config`;默认 runner 可保存。 |
| P0-ENV-05 | 主聊天路径调用插件 runner | 使用默认 `local-agent` Pipeline 发送一条普通消息。 | 后端日志显示走 `AgentRunOrchestrator` / `RUN_AGENT`;用户收到正常回复;旧内置 runner 不应作为主路径执行。 |
| P0-ENV-06 | 单测基线 | 运行 `uv run --frozen pytest tests/unit_tests/agent`。 | 全部通过;若失败,必须先修复或记录为 P0 FAIL。 |
## 10. 历史高价值记录
## 6. P1 local-agent parity
历史报告已合并为本指南,不再保留单独文档。后续若需要追溯,优先查看 `langbot-skills/reports/` 下的原始执行报告。
`local-agent` 是 Phase 1 的主验收对象。以下 case 需要和旧内置 local-agent 的用户可见行为对齐。
截至 2026-05-29已有本地 smoke 证明:
| ID | 场景 | 步骤 | 通过条件 |
| --- | --- | --- | --- |
| P1-LA-01 | 普通文本对话 | 绑定 `plugin:langbot/local-agent/default`,发送普通文本。 | 回复正常生成conversation history 写入用户消息和助手消息。 |
| P1-LA-02 | 有效 prompt | 配置 system prompt并通过 PromptPreProcessing 插件或现有预处理改变 prompt。 | runner 使用 host 处理后的 `ctx.adapter.extra["prompt"]`,不是只读取静态 `ctx.config.prompt`;回复体现有效 prompt。 |
| P1-LA-03 | 历史消息 | 连续多轮对话,第二轮引用第一轮内容。 | 当前兼容路径下 runner 能读到 host 下发的 bootstrap/history目标协议下应通过 history API 或插件自管上下文实现。第二轮能基于上下文回答。 |
| P1-LA-04 | 流式输出 | 使用支持流式的 adapter/WebUI开启流式模型或流式 runner。 | UI 逐步更新;后端接收 `message.delta`;最终没有重复消息或空白卡片。 |
| P1-LA-05 | 非流式输出 | 使用不支持流式或关闭流式的路径。 | 只输出最终消息;不会创建异常流式卡片。 |
| P1-LA-06 | 工具调用 | 绑定一个可调用工具,提问触发工具。 | `ctx.resources.tools` 只包含授权工具runner 能获取工具详情并调用;最终回复包含工具结果。 |
| P1-LA-07 | 工具权限裁剪 | 不绑定某工具,但让 runner 尝试调用。 | 调用被拒绝错误不泄露未授权工具详情Pipeline 不崩溃。 |
| P1-LA-08 | RAG 检索 | 绑定知识库并提问命中文档。 | `ctx.resources.knowledge_bases` 包含所选知识库runner 可检索;回复引用或使用检索内容。 |
| P1-LA-09 | RAG 权限裁剪 | 不绑定知识库或绑定另一个知识库。 | 未授权知识库不可检索;错误可控。 |
| P1-LA-10 | rerank | 绑定 rerank 模型并启用知识库检索排序。 | runner 可通过授权 rerank 模型排序;无权限时不允许调用。 |
| P1-LA-11 | fallback model | 配置 primary 和 fallback模拟 primary 失败。 | fallback 被调用;用户得到可用回复或明确失败提示;日志能区分 primary/fallback。 |
| P1-LA-12 | remove-think | 开启输出 `remove-think`,使用会产生 think 内容的模型。 | 用户最终回复不包含被移除的 think 内容;插件 runner 走 runtime metadata 或 API 参数保持旧行为。 |
| P1-LA-13 | 多模态图片 | 发送图片输入。 | `ctx.input.contents` / `ctx.input.attachments` 保留图片;支持视觉模型时可正常处理;不支持时错误提示可控。 |
| P1-LA-14 | 文件输入 | 发送文件或文件 URL。 | runner 可看到文件 attachment 摘要;支持文件处理时正常处理;不支持时不崩溃。 |
| P1-LA-15 | 会话状态 | runner 返回 `state.updated`,下一轮继续对话。 | state 被 host 接收并作用于下一轮conversation id 等兼容旧行为。 |
| P1-LA-16 | 异常处理 | 让 runner 返回 `run.failed` 或抛异常。 | ChatMessageHandler 使用 Pipeline 的异常策略用户提示符合配置runtime 和后续请求不受影响。 |
| P1-LA-17 | 无输出保护 | runner 完成但不返回消息。 | 不产生空白成功回复;应按受控失败处理或明确记录缺陷。 |
- `local-agent` 可以通过 Pipeline Debug Chat 走插件化 `AgentRunOrchestrator` 主链路。
- Claude Code runner 可以通过同一条 `run(event, binding)` 路径执行。
- Claude Code runner 可以读取 LangBot event-first context / skill / MCP 投影,并写回 `external.session_id` / `external.working_directory`
- Codex runner 可以通过同一条路径执行,并把 Codex `thread_id` 写回 host-owned state。
## 7. P1 配置兼容与迁移
| ID | 场景 | 步骤 | 通过条件 |
| --- | --- | --- | --- |
| P1-CFG-01 | 读取旧配置 | 使用只包含 `ai.runner.runner = local-agent` 和旧 `ai.local-agent` 配置的 Pipeline。 | 能解析为 `plugin:langbot/local-agent/default`;旧配置值生效。 |
| P1-CFG-02 | 保存新配置 | 在 WebUI 修改 runner 和 runner config 后保存。 | 数据库存储 `ai.runner.id``ai.runner_config[id]`;刷新页面后不丢失。 |
| P1-CFG-03 | runner 切换 | 同一 Pipeline 从 local-agent 切到另一个官方 runner再切回。 | 每个 runner 的绑定配置独立保存;切换不污染其它 runner config。 |
| P1-CFG-04 | 插件缺失 | 配置引用一个未安装或未启动的 runner。 | WebUI/后端给出可理解错误Pipeline 不因 metadata 加载失败整体不可用。 |
| P1-CFG-05 | bound plugin 授权 | Pipeline 只绑定部分插件。 | 未绑定插件的 runner 不能执行;已绑定插件正常执行。 |
## 8. P1 权限与隔离
| ID | 场景 | 步骤 | 通过条件 |
| --- | --- | --- | --- |
| P1-AUTH-01 | 模型权限 | runner 尝试调用不在 `ctx.resources.models` 的模型。 | Host action 拒绝;错误包含 run/session 维度信息;不会调用实际模型。 |
| P1-AUTH-02 | 工具权限 | runner 尝试调用不在 `ctx.resources.tools` 的工具。 | Host action 拒绝;不会越权执行工具。 |
| P1-AUTH-03 | 知识库权限 | runner 尝试检索不在 `ctx.resources.knowledge_bases` 的知识库。 | Host action 拒绝;不会返回未授权知识库内容。 |
| P1-AUTH-04 | 存储权限 | manifest 未声明 storage 权限时访问 plugin/workspace storage。 | 访问被拒绝;普通插件非 AgentRunner 的兼容路径不受影响。 |
| P1-AUTH-05 | run_id 生命周期 | runner 结束后继续使用旧 run_id 调 host action。 | session 已注销;请求被拒绝。 |
| P1-AUTH-06 | 插件身份隔离 | A 插件 runner 的 run_id 被 B 插件使用。 | Host 拒绝 identity mismatch。 |
## 9. P2 官方外部 runner smoke
以下 case 是 smoke不要求和 local-agent 一样覆盖全部能力。若缺少外部服务凭据,状态标 BLOCKED并记录缺失项。
| ID | Runner | 步骤 | 通过条件 |
| --- | --- | --- | --- |
| P2-EXT-01 | `dify-agent` | 配置 chat/agent/workflow 中至少一种可用应用并发送消息。 | runner 可选、配置可保存、请求成功或外部服务错误被清晰返回。 |
| P2-EXT-02 | `n8n-agent` | 配置 webhook 和认证方式并发送消息。 | webhook 被调用;返回内容进入 LangBot 回复;认证失败时提示明确。 |
| P2-EXT-03 | `coze-agent` | 配置 Coze 应用并发送文本,若可用再测图片。 | 文本回复正常;多模态能力按 manifest/配置表现;思维链处理不污染最终回复。 |
| P2-EXT-04 | `dashscope-agent` | 配置 agent 或 workflow 并发送消息。 | 调用成功;失败时错误可控且不影响后续请求。 |
| P2-EXT-05 | `langflow-agent` | 配置 flow endpoint 并发送消息。 | 普通或 SSE 流式响应能归一为 LangBot 消息。 |
| P2-EXT-06 | `tbox-agent` | 配置 Tbox 应用并发送消息。 | 回复正常;多模态输入按插件能力处理。 |
| P2-EXT-07 | `claude-code-agent` | 配置本地 Claude Code CLI使用保守权限模式发送确定性 Debug Chat prompt。 | runner 可选、配置可保存、CLI 成功返回LangBot context 文件可被 Claude Code 读取;`external.session_id` / `external.working_directory` 可写入 host-owned stateCLI 错误、timeout、空输出能被转成受控 `run.failed`。 |
| P2-EXT-08 | `codex-agent` | 配置本地 Codex CLI使用 Debug Chat 发送确定性 prompt。 | runner 可选、配置可保存、CLI 成功返回LangBot context 文件可被 Codex 读取;`external.session_id` / `external.working_directory` 可写入 host-owned state代理等 runtime-local 环境可通过 binding config 显式传入CLI 错误、timeout、空输出能被转成受控 `run.failed`。 |
### 9.1 外部 harness runner 追加检查
对 Claude Code / Codex / Kimi Code 这类 runnerP2 smoke 还需要检查:
- 默认不要求 LangBot 调用自己的模型/工具 looprunner 可以依赖自身 harness。
- LangBot 仍要把当前 event、input、delivery、resources、context 和 state 作为 scoped context 传给 runner。
- skill / MCP / workspace projection 必须来自 binding 或 Host 授权后的资源,不应让 runner 自行读取全局未授权配置。
- session id、working directory、checkpoint 等跨轮次状态必须进入 Host state 或 plugin storage不能保存在插件实例内存中。
- 发布级 path isolation、secret filtering、MCP allowlist、资源配额和 workspace cleanup 只作为 [SECURITY_HARDENING.md](./SECURITY_HARDENING.md) 的后续 release gate不阻塞当前 smoke。
## 10. P2 事件预留检查
这些只检查协议预留,不要求真实平台事件接入。
| ID | 场景 | 步骤 | 通过条件 |
| --- | --- | --- | --- |
| P2-EVT-01 | 消息事件名稳定 | 触发普通消息 runner。 | `ctx.trigger.type``ctx.event.event_type``message.received`;平台原始类型保存在 `ctx.event.event_data.source_event_type`。 |
| P2-EVT-02 | 非消息事件名预留 | 检查 host 侧保留事件名。 | `message.recalled``group.member_joined``friend.request_received` 作为稳定协议名存在。 |
| P2-EVT-03 | action.requested 预留 | 让测试 runner 返回 `action.requested`。 | Host 只记录日志,不执行平台动作,不影响主流程。 |
## 11. 退出标准
QA agent 完成后应输出一份报告,至少包含:
- 总状态PASS / FAIL / BLOCKED。
- 每个 case 的状态表。
- 所有 FAIL 的复现步骤和建议归属仓库。
- 所有 BLOCKED 的环境缺口。
- 是否建议关闭 Phase 1进入 Phase 2/EBA。
建议关闭 Phase 1 的条件:
- P0 全 PASS。
- P1 全 PASS或只有旧内置 runner 同样不支持的 N/A。
- P2 外部 runner smoke 对可用凭据全部 PASS本地 Claude Code runner 若作为当前 external harness 代表,应至少 PASS 一次 WebUI smoke。
- 剩余问题均为 EBA 预留、外部服务凭据、或非阻塞体验问题。
## 12. 当前已知验收记录
2026-05-29 本地记录:
| 范围 | 状态 | 证据 |
| --- | --- | --- |
| `local-agent` WebUI Debug Chat | PASS | `langbot-skills/reports/2026-05-29-17-59-00-462-08-00-pipeline-debug-chat.md` |
| `claude-code-agent` WebUI Debug Chat | PASS | `langbot-skills/reports/2026-05-29-18-03-31-169-08-00-pipeline-debug-chat.md` |
| Claude Code context / skill / MCP projection | PASS | `langbot-skills/reports/claude-code-agent-resource-context-20260529.md` |
| Claude Code resume state | PASS | `langbot-skills/reports/claude-code-agent-real-workdir-20260529.md` |
完整汇总见 [PHASE1_QA_REPORT_2026-05-29.md](./PHASE1_QA_REPORT_2026-05-29.md)。
这些记录只证明本地协议闭环可用,不代表发布级 security hardening 已完成。

View File

@@ -1,103 +0,0 @@
# Agent Runner Pluginization Phase 1 QA Report
Date: 2026-05-18
## Environment
- LangBot repo: `/home/glwuy/langbot-app/LangBot`
- LangBot branch/commit: `feat/agent-runner-plugin` / `036affe0`
- SDK repo commit: `/home/glwuy/langbot-app/sdk` / `feed530`
- langbot-skills commit: `/home/glwuy/langbot-app/langbot-skills` / `a82f006`
- Backend: `http://127.0.0.1:5300`, started from the `LangBot` worktree
- Frontend: `http://127.0.0.1:3000`, started from `LangBot/web`
- Pipeline: `565ec946-01a6-496d-8b8c-056a4eab7f4d` / `测试`
- Runner: `plugin:langbot/local-agent/default`
- Runner config summary: primary model configured, knowledge base `qa-local-agent-rag-20260516` bound, rerank disabled
- Installed runner plugins observed: `langbot/local-agent`, `langbot/dify-agent`
- Supporting plugins observed: `qa/plugin-smoke`, `langbot-team/LangRAG`
Evidence files:
- `/home/glwuy/langbot-app/phase1-runner-config.png`
- `/home/glwuy/langbot-app/phase1-local-agent-debug-chat.png`
- `/home/glwuy/langbot-app/phase1-console.log`
- Backend log: `/home/glwuy/langbot-app/LangBot/data/logs/langbot-2026-05-18.log`
## Automated Checks
| Check | Status | Evidence |
| --- | --- | --- |
| `uv run --frozen pytest tests/unit_tests/agent` | PASS | `241 passed, 16 warnings` |
| `uv run --frozen pytest tests/unit_tests/agent/test_handler_auth.py tests/unit_tests/agent/test_orchestrator_integration.py tests/unit_tests/agent/test_result_normalizer.py` | PASS | `96 passed, 11 warnings` |
| `langbot-skills` local env/tooling regression | PASS | `npm test`: `7 passed`; `bin/lbs validate`: `OK` |
## UI Cases Executed
| Matrix ID | Status | Evidence |
| --- | --- | --- |
| P0-ENV-01 | PASS | WebUI opened at `http://127.0.0.1:3000/home/pipelines`; backend responded on `5300`. |
| P0-ENV-02 | PASS | Logs show plugin runtime connected and plugins initialized without restart loop. |
| P0-ENV-03 | PASS | Pipeline AI runner UI and metadata show `plugin:langbot/local-agent/default` and `plugin:langbot/dify-agent/default`. |
| P0-ENV-04 | PASS | Existing default-style pipeline uses `ai.runner.id` and `ai.runner_config`; config page loaded and displayed runner config. |
| P0-ENV-05 | PASS | Debug Chat message returned `PHASE1_LOCAL_AGENT_PLAIN_OK`; logs show `[Action] run_agent`. |
| P0-ENV-06 | PASS | Agent unit baseline passed. |
| P1-LA-01 | PASS | Plain text Debug Chat returned `PHASE1_LOCAL_AGENT_PLAIN_OK`. |
| P1-LA-02 | PASS | Sending `qa-effective-prompt` returned `PROMPT_PREPROCESS_OK`. |
| P1-LA-03 | PASS | Second turn referenced the first marker and returned `PHASE1_LOCAL_AGENT_PLAIN_OK`. |
| P1-LA-04 | PASS | Stream mode enabled; UI showed bot response and logs reported streaming completion. |
| P1-LA-05 | PASS | Stream mode disabled; UI returned `PHASE1_LOCAL_AGENT_NONSTREAM_OK` without a blank/duplicate card. |
| P1-LA-06 | PASS | Prompt triggered tool call; logs show tool call started/completed for `qa_echo`; UI returned `qa-plugin-smoke:PHASE1_TOOL_CALL_OK`. |
| P1-LA-08 | PASS | Bound LangRAG KB retrieval returned sentinel `azalea-cobalt-7421`; logs show `retrieve_knowledge`. |
| P1-LA-13 | PASS | Uploaded 64x64 red-square fixture; UI returned `RED_IMAGE_OK`. |
## Unit Or Protocol Covered Cases
| Matrix ID | Status | Evidence |
| --- | --- | --- |
| P1-AUTH-01 | PASS | `test_handler_auth.py` covers unauthorized model rejection. |
| P1-AUTH-02 | PASS | `test_handler_auth.py` covers unauthorized tool rejection. |
| P1-AUTH-03 | PASS | `test_handler_auth.py` covers unauthorized knowledge-base rejection. |
| P1-AUTH-04 | PASS | `test_handler_auth.py` covers storage permission validation. |
| P1-AUTH-05 | PASS | `test_handler_auth.py` covers session expiry and unregister behavior. |
| P1-AUTH-06 | PASS | `test_handler_auth.py` covers caller plugin identity mismatch. |
| P1-LA-15 | PASS | `test_orchestrator_integration.py` covers `state.updated` handling. |
| P1-LA-16 | PASS | `test_orchestrator_integration.py` and `test_result_normalizer.py` cover `run.failed`. |
| P1-LA-17 | PASS | `test_result_normalizer.py` covers `run.completed` without message. |
| P1-CFG-01 | PASS | Config migration unit tests in the full agent suite passed. |
| P1-CFG-04 | PASS | Chat handler unit tests cover runner-not-found controlled errors. |
| P1-CFG-05 | PASS | Authorization unit tests cover bound resource restrictions. |
| P2-EVT-01 | PASS | `test_orchestrator_integration.py` asserts `message.received`. |
| P2-EVT-02 | PASS | `src/langbot/pkg/agent/runner/events.py` defines reserved event names. |
| P2-EVT-03 | PASS | `test_result_normalizer.py` covers `action.requested` as log-only/no execution. |
## Blocked Or N/A
| Matrix ID | Status | Reason |
| --- | --- | --- |
| P1-LA-07 | BLOCKED | Needs a dedicated restricted-pipeline or malicious-runner fixture to force an unauthorized tool call through the runner. Unit-level authorization passes. |
| P1-LA-09 | BLOCKED | Needs a dedicated restricted-pipeline or malicious-runner fixture to force unauthorized KB access. Unit-level authorization passes. |
| P1-LA-10 | BLOCKED | No rerank model configured for this environment. |
| P1-LA-11 | BLOCKED | Primary/fallback failure injection was not configured for this run. |
| P1-LA-12 | BLOCKED | No known think-output model/path configured for this run. |
| P1-LA-14 | N/A | Debug Chat UI exposes image upload but no generic file upload control in this run. |
| P1-CFG-03 | BLOCKED | Runner switching to an external runner requires a usable external runner config; only Dify is discoverable and no Dify credentials are configured. |
| P2-EXT-01 | BLOCKED | Dify runner is discoverable, but no Dify API key/app config is available. |
| P2-EXT-02 | N/A | `n8n-agent` runner is not discoverable in metadata. |
| P2-EXT-03 | N/A | `coze-agent` runner is not discoverable in metadata. |
| P2-EXT-04 | N/A | `dashscope-agent` runner is not discoverable in metadata. |
| P2-EXT-05 | N/A | `langflow-agent` runner is not discoverable in metadata. |
| P2-EXT-06 | N/A | `tbox-agent` runner is not discoverable in metadata. |
## Notes
- The current environment is strong enough to validate the main pluginized local-agent path: WebUI, runner registry, prompt preprocessing, history, streaming, non-streaming, tool calls, LangRAG retrieval, image input, and host-side authorization/unit protocol behavior all passed.
- External runner smoke cannot close without credentials or installed runner plugins beyond Dify.
- Console capture contains stale errors from earlier service restarts and diagnostic cross-origin fetch attempts. During the executed Debug Chat flows, the UI completed normally and the backend processed all tested queries.
- `langbot-skills` now supports machine-local `skills/.env.local` overrides, so local worktree/port changes do not need to modify shared `skills/.env`.
## Recommendation
Do not mark the whole Phase 1 matrix fully closed yet. It is reasonable to treat the local-agent Phase 1 core path as PASS, but Phase 1 closure still needs either:
- explicit acceptance that authorization/error/state cases are covered by unit/protocol tests rather than UI malicious-runner fixtures, and
- external runner credentials or a decision to keep external runner smoke BLOCKED by environment.

View File

@@ -1,103 +0,0 @@
# Agent Runner Phase 1 QA Report - 2026-05-29
本文档记录 2026-05-29 对 agent-runner plugin 协议闭环的本地验收。它不改写
[PHASE1_QA_REPORT_2026-05-18.md](./PHASE1_QA_REPORT_2026-05-18.md) 的历史结论。
## 1. 验收结论
当前分支可以认为完成了本地协议闭环 smoke
- `local-agent` 插件可以通过 Pipeline Debug Chat 走插件化 `AgentRunOrchestrator` 主链路。
- `claude-code-agent` 可以作为外部 harness runner 通过同一条 `run(event, binding)` 路径执行。
- Claude Code runner 可以接收 LangBot event-first context并把 context / skill / MCP 配置投影给本地 Claude Code CLI。
- Claude Code runner 可以把外部 session id 和 working directory 写回 LangBot host-owned state用于后续 resume。
- `codex-agent` 可以作为外部 harness runner 通过同一条 `run(event, binding)` 路径执行,并把 Codex `thread_id` 写回 host-owned state。
这表示当前架构足以支撑 `local-agent`、最小 Claude Code runner 与最小 Codex runner 的联调;不表示安全发布级 hardening 已完成。
## 2. 环境
| 项 | 值 |
| --- | --- |
| LangBot commit | `58e4b357` |
| `langbot-agent-runner` commit | `d681dda` |
| `langbot-local-agent` commit | `573cc00` |
| Claude Code CLI | `2.1.137 (Claude Code)` |
| Frontend | `http://127.0.0.1:3000` |
| Backend | `http://127.0.0.1:5300` |
## 3. Pipeline 与 Runner
| Runner | Pipeline | Runner ID | 结果 |
| --- | --- | --- | --- |
| local-agent | `dc75c543-70f9-4d2a-9467-968628e6ca01` | `plugin:langbot/local-agent/default` | PASS |
| Claude Code | `f5c6d8e0-0c5a-4f3f-b7d4-0c1a0dec0de1` | `plugin:langbot/claude-code-agent/default` | PASS |
| Codex | `57eb0cc8-5a5a-4865-9f3e-8b3ad070fbc2` | `plugin:langbot/codex-agent/default` | PASS |
## 4. 证据
### 4.1 local-agent UI E2E
- 报告:`/home/glwuy/langbot-app/langbot-skills/reports/2026-05-29-17-59-00-462-08-00-pipeline-debug-chat.md`
- 后端日志成功信号:
- `Processing request from person_websocket`
- `Conversation(1) Streaming completed: 1 chunks, 2 chars`
- 验收点Debug Chat 用户可见回复正常,后台 log guard 未发现失败信号。
### 4.2 Claude Code runner UI E2E
- 报告:`/home/glwuy/langbot-app/langbot-skills/reports/2026-05-29-18-03-31-169-08-00-pipeline-debug-chat.md`
- 后端日志成功信号:
- `Processing request from person_websocket`
- `Conversation(3) Streaming completed: 1 chunks, 22 chars`
- 验收点Debug Chat 用户可见回复 `LANGBOT_CLAUDE_E2E_OK2`
### 4.3 Claude Code context / skill / MCP projection
- 报告:`/home/glwuy/langbot-app/langbot-skills/reports/claude-code-agent-resource-context-20260529.md`
- 通过点:
- 生成的 context JSON schema 为 `langbot.agent_runner.external_harness_context.v1`
- context JSON 包含 `event``actor``delivery``input``resources``context``state`
- Claude Code 可读取 LangBot 注入的 context 文件并输出 `LANGBOT_CLAUDE_CONTEXT_RESOURCE_OK`
- skill 文件投影到 `.claude/skills/langbot-e2e-context/SKILL.md`
### 4.4 Claude Code resume state
- 报告:`/home/glwuy/langbot-app/langbot-skills/reports/claude-code-agent-real-workdir-20260529.md`
- 通过点:
- `agent_runner_state` 中记录了 `external.session_id`
- `agent_runner_state` 中记录了 `external.working_directory`
- 使用保存的 session id 在对应工作目录执行 Claude Code resume 成功。
### 4.5 Codex runner UI E2E
- 报告:`/home/glwuy/langbot-app/langbot-skills/reports/codex-agent-real-20260529-fifth.md`
- 截图:`/home/glwuy/langbot-app/langbot-skills/reports/evidence/codex-agent-real-20260529-fifth/screenshot.png`
- 后端日志成功信号:
- `Processing request from person_websocket`
- `Conversation(0) Streaming completed: 1 chunks, 21 chars`
- Codex JSONL 事件:
- `thread.started`
- `item.completed` with `agent_message`
- `turn.completed`
- 通过点:
- Debug Chat 用户可见回复 `LANGBOT_CODEX_E2E_OK5`
- `agent_runner_state` 中记录了 `external.session_id``external.working_directory`
- `environment-json` 可以显式传入代理环境,避免插件 worker 环境缺失导致本地 Codex CLI 卡住。
- timeout/cancel 路径会清理 Codex 子进程,避免 orphan `codex exec`
## 5. 当前未关闭项
以下不应作为当前协议闭环的阻塞项:
- 发布级安全 hardening见 [SECURITY_HARDENING.md](./SECURITY_HARDENING.md)。
- 完整 EBA 分支联调和 EventGateway 迁移。
- 完整异步队列、issue-centric 产品模型和复杂 workflow engine。
- Codex 发布级能力 / Kimi runner 全量接入。
## 6. 建议状态
- 本地 `local-agent` 协议闭环PASS。
- 本地 Claude Code external harness smokePASS。
- 本地 Codex external harness smokePASS。
- Phase 1 是否整体关闭:可以关闭本地协议闭环;若定义为所有官方外部服务 runner 都必须有真实凭据,则外部服务 runner 仍按凭据可用性分别 PASS / BLOCKED。

View File

@@ -151,8 +151,7 @@
## 相关文档
- [README.md](./README.md) — 总体设计
- [PHASE1_QA_ACCEPTANCE_MATRIX.md](./PHASE1_QA_ACCEPTANCE_MATRIX.md) — Phase 1 agent QA 验收矩阵
- [PHASE1_QA_REPORT_2026-05-29.md](./PHASE1_QA_REPORT_2026-05-29.md) — 2026-05-29 本地 smoke 验收记录
- [PHASE1_QA_ACCEPTANCE_MATRIX.md](./PHASE1_QA_ACCEPTANCE_MATRIX.md) — Agent Runner QA 指南和下一轮测试入口
- [OFFICIAL_RUNNER_PLUGINS.md](./OFFICIAL_RUNNER_PLUGINS.md) — 官方插件仓库计划
- [SECURITY_HARDENING.md](./SECURITY_HARDENING.md) — 安全发布级 hardening 后续门槛
- [IMPLEMENTATION_PLAN.md](./IMPLEMENTATION_PLAN.md) — 具体实施细节

View File

@@ -11,7 +11,7 @@
- ✅ Host 支持 `run_id` session authorization
- ✅ Host 能从当前 Pipeline 入口生成 event-first context
-`messages` 降级为 optional bootstrap
-`max-round` 不出现在协议实体中(只在 Pipeline adapter 中处理)
-`max-round` 不出现在协议实体中;类似历史窗口参数若存在,应来自 runner manifest/config schema并作为 binding config 进入 `ctx.config`
- ✅ Proxy 覆盖 model、tool、knowledge、state/storage
- ✅ History / Event / Artifact / State API 已落地
- ✅ EventLog / Transcript / ArtifactStore / PersistentStateStore 已落地
@@ -147,7 +147,7 @@ Host 使用该声明决定是否给 runner inline bootstrap history。默认原
- Host 默认只 inline 当前 event / input 和 context handles。
- Runner 拥有 working context assembly。
- Runner 可在授权后通过 Host history / event / artifact / state APIs 拉取更多上下文。
- `max-round` 不属于 Protocol v1 字段。
- `max-round` 不属于 Protocol v1 字段,也不属于 Pipeline / Host 通用语义
## 4. Run 协议
@@ -344,7 +344,7 @@ class BootstrapContext(BaseModel):
- `bootstrap.messages` 是 host convenience不是协议核心。
- 自管 context runner 默认应收到空 bootstrap 或只收到当前 event。
- Host 不应为了”帮 agent 更聪明”而自动拼接完整 transcript。
- Pipeline adapter 的 `max-round` 配置只影响 adapter 如何生成 `bootstrap.messages`,不能成为 Protocol v1 字段
- 类似历史窗口策略应由具体 runner 的 binding config 表达new/official runners 不应依赖 Pipeline adapter 下发的 bootstrap window
### 4.10 RuntimeContext
@@ -638,7 +638,7 @@ Protocol v1 的安全边界在 Host
- Host 在调用前完成 binding/resource policy 裁剪、路径策略、secret 过滤和审计记录。
- Runner plugin 把授权后的 context/resource projection 适配为目标 harness 的 context 文件、MCP 配置、skill 目录、环境变量或 CLI 参数。
- Claude Code / Codex / Kimi Code 等外部 harness 的 native permission mode、allowed/disallowed tools 和 sandbox 只是额外执行约束,不能替代 Host 侧授权。
- Claude Code / Codex / Kimi Code 等外部 harness 的 native permission mode、allowed/disallowed tools 和执行隔离策略只是额外执行约束,不能替代 Host 侧授权。
- 外部 session id、working directory、checkpoint 等跨轮次指针应作为小型 JSON state 保存,例如 `external.session_id``external.working_directory`
完整路径隔离、MCP allowlist、secret redaction、配额、workspace 清理和发布级安全测试不属于当前 Protocol v1 smoke 闭环,详见 [SECURITY_HARDENING.md](./SECURITY_HARDENING.md)。
@@ -662,15 +662,15 @@ Pipeline 是当前入口 adapter不是协议中心。
-`PipelineAdapter.query_to_event(query)` — 从 `Query` 构造 `AgentEventEnvelope`
-`PipelineAdapter.pipeline_config_to_binding(query, runner_id)` — 从 Pipeline config 构造临时 AgentBinding
-`run_from_query()` 委托到 `run(event, binding)`
-`max-round` 在 Pipeline adapter 中处理,不进入协议实体
-runner-specific config 从 Pipeline 当前绑定配置透传到 `AgentBinding.runner_config` / `ctx.config`
- ✅ Query-only 字段放入 `adapter` context
Pipeline adapter 负责:
-`Query` 构造 `AgentEventContext`
- 从 Pipeline config 构造临时 AgentBinding。
- runner config 构造 `ctx.config`
- `max-round` 转换为 `bootstrap` policy
-当前 runner binding config 构造 `ctx.config`
- 保留必要的 legacy adapter metadata但不定义历史窗口、prompt 组装或 agentic context 策略
- 将 Query-only 字段放入 `adapter`
Runner 不应长期依赖 `adapter`。新 runner 应只依赖 event-first context 和 Host APIs。
@@ -684,7 +684,7 @@ Protocol v1 已在当前分支完成:
- ✅ Host 支持 `run_id` session authorization
- ✅ Host 能从当前 Pipeline 入口生成 event-first context
-`messages` 降级为 optional bootstrap
-`max-round` 不出现在协议实体中
-`max-round` 不出现在协议实体中;类似参数属于具体 runner binding config
- ✅ Proxy 至少覆盖 model、tool、knowledge、state/storage
- ✅ History / event / artifact API 已落地
- ✅ EventLog / Transcript / ArtifactStore / PersistentStateStore 已落地

View File

@@ -24,6 +24,7 @@
- **Event subscription / Event notification**:事件订阅、推送通知
- **BindingResolver persistence UI**:绑定配置的持久化 UI 和 event router 集成(如由其他模块负责)
- **Scheduler / Background event source**:定时任务、后台事件源
- **Runtime control plane v2**runtime registry、heartbeat、task queue、daemon claim、progress/cancel 和 runtime audit
EventGateway 在本文档中描述为 **future integration point**,由外部 event branch 提供。本分支只定义 host-side envelope/binding models 和 `run(event, binding)` orchestrator 入口。
@@ -51,11 +52,11 @@ Pipeline path 已获得 event-first host capabilities
| [HOST_SDK_INFRASTRUCTURE.md](./HOST_SDK_INFRASTRUCTURE.md) | LangBot 宿主能力、SDK 协议、runner 发现、绑定、权限、状态、存储、生命周期和调用链。 |
| [AGENT_CONTEXT_PROTOCOL.md](./AGENT_CONTEXT_PROTOCOL.md) | Agent-owned context 方向:事件到来时 LangBot 传什么agent 如何按需拉取更多历史 / artifact / state以及如何支持 KV cache 友好的上下文管理。 |
| [EVENT_BASED_AGENT.md](./EVENT_BASED_AGENT.md) | EBA 预留:事件模型、事件来源、触发绑定、非消息事件如何复用 AgentRunner 调度。**标注为 future design note**。 |
| [RUNTIME_CONTROL_PLANE_V2.md](./RUNTIME_CONTROL_PLANE_V2.md) | Agent Platform v2 / runtime 管控面预留Host 新增 runtime registry、heartbeat、task queue、daemon 执行和 audit管理插件构建在这些 Host 能力之上。**标注为 future design note**。 |
| [OFFICIAL_RUNNER_PLUGINS.md](./OFFICIAL_RUNNER_PLUGINS.md) | 官方 runner 插件迁移,包括 local-agent 和外部 runner。它是下游落地计划不是 LangBot 基础能力设计的前置约束。 |
| [PHASE1_QA_ACCEPTANCE_MATRIX.md](./PHASE1_QA_ACCEPTANCE_MATRIX.md) | 当前阶段的 QA 验收矩阵。它验证现有分支的兼容性,不代表最终架构边界。 |
| [PHASE1_QA_ACCEPTANCE_MATRIX.md](./PHASE1_QA_ACCEPTANCE_MATRIX.md) | Agent Runner QA 指南:保留最高价值测试路径,指导 agent 开展下一轮 WebUI / runner smoke 验证。 |
| [SECURITY_HARDENING.md](./SECURITY_HARDENING.md) | 安全发布级 hardening 的后续发布门槛路径隔离、权限边界、secret、资源配额、MCP / skill 投影和审计。 |
| [PROGRESS.md](./PROGRESS.md) | 当前实现进度、已验收能力、未完成收尾和非本分支范围。 |
| [PHASE1_QA_REPORT_2026-05-29.md](./PHASE1_QA_REPORT_2026-05-29.md) | 2026-05-29 本地 local-agent 与 Claude Code runner 的 UI E2E / smoke 验收记录。 |
## 工作拆分
@@ -79,7 +80,7 @@ Pipeline path 已获得 event-first host capabilities
LangBot 不应成为最终 agentic context manager。它应提供事实源、默认上下文引用和按需读取 APIagent 或其背后的 runtime 负责历史剪裁、摘要、召回和 KV cache 策略。
当前代码中的 `max-round` 是 Pipeline adapter 配置,不应作为目标协议继续扩展
`max-round` 这类历史窗口参数不应作为目标协议继续扩展;如果某个 runner 仍需要类似策略,应由该 runner 的 manifest/config schema 暴露为 binding config
详见 [AGENT_CONTEXT_PROTOCOL.md](./AGENT_CONTEXT_PROTOCOL.md)。
@@ -103,6 +104,15 @@ LangBot 不应成为最终 agentic context manager。它应提供事实源、默
详见 [OFFICIAL_RUNNER_PLUGINS.md](./OFFICIAL_RUNNER_PLUGINS.md)。
### 5. Runtime Control Plane v2Future
当前 AgentRunner v1 主线只负责 `event -> binding -> runner.run(ctx) -> result stream`
后续 Agent Platform v2 可以在 Host 侧新增 runtime registry、heartbeat、task queue、daemon claim、progress/cancel 和 runtime audit。
在这些 Host 能力之上,可以构建独立 agent 管控面插件;插件负责 UI、策略和编排体验runtime/task 的事实源仍由 Host 持有。
详见 [RUNTIME_CONTROL_PLANE_V2.md](./RUNTIME_CONTROL_PLANE_V2.md)。
## 已确认决策
- 一个插件可以声明多个 `AgentRunner` 组件,每个组件独立暴露 manifest、配置 schema、能力和权限。
@@ -112,3 +122,4 @@ LangBot 不应成为最终 agentic context manager。它应提供事实源、默
- 官方 runner 插件是协议消费者,不是协议设计的优先约束。
- Pipeline 是当前入口 adapter不是未来架构中心。
- EventGateway 是 future integration point由外部 event branch 提供。
- Runtime control plane 是 v2 Host capability layer不阻塞当前 AgentRunner v1 主线agent 管控面插件应构建在该 Host 能力层之上。

View File

@@ -0,0 +1,225 @@
# Agent Runtime Control Plane V2
本文档记录后续 Agent Platform / runtime 管控面的设计方向。它是当前讨论中的 **v2 文档**,但这里的 v2 指 Host capability layer / runtime control plane不是 `AgentRunner Protocol v2`,也不属于当前 AgentRunner Protocol v1 插件化主线的交付范围。
## 1. 结论
当前主线应继续收口 AgentRunner v1
```text
message/event -> binding -> runner.run(ctx) -> result stream
```
Runtime Control Plane v2 在 Host 侧新增 runtime control plane
```text
event -> task -> runtime selection -> daemon claim -> execute -> progress/audit/result
```
在 Runtime Control Plane v2 之上,可以构建独立的 agent 管控面插件。插件负责 UI、策略和编排体验runtime、task、heartbeat、audit 的事实源必须属于 LangBot Host而不是插件私有 storage。
## 2. 不影响 v1 主线
v2 不应改变 AgentRunner v1 的基本契约:
- 现有 `local-agent`、Dify、n8n、Coze 等 runner 仍可按 v1 直接执行。
- 当前 Claude Code / Codex MVP runner 可以继续作为本机 subprocess 开发路径。
- Host v1 已有的 event-first context、resource authorization、history / event / artifact / state / storage pull APIs 继续保留。
- Pipeline 仍只是当前入口 adapter不参与 v2 runtime 管控面的设计中心。
v2 只是在 Host 上新增一层可选能力。需要管控面的 runner 或管理插件可以声明使用它;不需要的 runner 不受影响。
## 3. 当前 Host 能力与缺口
当前 Host 已经具备 v2 的基础设施底座:
- `AgentEventEnvelope` / `AgentBinding`
- run-scoped resource authorization
- EventLog / Transcript / ArtifactStore / PersistentStateStore
- History / Event / Artifact / State / Storage pull APIs
- AgentRunner result stream 和受控错误回流
- binding config 与 host-owned state
这些能力足够支持一次 `runner.run(ctx)` 内的安全执行,但不足以承担完整 runtime 管控面。
v2 还需要 Host 新增:
- runtime registryruntime id、所属 workspace、所在机器、provider 能力、状态。
- capability discovery`claude` / `codex` / 其它 CLI 是否存在、版本、登录状态、执行隔离能力。
- heartbeat / livenessruntime 在线、忙闲、最后心跳、可用 slot。
- task queueenqueue、claim、start、progress、complete、fail、cancel。
- workspace mappingLangBot workspace / project 如何映射到 runtime 上的真实目录、仓库或挂载。
- secret / env projection按授权向 runtime 投影 token、代理、MCP 配置、技能和环境变量。
- runtime auditstdout、stderr、事件流、产物、失败原因、执行耗时、使用量。
- control API / UI选择 runtime、测试 runtime、查看状态、下线、取消任务、重试任务。
## 4. 角色边界
### 4.1 LangBot Host
Host 是事实源和控制面内核:
- 保存 runtime / task / heartbeat / audit 状态。
- 做权限校验、资源裁剪、workspace 绑定和审计。
- 决定任务是否可被某 runtime claim。
- 将执行结果统一回写到 event / transcript / artifact / state。
Host 不应内置具体 agent CLI 的复杂业务逻辑,也不应把某个官方 runner 的特殊行为提升为通用协议。
### 4.2 Agent 管控面插件
管理插件是 v2 control plane 的产品化管理层:
- 展示 runtime、agent、task、进度、失败、审计。
- 提供策略配置,例如默认 runtime、provider 偏好、并发限制、重试策略。
- 触发 runtime 测试、任务取消、任务重试、手动分配。
管理插件不应把 runtime/task 的事实源放进自己的 plugin storage。它应该调用 Host v2 API。
### 4.3 Runtime daemon / worker
Runtime daemon 负责真实执行:
- 在所在机器上检测 CLI 和版本。
- 管理工作目录、仓库、挂载、临时文件和进程。
- 从 Host claim 任务,执行后上报 progress / complete / fail。
- 将 stdout / stderr / artifacts / session id 回流 Host。
Claude Code、Codex、OpenCode、Gemini CLI 等 provider 适配逻辑应主要落在 daemon / worker 或 provider adapter 中。
## 5. 部署形态
### 5.1 uv / local embedded
用户用 `uv` 或源码直接启动 LangBot 时LangBot 进程所在机器就是 runtime host。
这种模式下可以直接检测用户主机上的 `claude``codex` 等 CLI也可以直接 subprocess 执行。它适合个人开发和本地 smoke但不应作为团队级管控面的唯一形态。
### 5.2 Docker embedded
用户用 Docker 启动 LangBot 时runtime host 是容器,不是宿主机。
因此:
- 只能检测容器内的 `claude``codex`
- 只能使用容器内的 HOME、PATH、凭据和挂载目录。
- 如果镜像未安装 CLI或未挂载认证文件 / workspaceCLI runner 会不可用。
Docker embedded 可以作为高级部署选项,但需要用户显式安装 CLI、挂载工作区和凭据。Host 不应假设 Docker 容器能自动访问宿主机 CLI。
### 5.3 Sidecar daemon
推荐的 v2 形态是 sidecar daemon
```text
LangBot Host (Docker or server)
<-> Runtime daemon on user host / worker host
-> claude / codex / other CLI
```
这种模式下LangBot 可以跑在 Docker 内runtime daemon 跑在宿主机或独立 worker 机器上。daemon 负责检测本机 CLI、持有本机凭据和工作区访问能力。
### 5.4 Remote runtime
团队场景可以使用远端 runtime
- 开发机、构建机、云主机或专用 worker。
- 多个 workspace 可绑定不同 runtime。
- Host 只通过 registry / task queue / heartbeat / audit 进行管理。
### 5.5 API-only agent
Dify、n8n、Coze、DashScope 等 API 型 runner 不依赖本地 CLI。它们可以继续按 v1 直接执行,也可以在未来按需要接入 v2 task/audit。
## 6. 与 Claude Code / Codex MVP runner 的关系
当前 Claude Code / Codex runner 是 v1 runner
```text
runner.run(ctx) -> subprocess("claude" / "codex")
```
它们适合验证 Host context 投影、state resume、result stream 和基础 CLI 调用,但有明确限制:
- 命令只在 LangBot runtime host 上执行。
- Docker 环境只能看到容器内 CLI。
- 没有 runtime registry、heartbeat、task queue、cancel、workspace lifecycle。
- 不提供发布级执行隔离、secret projection、团队级 audit。
v2 不需要删除这些 runner。它们可以继续作为 dev / MVP 路径存在。未来若接入管控面,可以增加 runtime-managed 执行模式:
```text
runner binding -> Host task -> runtime daemon -> provider CLI -> Host result
```
## 7. 最小 v2 API 草案
以下仅记录能力边界,不代表最终 API 命名。
Runtime
- `runtime.register`
- `runtime.heartbeat`
- `runtime.list`
- `runtime.get`
- `runtime.disable`
- `runtime.capabilities.report`
- `runtime.capabilities.probe`
Task
- `task.enqueue`
- `task.claim`
- `task.start`
- `task.progress`
- `task.complete`
- `task.fail`
- `task.cancel`
- `task.retry`
Workspace
- `runtime.workspace.bind`
- `runtime.workspace.unbind`
- `runtime.workspace.resolve`
Audit / artifacts
- `task.log.append`
- `task.artifact.create`
- `task.events.page`
这些 API 应由 Host 提供,并受 workspace、runtime、binding、actor 和 plugin identity 约束。
## 8. 管控面插件可以构建的能力
基于 v2 Host 能力,可以实现一个类似 Multica 的 agent 管控面插件:
- runtime 列表、在线状态、CLI 能力、版本、认证状态。
- agent profile 与 runtime/provider 绑定。
- 任务看板、任务详情、进度流、失败原因、重试和取消。
- workspace 到 runtime 目录 / 仓库的映射管理。
- provider capability 测试,例如 Claude Code / Codex 是否可执行。
- 审计视图输入、输出、工具、artifact、stdout/stderr、session id。
- 策略配置:并发、队列、默认 runtime、fallback runtime、权限模式。
该插件应该是 Host v2 的消费者,而不是 Host v2 的替代品。
## 9. 设计原则
- v1 先稳定v2 可选叠加。
- Host 保存事实源,插件提供管理体验。
- Runtime daemon 执行具体 CLI 和本机资源访问。
- Docker 不假设拥有宿主机 CLI需要 sidecar 或显式挂载。
- Pipeline 不进入 v2 控制面中心。
- 直接 subprocess runner 可保留,但只作为 local/dev/MVP 路径。
- 发布级能力必须经过 Host 权限、审计和资源边界。
## 10. 待定问题
- runtime daemon 与 Host 的认证模型workspace token、device token、还是 scoped PAT。
- task 与 AgentRunner binding 的映射关系:由 binding 直接 enqueue还是由独立 task policy 决定。
- runtime capability schema 的稳定字段provider、version、login status、execution isolation、workspace access、slot。
- secret projection 的边界Host 存储、用户本机存储、或外部 secret manager。
- Docker compose 是否提供官方 sidecar daemon 示例。
- v2 UI 是核心前端的一部分,还是完全由管理插件提供。

View File

@@ -155,7 +155,7 @@ class AgentBinding(pydantic.BaseModel):
"""Runner ID to invoke."""
runner_config: dict[str, typing.Any] = pydantic.Field(default_factory=dict)
"""Runner instance configuration."""
"""Runner binding configuration."""
resource_policy: ResourcePolicy = pydantic.Field(default_factory=ResourcePolicy)
"""Resource policy."""

View File

@@ -23,7 +23,7 @@ class AgentResourceBuilder:
- Apply 3-layer permission filtering:
1. Runner manifest declared permissions
2. Pipeline extensions_preference (bound plugins/MCP servers)
3. Runner instance config selected resources
3. Runner binding config selected resources
- Build models list from authorized models
- Build tools list from bound plugins/MCP servers
- Build knowledge_bases list from config
@@ -68,7 +68,7 @@ class AgentResourceBuilder:
# Layer 2: Binding resource policy
resource_policy = binding.resource_policy
# Layer 3: Runner instance config
# Layer 3: Runner binding config
runner_config = binding.runner_config
# Build each resource category

View File

@@ -75,4 +75,4 @@ def make_session(
'last_activity_at': now,
},
'_authorized_ids': authorized_ids,
}
}

View File

@@ -42,7 +42,6 @@ async def test_default_pipeline_config_uses_installed_local_agent_schema():
'plugin:langbot/local-agent/default',
[
{'name': 'model', 'type': 'model-fallback-selector', 'default': {'primary': '', 'fallbacks': []}},
{'name': 'max-round', 'type': 'integer', 'default': 10},
{'name': 'prompt', 'type': 'prompt-editor', 'default': [{'role': 'system', 'content': 'Hello'}]},
],
)
@@ -61,7 +60,6 @@ async def test_default_pipeline_config_uses_installed_local_agent_schema():
assert config['ai']['runner_config'] == {
'plugin:langbot/local-agent/default': {
'model': {'primary': '', 'fallbacks': []},
'max-round': 10,
'prompt': [{'role': 'system', 'content': 'Hello'}],
},
}