使用 Agent Handoff
当你需要在同一个 run、同一条 thread 内,动态切换 agent 的 system prompt、model 或工具集,而不终止 run 时,使用本页。
前置条件
- 已添加
awaken - 了解
Plugin、StateKey和AgentRuntimeBuilder
概览
handoff 的核心不是启动一个全新 agent run,而是在当前 run 内应用 AgentOverlay,覆盖基础 agent 的一部分配置。
关键类型:
HandoffPluginAgentOverlayHandoffStateHandoffAction
步骤
- 定义 overlay:
use awaken::extensions::handoff::AgentOverlay;
let researcher = AgentOverlay {
system_prompt: Some("You are a research specialist. Find and cite sources.".into()),
model: Some("claude-sonnet".into()),
allowed_tools: Some(vec!["web_search".into(), "read_document".into()]),
excluded_tools: None,
};
let writer = AgentOverlay {
system_prompt: Some("You are a technical writer. Produce clear documentation.".into()),
model: None,
allowed_tools: None,
excluded_tools: Some(vec!["web_search".into()]),
};
model 字段使用的也是模型注册表 ID。
- 用 overlays 构建
HandoffPlugin:
use std::collections::HashMap;
use awaken::extensions::handoff::HandoffPlugin;
let mut overlays = HashMap::new();
overlays.insert("researcher".to_string(), researcher);
overlays.insert("writer".to_string(), writer);
let handoff = HandoffPlugin::new(overlays);
- 把插件注册进 runtime:
use std::sync::Arc;
use awaken::AgentRuntimeBuilder;
let runtime = AgentRuntimeBuilder::new()
.with_plugin("agent_handoff", Arc::new(handoff))
.with_agent_spec(spec)
.with_provider("anthropic", Arc::new(provider))
.build()?;
- 在 tool 或 hook 中请求 handoff:
use awaken::extensions::handoff::{request_handoff, activate_handoff, clear_handoff, ActiveAgentKey};
use awaken::state::StateCommand;
let mut cmd = StateCommand::new();
cmd.update::<ActiveAgentKey>(request_handoff("researcher"));
let mut cmd = StateCommand::new();
cmd.update::<ActiveAgentKey>(activate_handoff("writer"));
let mut cmd = StateCommand::new();
cmd.update::<ActiveAgentKey>(clear_handoff());
- 从插件状态里读取 overlay:
let overlay = handoff.overlay("researcher");
它是如何工作的
HandoffState 有两部分:
active_agentrequested_agent
内部同步 hook 会在 RunStart 和 StepEnd 检测 requested_agent,并在安全边界上把它提升为 active_agent。
Handoff vs Delegation
| Handoff | Delegation | |
|---|---|---|
| Thread | 同一 thread、同一 run | 通常会产生子 agent 执行上下文 |
| 状态 | 共享,原地覆盖 | 一般隔离 |
| 适用场景 | 切换角色、人设或工具集 | 拆分独立子任务 |
| 开销 | 很低 | 更高 |
常见错误
| 错误 | 原因 | 修复 |
|---|---|---|
| overlay 没生效 | request_handoff 的名字和 overlays map 不一致 | 保证字符串完全一致 |
StateError::KeyAlreadyRegistered | 其他插件也注册了 ActiveAgentKey | 每个 runtime 只保留一个 HandoffPlugin |
| hook 没有执行 | 插件未激活 | 把 "agent_handoff" 加到 hook filter |
关键文件
crates/awaken-runtime/src/extensions/handoff/mod.rscrates/awaken-runtime/src/extensions/handoff/plugin.rscrates/awaken-runtime/src/extensions/handoff/types.rscrates/awaken-runtime/src/extensions/handoff/state.rscrates/awaken-runtime/src/extensions/handoff/action.rs