mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-04 21:06:03 +00:00
365 lines
10 KiB
Markdown
365 lines
10 KiB
Markdown
# 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 插件如何消费这些基础设施。
|