Skip to main content

agent_brain/
agent_brain.rs

1//! A tiny decision brain: an assistant deciding what to do with a request.
2//!
3//! It shows the pieces working together — graded considerations, a hard
4//! constraint via `gate`, abstaining via `decide_above`, and an explanation.
5//! Run with: `cargo run -p reliakit-decide --example agent_brain`
6
7use reliakit_decide::{Action, Curve, Reasoner, Score};
8
9fn main() {
10    // Signals about the current request, each normalized to 0.0..=1.0.
11    let urgency = Score::from_ratio(80, 100);
12    let confidence = Score::from_ratio(40, 100); // how well we already understand it
13    let llm_available = true; // e.g. circuit breaker closed AND rate limiter has tokens
14
15    let mut brain = Reasoner::new();
16
17    // Answer from a template — strong when we are already confident.
18    brain.add(Action::new("answer_template").consider_labeled(
19        "confidence",
20        Curve::Linear,
21        confidence,
22    ));
23
24    // Escalate to the LLM — strong when urgent, but only if the LLM is available.
25    brain.add(
26        Action::new("call_llm")
27            .gate(llm_available) // constraint-aware: skipped entirely if the LLM is down/limited
28            .consider_labeled("urgency", Curve::Linear, urgency),
29    );
30
31    // An always-available, low-weight fallback so a decision still resolves.
32    brain.add(Action::new("defer").with_base(Score::from_ratio(1, 10)));
33
34    // Abstain if nothing clears the bar — the caller would escalate to a human.
35    let threshold = Score::from_ratio(5, 100);
36    match brain.decide_above(threshold) {
37        Some(decision) => {
38            println!(
39                "chose: {} (utility {}/10000)",
40                decision.id,
41                decision.utility.raw()
42            );
43            if let Some(why) = brain.explain() {
44                for c in why.contributions {
45                    println!(
46                        "  {} : input {} -> {}",
47                        c.label,
48                        c.input.raw(),
49                        c.output.raw()
50                    );
51                }
52            }
53        }
54        None => println!("nothing good enough — escalate to a human"),
55    }
56}