跳转到内容

配置停止策略

当你需要根据轮数、token 用量、耗时或连续错误来决定 agent run 何时终止时,使用本页。

  • 已添加 awaken
  • 了解 PluginAgentRuntimeBuilder

stop policy 会在每次推理步骤结束后判断 run 是否继续。内置策略包括:

策略触发条件
MaxRoundsPolicy步数超过上限
TokenBudgetPolicy输入+输出 token 超过预算
TimeoutPolicy墙钟时间超过上限
ConsecutiveErrorsPolicy连续推理错误达到阈值
  1. 以编程方式构造策略:
use std::sync::Arc;
use awaken::policies::{
MaxRoundsPolicy, TokenBudgetPolicy, TimeoutPolicy,
ConsecutiveErrorsPolicy, StopPolicy,
};
let policies: Vec<Arc<dyn StopPolicy>> = vec![
Arc::new(MaxRoundsPolicy::new(25)),
Arc::new(TokenBudgetPolicy::new(100_000)),
Arc::new(TimeoutPolicy::new(300_000)),
Arc::new(ConsecutiveErrorsPolicy::new(3)),
];
  1. StopConditionPlugin 注册到 runtime:
use std::sync::Arc;
use awaken::policies::StopConditionPlugin;
use awaken::engine::GenaiExecutor;
use awaken::registry_spec::ModelSpec;
use awaken::AgentRuntimeBuilder;
let mut spec = spec;
spec.plugin_ids.push("stop-condition".into());
let runtime = AgentRuntimeBuilder::new()
.with_plugin("stop-condition", Arc::new(StopConditionPlugin::new(policies)))
.with_agent_spec(spec)
.with_provider("anthropic", Arc::new(GenaiExecutor::new()))
.with_model(ModelSpec::new("claude-sonnet", "anthropic", "claude-sonnet-4-20250514"))
.build()?;

如果只需要限制轮数,也可以直接用 MaxRoundsPlugin

use std::sync::Arc;
use awaken::policies::MaxRoundsPlugin;
use awaken::engine::GenaiExecutor;
use awaken::registry_spec::ModelSpec;
use awaken::AgentRuntimeBuilder;
let mut spec = spec;
spec.plugin_ids.push("stop-condition:max-rounds".into());
let runtime = AgentRuntimeBuilder::new()
.with_plugin("stop-condition:max-rounds", Arc::new(MaxRoundsPlugin::new(10)))
.with_agent_spec(spec)
.with_provider("anthropic", Arc::new(GenaiExecutor::new()))
.with_model(ModelSpec::new("claude-sonnet", "anthropic", "claude-sonnet-4-20250514"))
.build()?;

自定义 stop-condition 插件必须列在 AgentSpec.plugin_ids 中。内置 AgentSpec.max_rounds 保护仍会自动注入;只有需要额外 policy 类型时才使用这些 插件。

  1. 用声明式 StopConditionSpec
use awaken::contract::lifecycle::StopConditionSpec;
use awaken::policies::{policies_from_specs, StopConditionPlugin};
let specs = vec![
StopConditionSpec::MaxRounds { rounds: 10 },
StopConditionSpec::Timeout { seconds: 300 },
StopConditionSpec::TokenBudget { max_total: 100_000 },
StopConditionSpec::ConsecutiveErrors { max: 3 },
];
let policies = policies_from_specs(&specs);
let plugin = StopConditionPlugin::new(policies);

StopConditionSpec 的所有变体都已由 policies_from_specs 转换为运行时策略;无效的 ContentMatch 正则会 fail-closed,以 content_match_invalid_regex 停止。

你也可以实现自定义策略:

use awaken::policies::{StopPolicy, StopDecision, StopPolicyStats};
pub struct MyCustomPolicy {
pub threshold: u64,
}
impl StopPolicy for MyCustomPolicy {
fn id(&self) -> &str {
"my_custom"
}
fn evaluate(&self, stats: &StopPolicyStats) -> StopDecision {
if stats.total_output_tokens > self.threshold {
StopDecision::Stop {
code: "my_custom".into(),
detail: format!("output tokens {} exceeded {}", stats.total_output_tokens, self.threshold),
}
} else {
StopDecision::Continue
}
}
}

内置 StopConditionHook 会为每次评估准备一份 StopPolicyStats

字段类型说明
step_countu32已完成推理步数
total_input_tokensu64累计输入 token
total_output_tokensu64累计输出 token
elapsed_msu64从第一步开始经过的毫秒数
consecutive_errorsu32连续推理错误计数
last_tool_namesVec<String>最近一轮里调用的工具名
last_response_textString最近一次推理返回的文本
pub enum StopDecision {
Continue,
Stop { code: String, detail: String },
}

任何一个 policy 返回 Stop,该 run 就会以 TerminationReason::Stopped 结束。

  1. StopConditionPluginPhase::AfterInference 注册 hook
  2. 每轮推理结束后,hook 会更新统计状态
  3. 构造 StopPolicyStats
  4. 依次调用每个策略的 evaluate
  5. 如果有策略返回 Stop,则写入 RunLifecycleUpdate::Done

maxmax_total 设为 0 的策略视为禁用,始终返回 Continue

错误原因修复
run 永远不结束没注册 stop policy,LLM 一直在调工具至少加一个 MaxRoundsPolicy
StateError::KeyAlreadyRegistered同时注册了 StopConditionPluginMaxRoundsPlugin二选一
Timeout 提前触发TimeoutPolicy::new() 传的是毫秒,StopConditionSpec::Timeout 是秒注意单位
  • crates/awaken-runtime/src/policies/mod.rs
  • crates/awaken-runtime/src/policies/policy.rs
  • crates/awaken-runtime/src/policies/plugin.rs
  • crates/awaken-runtime/src/policies/state.rs
  • crates/awaken-runtime/src/policies/hook.rs
  • crates/awaken-runtime-contract/src/contract/lifecycle.rs