14.5 三层多智能体编排模型
RAF 宿主服务采用三层编排架构,将 ACP 协议的会话管理、RAF 的多 Agent 执行和客户端的流式渲染清晰地分层解耦。
三层架构
graph TB
subgraph "第 1 层:ACP 会话层"
CLIENT[ACP 客户端]
SESSION[ACP SessionId]
NEW[session/new]
PROMPT[session/prompt]
end
subgraph "第 2 层:SessionBridge 映射层"
SB[SessionBridge]
CTX[SessionContext]
CT[CancelToken]
end
subgraph "第 3 层:RAF 执行层"
RAF_SESSION[AgentSession]
AGENT1[Agent A]
AGENT2[Agent B]
WORKFLOW[Workflow Engine]
end
CLIENT --> SESSION
SESSION --> SB
SB --> CTX
CTX --> RAF_SESSION
CTX --> CT
RAF_SESSION --> AGENT1
RAF_SESSION --> AGENT2
RAF_SESSION --> WORKFLOW
第 1 层:ACP 会话层
客户端通过 ACP 协议与宿主通信:
// 1. 创建会话(指定目标 Agent)
{
"method": "session/new",
"params": {
"_meta": { "raf": { "agent_id": "coding_workflow" } }
}
}
// 2. 发送提示
{
"method": "session/prompt",
"params": {
"session_id": "abc-123",
"messages": [{"role": "user", "content": "请审查这段代码"}]
}
}
// 3. 取消(可选)
{
"method": "session/cancel",
"params": {
"session_id": "abc-123"
}
}
第 2 层:SessionBridge 映射层
`SessionBridge` 负责 ACP 会话与 RAF 会话之间的映射:
pub struct SessionBridge {
sessions: RwLock<HashMap<String, SessionContext>>,
}
pub struct SessionContext {
pub raf_session: Arc<AgentSession>, // RAF 会话
pub target_agent_id: String, // 目标 Agent ID
pub cancel_token: Option<Arc<AtomicBool>>, // 取消令牌
}
会话生命周期
sequenceDiagram
participant C as ACP 客户端
participant SB as SessionBridge
participant AS as AgentSession
participant AG as Agent
C->>SB: create_session(id, target_agent)
SB->>AS: new AgentSession
SB->>SB: 存储 SessionContext
C->>SB: get_or_create_raf_session(id)
SB-->>C: Arc<AgentSession>
C->>SB: register_cancel_token(id, token)
SB->>SB: 更新 cancel_token
C->>SB: cancel_session(id)
SB->>SB: token.store(true)
C->>SB: clear_cancel_token(id)
SB->>SB: cancel_token = None
会话操作
| 操作 | 方法 | 说明 | |------|------|------| | 创建会话 | `create_session(id, target)` | 创建 AgentSession 并存储 | | 获取会话 | `get_or_create_raf_session(id)` | 获取或按需创建 | | 取消会话 | `cancel_session(id)` | 设置 cancel_token = true | | 注册令牌 | `register_cancel_token(id, token)` | 注册本轮取消令牌 | | 清除令牌 | `clear_cancel_token(id)` | 轮次完成后清理 | | 移除会话 | `remove_session(id)` | 删除会话记录 |
第 3 层:RAF 执行层
RAF Agent 通过 `IAgent::run()` 执行,使用 `AgentSession` 维护对话历史:
// 提示处理流程
async fn handle_prompt(
req: PromptRequest,
registry: &AgentRegistry,
bridge: &SessionBridge,
) {
// 1. 解析目标 Agent
let target_agent = bridge.get_target_agent_id(&req.session_id).await;
let agent = registry.resolve_agent(target_agent.as_deref()).unwrap();
// 2. 获取或创建 RAF 会话
let raf_session = bridge.get_or_create_raf_session(&req.session_id).await?;
// 3. 创建取消令牌
let cancel_token = Arc::new(AtomicBool::new(false));
bridge.register_cancel_token(&req.session_id, cancel_token.clone()).await;
// 4. 映射选项
let options = map_acp_options_to_agent_options(&req);
// 5. 运行 Agent
let stream = agent.run(
req.messages,
Some(raf_session),
options,
).await?;
// 6. 处理流式输出,发送 session/update
// 7. 完成后清理取消令牌
}
独立子 Agent 会话
客户端可以为每个子 Agent 创建独立的 ACP 会话,实现并行流式视图:
graph LR
subgraph "客户端"
VIEW1[代码专家视图]
VIEW2[审查员视图]
VIEW3[测试员视图]
end
subgraph "ACP 会话"
S1[session-1 → coding]
S2[session-2 → reviewer]
S3[session-3 → tester]
end
subgraph "RAF"
WF[WorkflowAsAgent]
A1[CodingAgent]
A2[ReviewerAgent]
A3[TesterAgent]
end
WF --> A1
WF --> A2
WF --> A3
S1 --> A1
S2 --> A2
S3 --> A3
VIEW1 --> S1
VIEW2 --> S2
VIEW3 --> S3
独立会话创建
// 父会话(执行编排)
{"method": "session/new", "params": {"_meta": {"raf": {"agent_id": "seq_workflow"}}}}
// 子 Agent 独立会话(用于前端渲染各自的流式视图)
{"method": "session/new", "params": {"_meta": {"raf": {"agent_id": "coding"}}}}
{"method": "session/new", "params": {"_meta": {"raf": {"agent_id": "reviewer"}}}}
{"method": "session/new", "params": {"_meta": {"raf": {"agent_id": "tester"}}}}
提示处理流程
// 完整的 session/prompt 处理
async fn handle_prompt(
req: PromptRequest,
responder: impl Responder,
conn: ConnectionTo<Client>,
registry: &AgentRegistry,
bridge: &SessionBridge,
) {
// 1. 解析 Agent
let target_id = bridge.get_target_agent_id(&req.session_id).await;
let agent = registry.resolve_agent(target_id.as_deref())
.unwrap_or_else(|| registry.get_default().cloned().unwrap());
// 2. 准备会话
let raf_session = bridge.get_or_create_raf_session(&req.session_id).await?;
let cancel_token = Arc::new(AtomicBool::new(false));
bridge.register_cancel_token(&req.session_id, cancel_token).await;
// 3. 映射选项
let options = extract_run_options(&req);
// 4. 添加历史消息
let history = raf_session.messages().await;
let all_messages = if history.is_empty() {
req.messages
} else {
let mut msgs = history;
msgs.extend(req.messages);
msgs
};
// 5. 运行 Agent
let stream = agent.run(all_messages, Some(raf_session.clone()), options).await?;
// 6. 发送流式更新
tokio::pin!(stream);
while let Some(chunk) = stream.next().await {
// 检查取消
if cancel_token.load(Ordering::SeqCst) {
break;
}
let update = chunk_to_session_update(chunk, &agent);
conn.send_notification(update).await?;
}
// 7. 保存消息到会话
raf_session.add_messages(final_messages).await?;
// 8. 清理
bridge.clear_cancel_token(&req.session_id).await;
}