agent_works/guard/config.rs
1/// Reasoning-only handling strategy
2#[derive(Debug, Clone, Default)]
3pub enum ReasoningOnlyAction {
4 /// Default: fail after N nudges
5 #[default]
6 Fail,
7 /// New: disable thinking after N nudges, continue running
8 DisableThinking,
9}
10
11/// Default guard configuration
12pub struct DefaultGuardConfig {
13 // ─── reasoning-only configuration ─────────────────────────
14 /// Maximum retries for reasoning-only responses
15 pub reasoning_only_max_strikes: usize,
16 /// Nudge message for reasoning-only responses
17 pub reasoning_only_nudge: String,
18 /// Reasoning-only handling strategy
19 pub reasoning_only_action: ReasoningOnlyAction,
20
21 // ─── thinking guard configuration (for DisableThinking strategy) ──
22 /// Nudge message when disabling thinking
23 pub disable_thinking_nudge: String,
24
25 // ─── empty-response configuration ─────────────────────────
26 /// Maximum retries for empty responses
27 pub empty_response_max_strikes: usize,
28 /// Nudge message for empty responses
29 pub empty_response_nudge: String,
30
31 // ─── text-only configuration ─────────────────────────────
32 /// Whether to use LLM judge for text-only after tools
33 pub use_llm_judge: bool,
34 /// Timeout in seconds for the LLM judge call
35 pub judge_timeout_secs: u64,
36 /// Skip judge if response is longer than this (likely complete)
37 pub judge_skip_threshold: usize,
38 /// Whether to trust LLM when judge fails or times out.
39 /// - true: fail-open (trust the model, end loop)
40 /// - false: fail-closed (don't trust, force continue)
41 pub judge_fail_open: bool,
42 /// Enable short-response detection (merged from CompletionGateMiddleware).
43 /// When the user input is long but the model response is very short,
44 /// treat it as potentially incomplete and nudge/judge accordingly.
45 pub detect_short_response: bool,
46 /// Minimum user input character count to trigger short-response detection.
47 pub short_response_min_input: usize,
48 /// Maximum LLM output character count to be considered a short response.
49 pub short_response_max_output: usize,
50 /// Nudge message for short responses
51 pub short_response_nudge: String,
52 /// Number of recent user messages to include in the judge prompt.
53 /// Helps the judge understand context like "继续" after a multi-turn discussion.
54 pub recent_user_count: usize,
55}
56
57impl Default for DefaultGuardConfig {
58 fn default() -> Self {
59 Self {
60 // reasoning-only
61 reasoning_only_max_strikes: 3,
62 reasoning_only_nudge: "You produced internal reasoning but no tool call \
63 and no final answer. Make a decision now: call a tool to make progress, \
64 or write your final answer as plain text."
65 .to_string(),
66 reasoning_only_action: ReasoningOnlyAction::Fail,
67
68 // thinking guard
69 disable_thinking_nudge: "Thinking has been disabled due to excessive reasoning. \
70 You MUST now either call a tool or write your final answer. \
71 Do NOT attempt to reason further."
72 .to_string(),
73
74 // empty-response
75 empty_response_max_strikes: 3,
76 empty_response_nudge: "Your response was empty. Please provide a response \
77 with either a tool call or your final answer."
78 .to_string(),
79
80 // text-only
81 use_llm_judge: true,
82 judge_timeout_secs: 10,
83 judge_skip_threshold: 256,
84 judge_fail_open: false, // Default: don't trust LLM on judge failure
85 detect_short_response: true,
86 short_response_min_input: 128,
87 short_response_max_output: 64,
88 short_response_nudge: "Your response may be incomplete — \
89 you may need to continue."
90 .to_string(),
91 recent_user_count: 5,
92 }
93 }
94}