mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-27 16:04:21 +00:00
docs(agent-runner): split protocol and context design
This commit is contained in:
@@ -0,0 +1,364 @@
|
||||
# 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 插件如何消费这些基础设施。
|
||||
Reference in New Issue
Block a user