# LangBot Host 与 SDK 基础设施设计 本文档描述 LangBot 和 SDK 为插件化 AgentRunner 共同提供的基础设施。它不以 Pipeline 为中心,也不以官方 local-agent 的实现方式为前提。 ## 1. 目标 LangBot 要转为 agent host,而不是内置 runner 容器: - 接收 IM、WebUI、API 和未来 EventRouter 产生的事件。 - 根据事件、bot、workspace、scope 解析应该调用的 agent binding。 - 发现、校验和调用插件提供的 AgentRunner。 - 为每次 run 提供受限资源、状态、存储、上下文引用和生命周期控制。 - 接收 AgentRunner 返回的事件流,并投递到 IM、WebUI 或其他 output surface。 SDK 要提供稳定协议: - `AgentRunner` 组件定义。 - runner manifest / capabilities / permissions / config schema。 - `AgentRunContext` 输入 envelope。 - `AgentRunResult` 输出事件流。 - `AgentRunAPIProxy` 运行期受限 API。 ## 2. 非目标 - 不把 Pipeline 当作长期架构中心。 - 不要求所有 AgentRunner 依赖 LangBot 的上下文管理。 - 不要求官方 local-agent 的旧行为反向塑造 host 协议。 - 不在 host 中实现通用 agentic prompt assembler。 - 不强制 runner 使用 LangBot state / storage;LangBot 只提供可选、受控的寄宿能力。 ## 3. 分层架构 目标结构: ```text IM / WebUI / API / EventRouter | v Event Gateway | v AgentBindingResolver | v AgentRunOrchestrator |-- AgentRunnerRegistry |-- AgentResourceBuilder |-- AgentContextBuilder |-- AgentRunSessionRegistry |-- AgentStateStore / Storage / EventLog / ArtifactStore v Plugin Runtime / AgentRunner | v AgentRunResult stream | v Delivery / Renderer / Platform API ``` 当前 Pipeline 只应接入在 `Event Gateway` 或兼容 adapter 位置。它可以继续产生 `message.received`,但不应继续拥有 runner 选择、上下文裁剪和业务 agent 执行的核心语义。 ## 4. LangBot 侧能力 ### 4.1 Event Gateway Event Gateway 负责把入口统一成 host event: - IM 平台消息。 - WebUI debug chat 消息。 - API 触发。 - 后续非消息事件,例如入群、撤回、好友申请。 输出应是稳定 envelope,而不是 Pipeline Query 私有结构: ```python class AgentEventEnvelope(BaseModel): event_id: str event_type: str event_time: int | None source: str bot_id: str | None workspace_id: str | None conversation_id: str | None thread_id: str | None actor: ActorRef | None subject: SubjectRef | None input: AgentInput delivery: DeliveryContext raw_ref: RawEventRef | None ``` 原始平台 payload 可以存为 raw event 或 artifact ref;不要把平台私有字段直接扩散到 AgentRunner 顶层协议。 ### 4.2 Agent Binding Agent binding 是“什么事件调用哪个 runner、带什么绑定配置”的持久配置。它替代长期依赖 Pipeline runner config 的角色。 建议模型: ```python class AgentBinding(BaseModel): binding_id: str scope: BindingScope event_types: list[str] runner_id: str runner_config: dict[str, Any] resource_policy: ResourcePolicy state_policy: StatePolicy delivery_policy: DeliveryPolicy enabled: bool ``` Pipeline 当前可以被迁移为一种 binding source: - 旧 Pipeline AI runner config -> `AgentBinding` - 旧 Pipeline extension preference -> `resource_policy` - 旧 Pipeline output settings -> `delivery_policy` 但新设计不应再把这些字段命名为 Pipeline 专属概念。 ### 4.3 AgentRunnerRegistry Registry 负责收集 runner descriptor: - 插件 runtime 提供的 `AgentRunner`。 - 可能存在的 host adapter runner。 - 开发期本地插件 runner。 Descriptor 必须包含: ```python class AgentRunnerDescriptor(BaseModel): id: str source: Literal["plugin", "host_adapter"] label: I18nObject description: I18nObject | None = None capabilities: AgentRunnerCapabilities permissions: AgentRunnerPermissions config_schema: list[DynamicFormItemSchema] plugin: PluginRef | None = None ``` `plugin:author/name/runner` 仍可作为稳定 id 格式。多个 binding 指向同一个 runner id 时,不创建多个插件实例。 ### 4.4 AgentRunOrchestrator Orchestrator 是唯一运行入口: ```text run(event, binding) -> resolve runner descriptor -> build resources -> build context -> register run session -> call plugin runtime -> normalize result stream -> update state -> unregister run session ``` 它负责: - `run_id` 生成和生命周期。 - timeout / deadline / cancellation。 - 插件异常隔离。 - result schema 校验和大小限制。 - state.updated 处理。 - delivery backpressure 和 telemetry。 `run_from_query()` 这类 API 可以保留为兼容 adapter,但内部应转换成 event + binding 后走统一 `run()`。 ### 4.5 Resource Authorization LangBot 在每次 run 前生成 `ctx.resources`。资源来自三层约束: - runner manifest 声明的 permissions。 - binding/resource policy 允许的资源范围。 - 当前 event / actor / bot / workspace 的实际权限。 资源类型包括: - models - tools - knowledge bases - files / artifacts - storage - platform capabilities - history / transcript access 运行期 action 必须再次通过 `run_id` 校验。SDK 侧本地校验只用于开发体验,host 侧校验才是安全边界。 ### 4.6 State 与 Storage LangBot 可以提供 host-owned state,让 AgentRunner 把状态寄宿在 LangBot: - conversation state - actor state - subject state - runner/binding state - workspace state 但这不是强制。外部 agent runtime 可以维护自己的 session 和 memory。LangBot 只需要提供: - 授权开关。 - scope key。 - get/set/list/delete API。 - 持久化 backend。 - 审计和清理策略。 当前进程内 state store 只能作为过渡实现,不能作为正式生产语义。 ### 4.7 EventLog / Transcript / Artifact LangBot 应提供事实源能力: - `EventLog`: 保存原始事件、系统事件、工具调用、投递结果、错误。 - `Transcript`: 面向对话 UI / agent history 的消息投影。 - `ArtifactStore`: 保存大文件、多模态输入、工具大结果、平台附件。 AgentRunner 可以读取这些能力,但不能被迫使用 LangBot 作为唯一记忆系统。 ## 5. SDK 侧协议 ### 5.1 AgentRunner 组件 ```python class AgentRunner(BaseComponent): __kind__ = "AgentRunner" @classmethod def get_capabilities(cls) -> AgentRunnerCapabilities: ... @classmethod def get_config_schema(cls) -> list[dict]: ... async def run(self, ctx: AgentRunContext) -> AsyncGenerator[AgentRunResult, None]: ... ``` ### 5.2 Capabilities 建议能力声明: ```yaml capabilities: streaming: true tool_calling: true knowledge_retrieval: true multimodal_input: true event_context: true platform_api: false interrupt: true stateful_session: true self_managed_context: true host_state: optional ``` `self_managed_context` 表示 runner 或外部 runtime 自己管理上下文。Host 不应给它强塞历史窗口,只提供当前事件和 context handles。 ### 5.3 Permissions ```yaml permissions: models: ["invoke", "stream", "rerank"] tools: ["detail", "call"] knowledge_bases: ["list", "retrieve"] history: ["page", "search"] artifacts: ["metadata", "read"] storage: ["plugin", "workspace", "binding"] platform_api: [] ``` 权限声明是 runner 需要的最大能力,实际可用资源仍由 binding 和当前运行上下文裁剪。 ### 5.4 AgentRunContext Context 顶层应是 event-first,而不是 Query-first: ```python class AgentRunContext(BaseModel): run_id: str trigger: AgentTrigger event: AgentEventContext conversation: ConversationContext | None = None actor: ActorContext | None = None subject: SubjectContext | None = None input: AgentInput resources: AgentResources context: ContextAccess state: AgentRunState runtime: AgentRuntimeContext config: dict[str, Any] ``` `messages` 可以作为兼容字段或 bootstrap 字段,但不应继续是协议核心。 ### 5.5 AgentRunResult 输出应是事件流: ```python class AgentRunResult(BaseModel): type: Literal[ "message.delta", "message.completed", "tool.call.started", "tool.call.completed", "state.updated", "artifact.created", "action.requested", "run.completed", "run.failed", ] data: dict[str, Any] = {} ``` 当前消息回复只消费 `message.delta` / `message.completed` / `run.failed`。平台动作执行等 EBA 和 platform API 权限落地后再启用。 ### 5.6 AgentRunAPIProxy Proxy 是 runner 访问 host 能力的唯一入口: - model APIs - tool APIs - knowledge APIs - state / storage APIs - history / event APIs - artifact APIs - platform APIs 所有请求必须带 `run_id`,host 侧按 active run session 验证 runner identity 和 resource ACL。 ## 6. 当前实现与目标差距 已落地: - `AgentRunnerRegistry` - `AgentRunOrchestrator` - `AgentRunContextBuilder` - `AgentResourceBuilder` - `AgentRunSessionRegistry` - `AgentRunAPIProxy` 基础模型 / 工具 / 知识库授权路径 需要调整: - 把 `pipeline_config` 语义抽象为 `AgentBinding`。 - 把 `Query` 输入抽象为 `AgentEventEnvelope`。 - 把 legacy `max-round` 从目标设计中移除,只作为旧配置兼容处理。 - 把 state store 改为持久 host storage backend。 - 增加 EventLog / Transcript / ArtifactStore。 - 增加 history / artifact / event 的受限拉取 API。 ## 7. 落地顺序 1. 固化 README 路由和专题文档边界。 2. 在 Host 中抽象 `AgentBinding`,先由 Pipeline adapter 生成。 3. 将 `AgentRunContextBuilder` 改为 event-first。 4. 增加持久 transcript/event log 的最小存储模型。 5. 扩展 `AgentRunAPIProxy` 的 history / artifact / state API。 6. 将 Pipeline-only 字段逐步下沉到兼容 adapter。 7. 再设计官方 local-agent 插件如何消费这些基础设施。