Skip to main content

Client

Struct Client 

Source
pub struct Client {
    pub auth: AuthClient,
    pub core: CoreClient,
    pub control: ControlClient,
    /* private fields */
}

Fields§

§auth: AuthClient§core: CoreClient§control: ControlClient

Implementations§

Source§

impl Client

Source

pub fn new(config: ClientConfig) -> Result<Self>

Examples found in repository?
examples/support/utils.rs (line 78)
60pub async fn create_client() -> Result<Client, Box<dyn Error>> {
61    let endpoint =
62        env::var("MUBIT_ENDPOINT").unwrap_or_else(|_| "http://127.0.0.1:3000".to_string());
63    let grpc_endpoint =
64        env::var("MUBIT_GRPC_ENDPOINT").unwrap_or_else(|_| "127.0.0.1:50051".to_string());
65    let timeout_ms = env::var("MUBIT_TIMEOUT_MS")
66        .ok()
67        .and_then(|raw| raw.parse::<u64>().ok())
68        .unwrap_or(30_000);
69
70    let api_key =
71        env::var("MUBIT_API_KEY").map_err(|_| boxed_error("MUBIT_API_KEY must be set"))?;
72
73    let mut cfg = ClientConfig::new(endpoint).transport("http");
74    cfg.grpc_endpoint = Some(grpc_endpoint);
75    cfg.timeout_ms = timeout_ms;
76    cfg.api_key = Some(api_key.clone());
77
78    let client = Client::new(cfg)?;
79    client.set_transport(TransportMode::Http);
80    client.set_api_key(Some(api_key));
81
82    let _ = client.auth.health().await?;
83
84    Ok(client)
85}
Source

pub fn set_api_key(&self, api_key: Option<String>)

Examples found in repository?
examples/support/utils.rs (line 80)
60pub async fn create_client() -> Result<Client, Box<dyn Error>> {
61    let endpoint =
62        env::var("MUBIT_ENDPOINT").unwrap_or_else(|_| "http://127.0.0.1:3000".to_string());
63    let grpc_endpoint =
64        env::var("MUBIT_GRPC_ENDPOINT").unwrap_or_else(|_| "127.0.0.1:50051".to_string());
65    let timeout_ms = env::var("MUBIT_TIMEOUT_MS")
66        .ok()
67        .and_then(|raw| raw.parse::<u64>().ok())
68        .unwrap_or(30_000);
69
70    let api_key =
71        env::var("MUBIT_API_KEY").map_err(|_| boxed_error("MUBIT_API_KEY must be set"))?;
72
73    let mut cfg = ClientConfig::new(endpoint).transport("http");
74    cfg.grpc_endpoint = Some(grpc_endpoint);
75    cfg.timeout_ms = timeout_ms;
76    cfg.api_key = Some(api_key.clone());
77
78    let client = Client::new(cfg)?;
79    client.set_transport(TransportMode::Http);
80    client.set_api_key(Some(api_key));
81
82    let _ = client.auth.health().await?;
83
84    Ok(client)
85}
Source

pub fn set_token(&self, token: Option<String>)

Source

pub fn set_run_id(&self, run_id: Option<String>)

Examples found in repository?
examples/control_query_direct_bypass_matrix.rs (line 78)
72async fn main() -> Result<(), Box<dyn Error>> {
73    let name = "control_query_direct_bypass_matrix";
74    let started = Instant::now();
75    let config = ScenarioConfig::from_env();
76    let client = create_client().await?;
77    let run_id = new_run_id("control_query_direct_bypass");
78    client.set_run_id(Some(run_id.clone()));
79    client.set_transport(TransportMode::Http);
80
81    let mut passed = true;
82    let mut detail = "validated control query direct bypass semantic lane".to_string();
83    let mut metrics = json!({});
84
85    let scenario = async {
86        let semantic = run_lane(
87            &client,
88            &run_id,
89            "semantic direct bypass probe",
90            config.expect_direct_search_enabled,
91        )
92        .await?;
93
94        metrics = json!({
95            "run_id": run_id,
96            "expect_direct_search_enabled": config.expect_direct_search_enabled,
97            "semantic": semantic,
98        });
99
100        Ok::<(), Box<dyn Error>>(())
101    }
102    .await;
103
104    if let Err(err) = scenario {
105        passed = false;
106        detail = err.to_string();
107    }
108
109    let cleanup_ok = cleanup_run(&client, &run_id).await;
110    if !cleanup_ok {
111        passed = false;
112        detail = format!("{detail} | cleanup failures");
113    }
114
115    print_summary(
116        name,
117        passed,
118        &detail,
119        &metrics,
120        started.elapsed().as_secs_f64(),
121        cleanup_ok,
122    );
123
124    if passed { Ok(()) } else { Err(boxed_error(detail)) }
125}
More examples
Hide additional examples
examples/internal/goal_tree_and_goal_update.rs (line 16)
11async fn main() -> Result<(), Box<dyn Error>> {
12    let name = "internal_goal_tree_and_goal_update";
13    let started = Instant::now();
14    let client = create_client().await?;
15    let run_id = new_run_id("internal_goal_tree");
16    client.set_run_id(Some(run_id.clone()));
17    client.set_transport(TransportMode::Http);
18    let mut passed = true;
19    let mut detail = "validated raw goal tree lifecycle".to_string();
20    let mut metrics = json!({});
21
22    let scenario = async {
23        let parent = client.control.add_goal(json!({"run_id": run_id, "description": "Resolve claim", "priority": "high"})).await?;
24        let parent_id = parent.get("id").and_then(Value::as_str).ok_or_else(|| boxed_error(format!("add_goal parent failed: {parent}")))?.to_string();
25        let child = client.control.add_goal(json!({"run_id": run_id, "description": "Verify receipts", "priority": "medium", "parent_goal_id": parent_id})).await?;
26        let child_id = child.get("id").and_then(Value::as_str).ok_or_else(|| boxed_error(format!("add_goal child failed: {child}")))?.to_string();
27        let updated = client.control.update_goal(json!({"run_id": run_id, "goal_id": child_id, "status": "achieved"})).await?;
28        let listed = client.control.list_goals(json!({"run_id": run_id})).await?;
29        let tree = client.control.get_goal_tree(json!({"run_id": run_id, "root_goal_id": parent_id})).await?;
30        require(updated.get("success").and_then(Value::as_bool).unwrap_or(true), format!("update_goal failed: {updated}"))?;
31        require(listed.get("goals").and_then(|v| v.as_array()).map(|items| items.iter().any(|item| item.get("id").and_then(|v| v.as_str()) == Some(child_id.as_str()))).unwrap_or(false), format!("list_goals missing child: {listed}"))?;
32        require(tree.get("goals").is_some() || tree.get("root").is_some() || tree.get("nodes").is_some(), format!("goal tree malformed: {tree}"))?;
33        metrics = json!({"run_id": run_id, "parent_goal_id": parent_id, "child_goal_id": child_id});
34        Ok::<(), Box<dyn Error>>(())
35    }.await;
36
37    if let Err(err) = scenario { passed = false; detail = err.to_string(); }
38    let cleanup_ok = cleanup_run(&client, &run_id).await;
39    if !cleanup_ok { passed = false; detail = format!("{detail} | cleanup failures"); }
40    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
41    if passed { Ok(()) } else { Err(boxed_error(detail)) }
42}
examples/core_direct_search_optional.rs (line 31)
25async fn main() -> Result<(), Box<dyn Error>> {
26    let name = "core_direct_search_optional";
27    let started = Instant::now();
28    let config = ScenarioConfig::from_env();
29    let client = create_client().await?;
30    let run_id = new_run_id("core_direct_search_optional");
31    client.set_run_id(Some(run_id.clone()));
32    client.set_transport(TransportMode::Http);
33
34    let mut passed = true;
35    let mut detail = "validated optional core direct-search".to_string();
36    let mut metrics = json!({});
37
38    let scenario = async {
39        match client
40            .core
41            .search(json!({
42                "query": "direct core semantic search probe",
43                "k": 5,
44            }))
45            .await
46        {
47            Ok(payload) => {
48                require(
49                    payload.is_array() || payload.is_object(),
50                    format!("core.search payload must be dict/list: {payload}"),
51                )?;
52
53                metrics = json!({
54                    "run_id": run_id,
55                    "enabled": true,
56                    "result_count": extract_result_count(&payload),
57                });
58                detail = "validated optional core direct-search (enabled)".to_string();
59            }
60            Err(err) => {
61                if config.expect_direct_search_enabled {
62                    return Err(boxed_error(format!(
63                        "core.search expected enabled but failed: {err}"
64                    )));
65                }
66                let message = err.to_string();
67                require(
68                    is_permission_denied_like(&message),
69                    format!(
70                        "core.search should fail with permission denied when disabled: {message}"
71                    ),
72                )?;
73
74                metrics = json!({
75                    "run_id": run_id,
76                    "enabled": false,
77                    "message": message,
78                });
79                detail = "validated optional core direct-search (disabled)".to_string();
80            }
81        }
82
83        Ok::<(), Box<dyn Error>>(())
84    }
85    .await;
86
87    if let Err(err) = scenario {
88        passed = false;
89        detail = err.to_string();
90    }
91
92    let cleanup_ok = cleanup_run(&client, &run_id).await;
93    if !cleanup_ok {
94        passed = false;
95        detail = format!("{detail} | cleanup failures");
96    }
97
98    print_summary(
99        name,
100        passed,
101        &detail,
102        &metrics,
103        started.elapsed().as_secs_f64(),
104        cleanup_ok,
105    );
106
107    if passed {
108        Ok(())
109    } else {
110        Err(boxed_error(detail))
111    }
112}
examples/internal/core_direct_search.rs (line 31)
25async fn main() -> Result<(), Box<dyn Error>> {
26    let name = "internal_core_direct_search";
27    let started = Instant::now();
28    let config = ScenarioConfig::from_env();
29    let client = create_client().await?;
30    let run_id = new_run_id("internal_core_direct_search");
31    client.set_run_id(Some(run_id.clone()));
32    client.set_transport(TransportMode::Http);
33
34    let mut passed = true;
35    let mut detail = "validated optional core direct-search".to_string();
36    let mut metrics = json!({});
37
38    let scenario = async {
39        match client
40            .core
41            .search(json!({
42                "query": "direct core semantic search probe",
43                "k": 5,
44            }))
45            .await
46        {
47            Ok(payload) => {
48                require(
49                    payload.is_array() || payload.is_object(),
50                    format!("core.search payload must be dict/list: {payload}"),
51                )?;
52
53                metrics = json!({
54                    "run_id": run_id,
55                    "enabled": true,
56                    "result_count": extract_result_count(&payload),
57                });
58                detail = "validated optional core direct-search (enabled)".to_string();
59            }
60            Err(err) => {
61                if config.expect_direct_search_enabled {
62                    return Err(boxed_error(format!(
63                        "core.search expected enabled but failed: {err}"
64                    )));
65                }
66                let message = err.to_string();
67                require(
68                    is_permission_denied_like(&message),
69                    format!(
70                        "core.search should fail with permission denied when disabled: {message}"
71                    ),
72                )?;
73
74                metrics = json!({
75                    "run_id": run_id,
76                    "enabled": false,
77                    "message": message,
78                });
79                detail = "validated optional core direct-search (disabled)".to_string();
80            }
81        }
82
83        Ok::<(), Box<dyn Error>>(())
84    }
85    .await;
86
87    if let Err(err) = scenario {
88        passed = false;
89        detail = err.to_string();
90    }
91
92    let cleanup_ok = cleanup_run(&client, &run_id).await;
93    if !cleanup_ok {
94        passed = false;
95        detail = format!("{detail} | cleanup failures");
96    }
97
98    print_summary(
99        name,
100        passed,
101        &detail,
102        &metrics,
103        started.elapsed().as_secs_f64(),
104        cleanup_ok,
105    );
106
107    if passed {
108        Ok(())
109    } else {
110        Err(boxed_error(detail))
111    }
112}
examples/internal/lessons_lifecycle.rs (line 17)
12async fn main() -> Result<(), Box<dyn Error>> {
13    let name = "internal_lessons_lifecycle";
14    let started = Instant::now();
15    let client = create_client().await?;
16    let run_id = new_run_id("internal_lessons_lifecycle");
17    client.set_run_id(Some(run_id.clone()));
18    client.set_transport(TransportMode::Http);
19    let mut passed = true;
20    let mut detail = "validated raw lessons lifecycle".to_string();
21    let mut metrics = json!({});
22
23    let scenario = async {
24        let mut remember = RememberOptions::new("Always verify the stored deductible before approving reimbursement.");
25        remember.run_id = Some(run_id.clone());
26        remember.intent = Some("lesson".into());
27        remember.lesson_type = Some("success".into());
28        remember.lesson_scope = Some("session".into());
29        client.remember(remember).await?;
30
31        let mut lessons = serde_json::Value::Null;
32        for _ in 0..24 {
33            let current = client
34                .control
35                .lessons(json!({"run_id": run_id, "limit": 10}))
36                .await?;
37            let has_lesson = current
38                .get("lessons")
39                .and_then(|v| v.as_array())
40                .map(|items| !items.is_empty())
41                .unwrap_or(false);
42            lessons = current;
43            if has_lesson {
44                break;
45            }
46            sleep(Duration::from_millis(500)).await;
47        }
48        let lesson_id = lessons.get("lessons").and_then(|v| v.as_array()).and_then(|items| items.iter().find_map(|item| item.get("id").and_then(|v| v.as_str()))).ok_or_else(|| boxed_error(format!("expected lesson in lifecycle test: {lessons}")))?.to_string();
49        let deleted = client.control.delete_lesson(json!({"lesson_id": lesson_id})).await?;
50        let remaining = client.control.lessons(json!({"run_id": run_id, "limit": 10})).await?;
51        require(deleted.get("success").and_then(Value::as_bool).unwrap_or(true), format!("delete_lesson failed: {deleted}"))?;
52        require(!remaining.get("lessons").and_then(|v| v.as_array()).map(|items| items.iter().any(|item| item.get("id").and_then(|v| v.as_str()) == Some(lesson_id.as_str()))).unwrap_or(false), format!("lesson still present after delete: {remaining}"))?;
53        metrics = json!({"run_id": run_id, "lesson_id": lesson_id});
54        Ok::<(), Box<dyn Error>>(())
55    }.await;
56
57    if let Err(err) = scenario { passed = false; detail = err.to_string(); }
58    let cleanup_ok = cleanup_run(&client, &run_id).await;
59    if !cleanup_ok { passed = false; detail = format!("{detail} | cleanup failures"); }
60    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
61    if passed { Ok(()) } else { Err(boxed_error(detail)) }
62}
examples/helper_remember_recall.rs (line 16)
11async fn main() -> Result<(), Box<dyn Error>> {
12    let name = "helper_remember_recall";
13    let started = Instant::now();
14    let client = create_client().await?;
15    let run_id = new_run_id("helper_remember_recall");
16    client.set_run_id(Some(run_id.clone()));
17    client.set_transport(TransportMode::Http);
18
19    let mut passed = true;
20    let mut detail = "validated helper remember -> recall flow".to_string();
21    let mut metrics = json!({});
22
23    let scenario = async {
24        let mut remember = RememberOptions::new(
25            "Before retrying cache rebuilds, verify the token signer has rotated cleanly.",
26        );
27        remember.run_id = Some(run_id.clone());
28        remember.agent_id = Some("helper-example".to_string());
29        remember.intent = Some("lesson".to_string());
30        remember.lesson_type = Some("success".to_string());
31        remember.lesson_scope = Some("session".to_string());
32        remember.metadata = Some(json!({ "source": "rust-helper-example" }));
33        remember.occurrence_time = Some(std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as i64 - 86400);
34
35        let remembered = client.remember(remember).await?;
36        require(
37            remembered
38                .get("done")
39                .and_then(|value| value.as_bool())
40                .unwrap_or(false),
41            format!("remember should wait for ingest completion: {remembered}"),
42        )?;
43
44        let mut recall = RecallOptions::new("What should I verify before retrying cache rebuilds?");
45        recall.run_id = Some(run_id.clone());
46        recall.entry_types = vec!["lesson".to_string(), "fact".to_string()];
47        let answer = client.recall(recall).await?;
48        let evidence = answer
49            .get("evidence")
50            .and_then(|value| value.as_array())
51            .ok_or_else(|| boxed_error(format!("evidence missing: {answer}")))?;
52        require(!evidence.is_empty(), format!("evidence missing: {answer}"))?;
53        require(
54            answer
55                .get("final_answer")
56                .and_then(|value| value.as_str())
57                .is_some(),
58            format!("final answer missing: {answer}"),
59        )?;
60
61        metrics = json!({
62            "run_id": run_id,
63            "evidence_count": evidence.len(),
64            "confidence": answer.get("confidence").cloned().unwrap_or(serde_json::Value::Null),
65        });
66
67        Ok::<(), Box<dyn Error>>(())
68    }
69    .await;
70
71    if let Err(err) = scenario {
72        passed = false;
73        detail = err.to_string();
74    }
75
76    let cleanup_ok = cleanup_run(&client, &run_id).await;
77    if !cleanup_ok {
78        passed = false;
79        detail = format!("{detail} | cleanup failures");
80    }
81
82    print_summary(
83        name,
84        passed,
85        &detail,
86        &metrics,
87        started.elapsed().as_secs_f64(),
88        cleanup_ok,
89    );
90
91    if passed {
92        Ok(())
93    } else {
94        Err(boxed_error(detail))
95    }
96}
Source

pub fn set_transport(&self, transport: TransportMode)

Examples found in repository?
examples/support/utils.rs (line 79)
60pub async fn create_client() -> Result<Client, Box<dyn Error>> {
61    let endpoint =
62        env::var("MUBIT_ENDPOINT").unwrap_or_else(|_| "http://127.0.0.1:3000".to_string());
63    let grpc_endpoint =
64        env::var("MUBIT_GRPC_ENDPOINT").unwrap_or_else(|_| "127.0.0.1:50051".to_string());
65    let timeout_ms = env::var("MUBIT_TIMEOUT_MS")
66        .ok()
67        .and_then(|raw| raw.parse::<u64>().ok())
68        .unwrap_or(30_000);
69
70    let api_key =
71        env::var("MUBIT_API_KEY").map_err(|_| boxed_error("MUBIT_API_KEY must be set"))?;
72
73    let mut cfg = ClientConfig::new(endpoint).transport("http");
74    cfg.grpc_endpoint = Some(grpc_endpoint);
75    cfg.timeout_ms = timeout_ms;
76    cfg.api_key = Some(api_key.clone());
77
78    let client = Client::new(cfg)?;
79    client.set_transport(TransportMode::Http);
80    client.set_api_key(Some(api_key));
81
82    let _ = client.auth.health().await?;
83
84    Ok(client)
85}
More examples
Hide additional examples
examples/control_query_direct_bypass_matrix.rs (line 79)
72async fn main() -> Result<(), Box<dyn Error>> {
73    let name = "control_query_direct_bypass_matrix";
74    let started = Instant::now();
75    let config = ScenarioConfig::from_env();
76    let client = create_client().await?;
77    let run_id = new_run_id("control_query_direct_bypass");
78    client.set_run_id(Some(run_id.clone()));
79    client.set_transport(TransportMode::Http);
80
81    let mut passed = true;
82    let mut detail = "validated control query direct bypass semantic lane".to_string();
83    let mut metrics = json!({});
84
85    let scenario = async {
86        let semantic = run_lane(
87            &client,
88            &run_id,
89            "semantic direct bypass probe",
90            config.expect_direct_search_enabled,
91        )
92        .await?;
93
94        metrics = json!({
95            "run_id": run_id,
96            "expect_direct_search_enabled": config.expect_direct_search_enabled,
97            "semantic": semantic,
98        });
99
100        Ok::<(), Box<dyn Error>>(())
101    }
102    .await;
103
104    if let Err(err) = scenario {
105        passed = false;
106        detail = err.to_string();
107    }
108
109    let cleanup_ok = cleanup_run(&client, &run_id).await;
110    if !cleanup_ok {
111        passed = false;
112        detail = format!("{detail} | cleanup failures");
113    }
114
115    print_summary(
116        name,
117        passed,
118        &detail,
119        &metrics,
120        started.elapsed().as_secs_f64(),
121        cleanup_ok,
122    );
123
124    if passed { Ok(()) } else { Err(boxed_error(detail)) }
125}
examples/internal/goal_tree_and_goal_update.rs (line 17)
11async fn main() -> Result<(), Box<dyn Error>> {
12    let name = "internal_goal_tree_and_goal_update";
13    let started = Instant::now();
14    let client = create_client().await?;
15    let run_id = new_run_id("internal_goal_tree");
16    client.set_run_id(Some(run_id.clone()));
17    client.set_transport(TransportMode::Http);
18    let mut passed = true;
19    let mut detail = "validated raw goal tree lifecycle".to_string();
20    let mut metrics = json!({});
21
22    let scenario = async {
23        let parent = client.control.add_goal(json!({"run_id": run_id, "description": "Resolve claim", "priority": "high"})).await?;
24        let parent_id = parent.get("id").and_then(Value::as_str).ok_or_else(|| boxed_error(format!("add_goal parent failed: {parent}")))?.to_string();
25        let child = client.control.add_goal(json!({"run_id": run_id, "description": "Verify receipts", "priority": "medium", "parent_goal_id": parent_id})).await?;
26        let child_id = child.get("id").and_then(Value::as_str).ok_or_else(|| boxed_error(format!("add_goal child failed: {child}")))?.to_string();
27        let updated = client.control.update_goal(json!({"run_id": run_id, "goal_id": child_id, "status": "achieved"})).await?;
28        let listed = client.control.list_goals(json!({"run_id": run_id})).await?;
29        let tree = client.control.get_goal_tree(json!({"run_id": run_id, "root_goal_id": parent_id})).await?;
30        require(updated.get("success").and_then(Value::as_bool).unwrap_or(true), format!("update_goal failed: {updated}"))?;
31        require(listed.get("goals").and_then(|v| v.as_array()).map(|items| items.iter().any(|item| item.get("id").and_then(|v| v.as_str()) == Some(child_id.as_str()))).unwrap_or(false), format!("list_goals missing child: {listed}"))?;
32        require(tree.get("goals").is_some() || tree.get("root").is_some() || tree.get("nodes").is_some(), format!("goal tree malformed: {tree}"))?;
33        metrics = json!({"run_id": run_id, "parent_goal_id": parent_id, "child_goal_id": child_id});
34        Ok::<(), Box<dyn Error>>(())
35    }.await;
36
37    if let Err(err) = scenario { passed = false; detail = err.to_string(); }
38    let cleanup_ok = cleanup_run(&client, &run_id).await;
39    if !cleanup_ok { passed = false; detail = format!("{detail} | cleanup failures"); }
40    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
41    if passed { Ok(()) } else { Err(boxed_error(detail)) }
42}
examples/core_direct_search_optional.rs (line 32)
25async fn main() -> Result<(), Box<dyn Error>> {
26    let name = "core_direct_search_optional";
27    let started = Instant::now();
28    let config = ScenarioConfig::from_env();
29    let client = create_client().await?;
30    let run_id = new_run_id("core_direct_search_optional");
31    client.set_run_id(Some(run_id.clone()));
32    client.set_transport(TransportMode::Http);
33
34    let mut passed = true;
35    let mut detail = "validated optional core direct-search".to_string();
36    let mut metrics = json!({});
37
38    let scenario = async {
39        match client
40            .core
41            .search(json!({
42                "query": "direct core semantic search probe",
43                "k": 5,
44            }))
45            .await
46        {
47            Ok(payload) => {
48                require(
49                    payload.is_array() || payload.is_object(),
50                    format!("core.search payload must be dict/list: {payload}"),
51                )?;
52
53                metrics = json!({
54                    "run_id": run_id,
55                    "enabled": true,
56                    "result_count": extract_result_count(&payload),
57                });
58                detail = "validated optional core direct-search (enabled)".to_string();
59            }
60            Err(err) => {
61                if config.expect_direct_search_enabled {
62                    return Err(boxed_error(format!(
63                        "core.search expected enabled but failed: {err}"
64                    )));
65                }
66                let message = err.to_string();
67                require(
68                    is_permission_denied_like(&message),
69                    format!(
70                        "core.search should fail with permission denied when disabled: {message}"
71                    ),
72                )?;
73
74                metrics = json!({
75                    "run_id": run_id,
76                    "enabled": false,
77                    "message": message,
78                });
79                detail = "validated optional core direct-search (disabled)".to_string();
80            }
81        }
82
83        Ok::<(), Box<dyn Error>>(())
84    }
85    .await;
86
87    if let Err(err) = scenario {
88        passed = false;
89        detail = err.to_string();
90    }
91
92    let cleanup_ok = cleanup_run(&client, &run_id).await;
93    if !cleanup_ok {
94        passed = false;
95        detail = format!("{detail} | cleanup failures");
96    }
97
98    print_summary(
99        name,
100        passed,
101        &detail,
102        &metrics,
103        started.elapsed().as_secs_f64(),
104        cleanup_ok,
105    );
106
107    if passed {
108        Ok(())
109    } else {
110        Err(boxed_error(detail))
111    }
112}
examples/internal/core_direct_search.rs (line 32)
25async fn main() -> Result<(), Box<dyn Error>> {
26    let name = "internal_core_direct_search";
27    let started = Instant::now();
28    let config = ScenarioConfig::from_env();
29    let client = create_client().await?;
30    let run_id = new_run_id("internal_core_direct_search");
31    client.set_run_id(Some(run_id.clone()));
32    client.set_transport(TransportMode::Http);
33
34    let mut passed = true;
35    let mut detail = "validated optional core direct-search".to_string();
36    let mut metrics = json!({});
37
38    let scenario = async {
39        match client
40            .core
41            .search(json!({
42                "query": "direct core semantic search probe",
43                "k": 5,
44            }))
45            .await
46        {
47            Ok(payload) => {
48                require(
49                    payload.is_array() || payload.is_object(),
50                    format!("core.search payload must be dict/list: {payload}"),
51                )?;
52
53                metrics = json!({
54                    "run_id": run_id,
55                    "enabled": true,
56                    "result_count": extract_result_count(&payload),
57                });
58                detail = "validated optional core direct-search (enabled)".to_string();
59            }
60            Err(err) => {
61                if config.expect_direct_search_enabled {
62                    return Err(boxed_error(format!(
63                        "core.search expected enabled but failed: {err}"
64                    )));
65                }
66                let message = err.to_string();
67                require(
68                    is_permission_denied_like(&message),
69                    format!(
70                        "core.search should fail with permission denied when disabled: {message}"
71                    ),
72                )?;
73
74                metrics = json!({
75                    "run_id": run_id,
76                    "enabled": false,
77                    "message": message,
78                });
79                detail = "validated optional core direct-search (disabled)".to_string();
80            }
81        }
82
83        Ok::<(), Box<dyn Error>>(())
84    }
85    .await;
86
87    if let Err(err) = scenario {
88        passed = false;
89        detail = err.to_string();
90    }
91
92    let cleanup_ok = cleanup_run(&client, &run_id).await;
93    if !cleanup_ok {
94        passed = false;
95        detail = format!("{detail} | cleanup failures");
96    }
97
98    print_summary(
99        name,
100        passed,
101        &detail,
102        &metrics,
103        started.elapsed().as_secs_f64(),
104        cleanup_ok,
105    );
106
107    if passed {
108        Ok(())
109    } else {
110        Err(boxed_error(detail))
111    }
112}
examples/internal/lessons_lifecycle.rs (line 18)
12async fn main() -> Result<(), Box<dyn Error>> {
13    let name = "internal_lessons_lifecycle";
14    let started = Instant::now();
15    let client = create_client().await?;
16    let run_id = new_run_id("internal_lessons_lifecycle");
17    client.set_run_id(Some(run_id.clone()));
18    client.set_transport(TransportMode::Http);
19    let mut passed = true;
20    let mut detail = "validated raw lessons lifecycle".to_string();
21    let mut metrics = json!({});
22
23    let scenario = async {
24        let mut remember = RememberOptions::new("Always verify the stored deductible before approving reimbursement.");
25        remember.run_id = Some(run_id.clone());
26        remember.intent = Some("lesson".into());
27        remember.lesson_type = Some("success".into());
28        remember.lesson_scope = Some("session".into());
29        client.remember(remember).await?;
30
31        let mut lessons = serde_json::Value::Null;
32        for _ in 0..24 {
33            let current = client
34                .control
35                .lessons(json!({"run_id": run_id, "limit": 10}))
36                .await?;
37            let has_lesson = current
38                .get("lessons")
39                .and_then(|v| v.as_array())
40                .map(|items| !items.is_empty())
41                .unwrap_or(false);
42            lessons = current;
43            if has_lesson {
44                break;
45            }
46            sleep(Duration::from_millis(500)).await;
47        }
48        let lesson_id = lessons.get("lessons").and_then(|v| v.as_array()).and_then(|items| items.iter().find_map(|item| item.get("id").and_then(|v| v.as_str()))).ok_or_else(|| boxed_error(format!("expected lesson in lifecycle test: {lessons}")))?.to_string();
49        let deleted = client.control.delete_lesson(json!({"lesson_id": lesson_id})).await?;
50        let remaining = client.control.lessons(json!({"run_id": run_id, "limit": 10})).await?;
51        require(deleted.get("success").and_then(Value::as_bool).unwrap_or(true), format!("delete_lesson failed: {deleted}"))?;
52        require(!remaining.get("lessons").and_then(|v| v.as_array()).map(|items| items.iter().any(|item| item.get("id").and_then(|v| v.as_str()) == Some(lesson_id.as_str()))).unwrap_or(false), format!("lesson still present after delete: {remaining}"))?;
53        metrics = json!({"run_id": run_id, "lesson_id": lesson_id});
54        Ok::<(), Box<dyn Error>>(())
55    }.await;
56
57    if let Err(err) = scenario { passed = false; detail = err.to_string(); }
58    let cleanup_ok = cleanup_run(&client, &run_id).await;
59    if !cleanup_ok { passed = false; detail = format!("{detail} | cleanup failures"); }
60    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
61    if passed { Ok(()) } else { Err(boxed_error(detail)) }
62}
Source§

impl Client

Source

pub async fn remember(&self, options: RememberOptions) -> Result<Value>

Examples found in repository?
examples/internal/lessons_lifecycle.rs (line 29)
12async fn main() -> Result<(), Box<dyn Error>> {
13    let name = "internal_lessons_lifecycle";
14    let started = Instant::now();
15    let client = create_client().await?;
16    let run_id = new_run_id("internal_lessons_lifecycle");
17    client.set_run_id(Some(run_id.clone()));
18    client.set_transport(TransportMode::Http);
19    let mut passed = true;
20    let mut detail = "validated raw lessons lifecycle".to_string();
21    let mut metrics = json!({});
22
23    let scenario = async {
24        let mut remember = RememberOptions::new("Always verify the stored deductible before approving reimbursement.");
25        remember.run_id = Some(run_id.clone());
26        remember.intent = Some("lesson".into());
27        remember.lesson_type = Some("success".into());
28        remember.lesson_scope = Some("session".into());
29        client.remember(remember).await?;
30
31        let mut lessons = serde_json::Value::Null;
32        for _ in 0..24 {
33            let current = client
34                .control
35                .lessons(json!({"run_id": run_id, "limit": 10}))
36                .await?;
37            let has_lesson = current
38                .get("lessons")
39                .and_then(|v| v.as_array())
40                .map(|items| !items.is_empty())
41                .unwrap_or(false);
42            lessons = current;
43            if has_lesson {
44                break;
45            }
46            sleep(Duration::from_millis(500)).await;
47        }
48        let lesson_id = lessons.get("lessons").and_then(|v| v.as_array()).and_then(|items| items.iter().find_map(|item| item.get("id").and_then(|v| v.as_str()))).ok_or_else(|| boxed_error(format!("expected lesson in lifecycle test: {lessons}")))?.to_string();
49        let deleted = client.control.delete_lesson(json!({"lesson_id": lesson_id})).await?;
50        let remaining = client.control.lessons(json!({"run_id": run_id, "limit": 10})).await?;
51        require(deleted.get("success").and_then(Value::as_bool).unwrap_or(true), format!("delete_lesson failed: {deleted}"))?;
52        require(!remaining.get("lessons").and_then(|v| v.as_array()).map(|items| items.iter().any(|item| item.get("id").and_then(|v| v.as_str()) == Some(lesson_id.as_str()))).unwrap_or(false), format!("lesson still present after delete: {remaining}"))?;
53        metrics = json!({"run_id": run_id, "lesson_id": lesson_id});
54        Ok::<(), Box<dyn Error>>(())
55    }.await;
56
57    if let Err(err) = scenario { passed = false; detail = err.to_string(); }
58    let cleanup_ok = cleanup_run(&client, &run_id).await;
59    if !cleanup_ok { passed = false; detail = format!("{detail} | cleanup failures"); }
60    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
61    if passed { Ok(()) } else { Err(boxed_error(detail)) }
62}
More examples
Hide additional examples
examples/helper_remember_recall.rs (line 35)
11async fn main() -> Result<(), Box<dyn Error>> {
12    let name = "helper_remember_recall";
13    let started = Instant::now();
14    let client = create_client().await?;
15    let run_id = new_run_id("helper_remember_recall");
16    client.set_run_id(Some(run_id.clone()));
17    client.set_transport(TransportMode::Http);
18
19    let mut passed = true;
20    let mut detail = "validated helper remember -> recall flow".to_string();
21    let mut metrics = json!({});
22
23    let scenario = async {
24        let mut remember = RememberOptions::new(
25            "Before retrying cache rebuilds, verify the token signer has rotated cleanly.",
26        );
27        remember.run_id = Some(run_id.clone());
28        remember.agent_id = Some("helper-example".to_string());
29        remember.intent = Some("lesson".to_string());
30        remember.lesson_type = Some("success".to_string());
31        remember.lesson_scope = Some("session".to_string());
32        remember.metadata = Some(json!({ "source": "rust-helper-example" }));
33        remember.occurrence_time = Some(std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as i64 - 86400);
34
35        let remembered = client.remember(remember).await?;
36        require(
37            remembered
38                .get("done")
39                .and_then(|value| value.as_bool())
40                .unwrap_or(false),
41            format!("remember should wait for ingest completion: {remembered}"),
42        )?;
43
44        let mut recall = RecallOptions::new("What should I verify before retrying cache rebuilds?");
45        recall.run_id = Some(run_id.clone());
46        recall.entry_types = vec!["lesson".to_string(), "fact".to_string()];
47        let answer = client.recall(recall).await?;
48        let evidence = answer
49            .get("evidence")
50            .and_then(|value| value.as_array())
51            .ok_or_else(|| boxed_error(format!("evidence missing: {answer}")))?;
52        require(!evidence.is_empty(), format!("evidence missing: {answer}"))?;
53        require(
54            answer
55                .get("final_answer")
56                .and_then(|value| value.as_str())
57                .is_some(),
58            format!("final answer missing: {answer}"),
59        )?;
60
61        metrics = json!({
62            "run_id": run_id,
63            "evidence_count": evidence.len(),
64            "confidence": answer.get("confidence").cloned().unwrap_or(serde_json::Value::Null),
65        });
66
67        Ok::<(), Box<dyn Error>>(())
68    }
69    .await;
70
71    if let Err(err) = scenario {
72        passed = false;
73        detail = err.to_string();
74    }
75
76    let cleanup_ok = cleanup_run(&client, &run_id).await;
77    if !cleanup_ok {
78        passed = false;
79        detail = format!("{detail} | cleanup failures");
80    }
81
82    print_summary(
83        name,
84        passed,
85        &detail,
86        &metrics,
87        started.elapsed().as_secs_f64(),
88        cleanup_ok,
89    );
90
91    if passed {
92        Ok(())
93    } else {
94        Err(boxed_error(detail))
95    }
96}
examples/public/04_memory_health_and_diagnose.rs (line 36)
13async fn main() -> Result<(), Box<dyn Error>> {
14    let name = "public_04_memory_health_and_diagnose";
15    let started = Instant::now();
16    let client = create_client().await?;
17    let run_id = new_run_id("public_04_memory_health_and_diagnose");
18    client.set_run_id(Some(run_id.clone()));
19    client.set_transport(TransportMode::Http);
20
21    let mut passed = true;
22    let mut detail = "validated helper context + diagnose + memory health flow".to_string();
23    let mut metrics = json!({});
24
25    let scenario = async {
26        let mut remember = RememberOptions::new(
27            "Deploys fail when the migration checksum is stale after a force-push.",
28        );
29        remember.run_id = Some(run_id.clone());
30        remember.agent_id = Some("observer".to_string());
31        remember.intent = Some("lesson".to_string());
32        remember.lesson_type = Some("failure".to_string());
33        remember.lesson_scope = Some("session".to_string());
34        remember.lesson_importance = Some("high".to_string());
35        remember.metadata = Some(json!({ "source": "rust-helper-example" }));
36        client.remember(remember).await?;
37
38        let mut context_opts = GetContextOptions::default();
39        context_opts.run_id = Some(run_id.clone());
40        context_opts.query = Some("Why did the deploy fail?".to_string());
41        context_opts.entry_types = vec!["lesson".to_string()];
42        context_opts.mode = Some("summary".to_string());
43        let context = client.get_context(context_opts).await?;
44
45        let mut diagnose = DiagnoseOptions::new("deploy failed because migration checksum is stale");
46        diagnose.run_id = Some(run_id.clone());
47        diagnose.error_type = Some("deploy".to_string());
48        diagnose.limit = 5;
49        let diagnosis = client.diagnose(diagnose).await?;
50
51        let mut health_opts = MemoryHealthOptions::default();
52        health_opts.run_id = Some(run_id.clone());
53        health_opts.limit = 100;
54        let health = client.memory_health(health_opts).await?;
55
56        let section_summaries = context
57            .get("section_summaries")
58            .and_then(|value| value.as_array())
59            .ok_or_else(|| boxed_error(format!("section summaries missing: {context}")))?;
60        require(
61            diagnosis
62                .get("total_failure_lessons")
63                .and_then(|value| value.as_u64())
64                .unwrap_or(0)
65                >= 1,
66            format!("diagnose should surface a failure lesson: {diagnosis}"),
67        )?;
68        require(
69            health.get("entry_counts").and_then(|value| value.as_object()).is_some(),
70            format!("memory health missing entry counts: {health}"),
71        )?;
72
73        metrics = json!({
74            "run_id": run_id,
75            "section_count": section_summaries.len(),
76            "total_failure_lessons": diagnosis.get("total_failure_lessons").cloned().unwrap_or(serde_json::Value::Null),
77            "entry_count_keys": health.get("entry_counts").and_then(|value| value.as_object()).map(|map| map.len()).unwrap_or(0),
78        });
79
80        Ok::<(), Box<dyn Error>>(())
81    }
82    .await;
83
84    if let Err(err) = scenario {
85        passed = false;
86        detail = err.to_string();
87    }
88
89    let cleanup_ok = cleanup_run(&client, &run_id).await;
90    if !cleanup_ok {
91        passed = false;
92        detail = format!("{detail} | cleanup failures");
93    }
94
95    print_summary(
96        name,
97        passed,
98        &detail,
99        &metrics,
100        started.elapsed().as_secs_f64(),
101        cleanup_ok,
102    );
103
104    if passed {
105        Ok(())
106    } else {
107        Err(boxed_error(detail))
108    }
109}
examples/helper_context_diagnose_memory_health.rs (line 36)
13async fn main() -> Result<(), Box<dyn Error>> {
14    let name = "helper_context_diagnose_memory_health";
15    let started = Instant::now();
16    let client = create_client().await?;
17    let run_id = new_run_id("helper_context_diagnose_memory_health");
18    client.set_run_id(Some(run_id.clone()));
19    client.set_transport(TransportMode::Http);
20
21    let mut passed = true;
22    let mut detail = "validated helper context + diagnose + memory health flow".to_string();
23    let mut metrics = json!({});
24
25    let scenario = async {
26        let mut remember = RememberOptions::new(
27            "Deploys fail when the migration checksum is stale after a force-push.",
28        );
29        remember.run_id = Some(run_id.clone());
30        remember.agent_id = Some("observer".to_string());
31        remember.intent = Some("lesson".to_string());
32        remember.lesson_type = Some("failure".to_string());
33        remember.lesson_scope = Some("session".to_string());
34        remember.lesson_importance = Some("high".to_string());
35        remember.metadata = Some(json!({ "source": "rust-helper-example" }));
36        client.remember(remember).await?;
37
38        let mut context_opts = GetContextOptions::default();
39        context_opts.run_id = Some(run_id.clone());
40        context_opts.query = Some("Why did the deploy fail?".to_string());
41        context_opts.entry_types = vec!["lesson".to_string()];
42        context_opts.mode = Some("summary".to_string());
43        let context = client.get_context(context_opts).await?;
44
45        let mut diagnose = DiagnoseOptions::new("deploy failed because migration checksum is stale");
46        diagnose.run_id = Some(run_id.clone());
47        diagnose.error_type = Some("deploy".to_string());
48        diagnose.limit = 5;
49        let diagnosis = client.diagnose(diagnose).await?;
50
51        let mut health_opts = MemoryHealthOptions::default();
52        health_opts.run_id = Some(run_id.clone());
53        health_opts.limit = 100;
54        let health = client.memory_health(health_opts).await?;
55
56        let section_summaries = context
57            .get("section_summaries")
58            .and_then(|value| value.as_array())
59            .ok_or_else(|| boxed_error(format!("section summaries missing: {context}")))?;
60        require(
61            diagnosis
62                .get("total_failure_lessons")
63                .and_then(|value| value.as_u64())
64                .unwrap_or(0)
65                >= 1,
66            format!("diagnose should surface a failure lesson: {diagnosis}"),
67        )?;
68        require(
69            health.get("entry_counts").and_then(|value| value.as_object()).is_some(),
70            format!("memory health missing entry counts: {health}"),
71        )?;
72
73        metrics = json!({
74            "run_id": run_id,
75            "section_count": section_summaries.len(),
76            "total_failure_lessons": diagnosis.get("total_failure_lessons").cloned().unwrap_or(serde_json::Value::Null),
77            "entry_count_keys": health.get("entry_counts").and_then(|value| value.as_object()).map(|map| map.len()).unwrap_or(0),
78        });
79
80        Ok::<(), Box<dyn Error>>(())
81    }
82    .await;
83
84    if let Err(err) = scenario {
85        passed = false;
86        detail = err.to_string();
87    }
88
89    let cleanup_ok = cleanup_run(&client, &run_id).await;
90    if !cleanup_ok {
91        passed = false;
92        detail = format!("{detail} | cleanup failures");
93    }
94
95    print_summary(
96        name,
97        passed,
98        &detail,
99        &metrics,
100        started.elapsed().as_secs_f64(),
101        cleanup_ok,
102    );
103
104    if passed {
105        Ok(())
106    } else {
107        Err(boxed_error(detail))
108    }
109}
examples/public/01_remember_recall.rs (line 36)
11async fn main() -> Result<(), Box<dyn Error>> {
12    let name = "public_01_remember_recall";
13    let started = Instant::now();
14    let client = create_client().await?;
15    let run_id = new_run_id("public_01_remember_recall");
16    client.set_run_id(Some(run_id.clone()));
17    client.set_transport(TransportMode::Http);
18
19    let mut passed = true;
20    let mut detail = "validated helper remember -> recall flow with upsert_key idempotency".to_string();
21    let mut metrics = json!({});
22
23    let scenario = async {
24        let upsert_key = format!("remember-recall-{run_id}");
25        let mut remember = RememberOptions::new(
26            "Before retrying cache rebuilds, verify the token signer has rotated cleanly.",
27        );
28        remember.run_id = Some(run_id.clone());
29        remember.agent_id = Some("helper-example".to_string());
30        remember.intent = Some("lesson".to_string());
31        remember.lesson_type = Some("success".to_string());
32        remember.lesson_scope = Some("session".to_string());
33        remember.upsert_key = Some(upsert_key.clone());
34        remember.metadata = Some(json!({ "source": "rust-helper-example" }));
35
36        let remembered = client.remember(remember).await?;
37        require(
38            remembered
39                .get("done")
40                .and_then(|value| value.as_bool())
41                .unwrap_or(false),
42            format!("remember should wait for ingest completion: {remembered}"),
43        )?;
44
45        let mut updated = RememberOptions::new(
46            "Before retrying cache rebuilds, verify the signer rotation completed and invalidate stale cache tokens.",
47        );
48        updated.run_id = Some(run_id.clone());
49        updated.agent_id = Some("helper-example".to_string());
50        updated.intent = Some("lesson".to_string());
51        updated.lesson_type = Some("success".to_string());
52        updated.lesson_scope = Some("session".to_string());
53        updated.upsert_key = Some(upsert_key.clone());
54        updated.metadata = Some(json!({ "source": "rust-helper-example", "revision": 2 }));
55
56        let updated_response = client.remember(updated).await?;
57        require(
58            updated_response
59                .get("done")
60                .and_then(|value| value.as_bool())
61                .unwrap_or(false),
62            format!("upsert remember should wait for ingest completion: {updated_response}"),
63        )?;
64
65        let mut recall = RecallOptions::new("What should I verify before retrying cache rebuilds?");
66        recall.run_id = Some(run_id.clone());
67        recall.entry_types = vec!["lesson".to_string(), "fact".to_string()];
68        let answer = client.recall(recall).await?;
69        let evidence = answer
70            .get("evidence")
71            .and_then(|value| value.as_array())
72            .ok_or_else(|| boxed_error(format!("evidence missing: {answer}")))?;
73        require(!evidence.is_empty(), format!("evidence missing: {answer}"))?;
74        let rendered = evidence
75            .iter()
76            .filter_map(|item| item.get("content").and_then(|value| value.as_str()))
77            .collect::<Vec<_>>()
78            .join(" ");
79        require(
80            rendered.contains("invalidate stale cache tokens"),
81            format!("upserted lesson should be recalled: {answer}"),
82        )?;
83        require(
84            answer
85                .get("final_answer")
86                .and_then(|value| value.as_str())
87                .is_some(),
88            format!("final answer missing: {answer}"),
89        )?;
90
91        metrics = json!({
92            "run_id": run_id,
93            "evidence_count": evidence.len(),
94            "confidence": answer.get("confidence").cloned().unwrap_or(serde_json::Value::Null),
95            "upsert_key": upsert_key,
96        });
97
98        Ok::<(), Box<dyn Error>>(())
99    }
100    .await;
101
102    if let Err(err) = scenario {
103        passed = false;
104        detail = err.to_string();
105    }
106
107    let cleanup_ok = cleanup_run(&client, &run_id).await;
108    if !cleanup_ok {
109        passed = false;
110        detail = format!("{detail} | cleanup failures");
111    }
112
113    print_summary(
114        name,
115        passed,
116        &detail,
117        &metrics,
118        started.elapsed().as_secs_f64(),
119        cleanup_ok,
120    );
121
122    if passed {
123        Ok(())
124    } else {
125        Err(boxed_error(detail))
126    }
127}
examples/helper_mas_learning_loop.rs (line 44)
14async fn main() -> Result<(), Box<dyn Error>> {
15    let name = "helper_mas_learning_loop";
16    let started = Instant::now();
17    let client = create_client().await?;
18    let run_id = new_run_id("helper_mas_learning_loop");
19    client.set_run_id(Some(run_id.clone()));
20    client.set_transport(TransportMode::Http);
21
22    let mut passed = true;
23    let mut detail = "validated helper MAS checkpoint/outcome/strategies flow".to_string();
24    let mut metrics = json!({});
25
26    let scenario = async {
27        let mut register = RegisterAgentOptions::new("planner");
28        register.run_id = Some(run_id.clone());
29        register.role = "planner".to_string();
30        register.read_scopes = vec!["rule".to_string(), "lesson".to_string(), "fact".to_string()];
31        register.write_scopes = vec!["lesson".to_string(), "trace".to_string()];
32        register.shared_memory_lanes = vec!["knowledge".to_string(), "history".to_string()];
33        client.register_agent(register).await?;
34
35        let mut remember = RememberOptions::new(
36            "If a retry succeeds after token signer rotation, record it as a reusable recovery pattern.",
37        );
38        remember.run_id = Some(run_id.clone());
39        remember.agent_id = Some("planner".to_string());
40        remember.intent = Some("lesson".to_string());
41        remember.lesson_type = Some("success".to_string());
42        remember.lesson_scope = Some("session".to_string());
43        remember.lesson_importance = Some("high".to_string());
44        client.remember(remember).await?;
45
46        let mut checkpoint = CheckpointOptions::new(
47            "Planner isolated the recovery path to token signer rotation.",
48        );
49        checkpoint.run_id = Some(run_id.clone());
50        checkpoint.label = Some("pre-compaction-1".to_string());
51        checkpoint.metadata = Some(json!({ "stage": "analysis" }));
52        checkpoint.agent_id = Some("planner".to_string());
53        let checkpoint_response = client.checkpoint(checkpoint).await?;
54
55        let mut list_agents = ListAgentsOptions::default();
56        list_agents.run_id = Some(run_id.clone());
57        let agents = client.list_agents(list_agents).await?;
58
59        let lessons = client.control.lessons(json!({ "run_id": run_id, "limit": 10 })).await?;
60        let lesson_id = lessons
61            .get("lessons")
62            .and_then(|value| value.as_array())
63            .and_then(|items| items.first())
64            .and_then(|item| item.get("id"))
65            .and_then(|value| value.as_str())
66            .ok_or_else(|| boxed_error(format!("expected at least one lesson to record outcome against: {lessons}")))?
67            .to_string();
68
69        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
70        outcome.run_id = Some(run_id.clone());
71        outcome.signal = 0.75;
72        outcome.rationale = "Recovery succeeded after following the stored lesson.".to_string();
73        outcome.agent_id = Some("planner".to_string());
74        let outcome_response = client.record_outcome(outcome).await?;
75
76        let mut strategies = SurfaceStrategiesOptions::default();
77        strategies.run_id = Some(run_id.clone());
78        strategies.lesson_types = vec!["success".to_string(), "failure".to_string()];
79        strategies.max_strategies = 5;
80        let strategy_response = client.surface_strategies(strategies).await?;
81
82        require(
83            checkpoint_response
84                .get("success")
85                .and_then(|value| value.as_bool())
86                .unwrap_or(false),
87            format!("checkpoint failed: {checkpoint_response}"),
88        )?;
89        let agent_count = agents
90            .get("agents")
91            .and_then(|value| value.as_array())
92            .map(|items| items.len())
93            .unwrap_or(0);
94        require(agent_count == 1, format!("agent registration missing: {agents}"))?;
95        require(
96            outcome_response
97                .get("success")
98                .and_then(|value| value.as_bool())
99                .unwrap_or(false),
100            format!("record_outcome failed: {outcome_response}"),
101        )?;
102        let strategy_count = strategy_response
103            .get("strategies")
104            .and_then(|value| value.as_array())
105            .map(|items| items.len())
106            .unwrap_or(0);
107
108        metrics = json!({
109            "run_id": run_id,
110            "checkpoint_id": checkpoint_response.get("checkpoint_id").cloned().unwrap_or(serde_json::Value::Null),
111            "agent_count": agent_count,
112            "strategy_count": strategy_count,
113        });
114
115        Ok::<(), Box<dyn Error>>(())
116    }
117    .await;
118
119    if let Err(err) = scenario {
120        passed = false;
121        detail = err.to_string();
122    }
123
124    let cleanup_ok = cleanup_run(&client, &run_id).await;
125    if !cleanup_ok {
126        passed = false;
127        detail = format!("{detail} | cleanup failures");
128    }
129
130    print_summary(
131        name,
132        passed,
133        &detail,
134        &metrics,
135        started.elapsed().as_secs_f64(),
136        cleanup_ok,
137    );
138
139    if passed {
140        Ok(())
141    } else {
142        Err(boxed_error(detail))
143    }
144}
Source

pub async fn recall(&self, options: RecallOptions) -> Result<Value>

Examples found in repository?
examples/helper_remember_recall.rs (line 47)
11async fn main() -> Result<(), Box<dyn Error>> {
12    let name = "helper_remember_recall";
13    let started = Instant::now();
14    let client = create_client().await?;
15    let run_id = new_run_id("helper_remember_recall");
16    client.set_run_id(Some(run_id.clone()));
17    client.set_transport(TransportMode::Http);
18
19    let mut passed = true;
20    let mut detail = "validated helper remember -> recall flow".to_string();
21    let mut metrics = json!({});
22
23    let scenario = async {
24        let mut remember = RememberOptions::new(
25            "Before retrying cache rebuilds, verify the token signer has rotated cleanly.",
26        );
27        remember.run_id = Some(run_id.clone());
28        remember.agent_id = Some("helper-example".to_string());
29        remember.intent = Some("lesson".to_string());
30        remember.lesson_type = Some("success".to_string());
31        remember.lesson_scope = Some("session".to_string());
32        remember.metadata = Some(json!({ "source": "rust-helper-example" }));
33        remember.occurrence_time = Some(std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as i64 - 86400);
34
35        let remembered = client.remember(remember).await?;
36        require(
37            remembered
38                .get("done")
39                .and_then(|value| value.as_bool())
40                .unwrap_or(false),
41            format!("remember should wait for ingest completion: {remembered}"),
42        )?;
43
44        let mut recall = RecallOptions::new("What should I verify before retrying cache rebuilds?");
45        recall.run_id = Some(run_id.clone());
46        recall.entry_types = vec!["lesson".to_string(), "fact".to_string()];
47        let answer = client.recall(recall).await?;
48        let evidence = answer
49            .get("evidence")
50            .and_then(|value| value.as_array())
51            .ok_or_else(|| boxed_error(format!("evidence missing: {answer}")))?;
52        require(!evidence.is_empty(), format!("evidence missing: {answer}"))?;
53        require(
54            answer
55                .get("final_answer")
56                .and_then(|value| value.as_str())
57                .is_some(),
58            format!("final answer missing: {answer}"),
59        )?;
60
61        metrics = json!({
62            "run_id": run_id,
63            "evidence_count": evidence.len(),
64            "confidence": answer.get("confidence").cloned().unwrap_or(serde_json::Value::Null),
65        });
66
67        Ok::<(), Box<dyn Error>>(())
68    }
69    .await;
70
71    if let Err(err) = scenario {
72        passed = false;
73        detail = err.to_string();
74    }
75
76    let cleanup_ok = cleanup_run(&client, &run_id).await;
77    if !cleanup_ok {
78        passed = false;
79        detail = format!("{detail} | cleanup failures");
80    }
81
82    print_summary(
83        name,
84        passed,
85        &detail,
86        &metrics,
87        started.elapsed().as_secs_f64(),
88        cleanup_ok,
89    );
90
91    if passed {
92        Ok(())
93    } else {
94        Err(boxed_error(detail))
95    }
96}
More examples
Hide additional examples
examples/public/01_remember_recall.rs (line 68)
11async fn main() -> Result<(), Box<dyn Error>> {
12    let name = "public_01_remember_recall";
13    let started = Instant::now();
14    let client = create_client().await?;
15    let run_id = new_run_id("public_01_remember_recall");
16    client.set_run_id(Some(run_id.clone()));
17    client.set_transport(TransportMode::Http);
18
19    let mut passed = true;
20    let mut detail = "validated helper remember -> recall flow with upsert_key idempotency".to_string();
21    let mut metrics = json!({});
22
23    let scenario = async {
24        let upsert_key = format!("remember-recall-{run_id}");
25        let mut remember = RememberOptions::new(
26            "Before retrying cache rebuilds, verify the token signer has rotated cleanly.",
27        );
28        remember.run_id = Some(run_id.clone());
29        remember.agent_id = Some("helper-example".to_string());
30        remember.intent = Some("lesson".to_string());
31        remember.lesson_type = Some("success".to_string());
32        remember.lesson_scope = Some("session".to_string());
33        remember.upsert_key = Some(upsert_key.clone());
34        remember.metadata = Some(json!({ "source": "rust-helper-example" }));
35
36        let remembered = client.remember(remember).await?;
37        require(
38            remembered
39                .get("done")
40                .and_then(|value| value.as_bool())
41                .unwrap_or(false),
42            format!("remember should wait for ingest completion: {remembered}"),
43        )?;
44
45        let mut updated = RememberOptions::new(
46            "Before retrying cache rebuilds, verify the signer rotation completed and invalidate stale cache tokens.",
47        );
48        updated.run_id = Some(run_id.clone());
49        updated.agent_id = Some("helper-example".to_string());
50        updated.intent = Some("lesson".to_string());
51        updated.lesson_type = Some("success".to_string());
52        updated.lesson_scope = Some("session".to_string());
53        updated.upsert_key = Some(upsert_key.clone());
54        updated.metadata = Some(json!({ "source": "rust-helper-example", "revision": 2 }));
55
56        let updated_response = client.remember(updated).await?;
57        require(
58            updated_response
59                .get("done")
60                .and_then(|value| value.as_bool())
61                .unwrap_or(false),
62            format!("upsert remember should wait for ingest completion: {updated_response}"),
63        )?;
64
65        let mut recall = RecallOptions::new("What should I verify before retrying cache rebuilds?");
66        recall.run_id = Some(run_id.clone());
67        recall.entry_types = vec!["lesson".to_string(), "fact".to_string()];
68        let answer = client.recall(recall).await?;
69        let evidence = answer
70            .get("evidence")
71            .and_then(|value| value.as_array())
72            .ok_or_else(|| boxed_error(format!("evidence missing: {answer}")))?;
73        require(!evidence.is_empty(), format!("evidence missing: {answer}"))?;
74        let rendered = evidence
75            .iter()
76            .filter_map(|item| item.get("content").and_then(|value| value.as_str()))
77            .collect::<Vec<_>>()
78            .join(" ");
79        require(
80            rendered.contains("invalidate stale cache tokens"),
81            format!("upserted lesson should be recalled: {answer}"),
82        )?;
83        require(
84            answer
85                .get("final_answer")
86                .and_then(|value| value.as_str())
87                .is_some(),
88            format!("final answer missing: {answer}"),
89        )?;
90
91        metrics = json!({
92            "run_id": run_id,
93            "evidence_count": evidence.len(),
94            "confidence": answer.get("confidence").cloned().unwrap_or(serde_json::Value::Null),
95            "upsert_key": upsert_key,
96        });
97
98        Ok::<(), Box<dyn Error>>(())
99    }
100    .await;
101
102    if let Err(err) = scenario {
103        passed = false;
104        detail = err.to_string();
105    }
106
107    let cleanup_ok = cleanup_run(&client, &run_id).await;
108    if !cleanup_ok {
109        passed = false;
110        detail = format!("{detail} | cleanup failures");
111    }
112
113    print_summary(
114        name,
115        passed,
116        &detail,
117        &metrics,
118        started.elapsed().as_secs_f64(),
119        cleanup_ok,
120    );
121
122    if passed {
123        Ok(())
124    } else {
125        Err(boxed_error(detail))
126    }
127}
examples/public/09_user_scoping_and_isolation.rs (line 66)
12async fn main() -> Result<(), Box<dyn Error>> {
13    let name = "public_09_user_scoping_and_isolation";
14    let started = Instant::now();
15    let client = create_client().await?;
16    let user_a = "sdk-user-a".to_string();
17    let user_b = "sdk-user-b".to_string();
18    let seed_run = new_run_id("public_user_scope_seed");
19    let allowed_run = new_run_id("public_user_scope_allowed");
20    let blocked_run = new_run_id("public_user_scope_blocked");
21    client.set_transport(TransportMode::Http);
22    client.set_run_id(Some(seed_run.clone()));
23
24    let mut passed = true;
25    let mut detail = "validated user scoping and same-user cross-run reuse".to_string();
26    let mut metrics = json!({});
27
28    let scenario = async {
29        let mut lesson = RememberOptions::new("When a claim is missing a city, check the original intake note before escalating.");
30        lesson.run_id = Some(seed_run.clone());
31        lesson.user_id = Some(user_a.clone());
32        lesson.agent_id = Some("planner".into());
33        lesson.intent = Some("lesson".into());
34        lesson.lesson_type = Some("success".into());
35        lesson.lesson_scope = Some("global".into());
36        lesson.lesson_importance = Some("high".into());
37        lesson.metadata = Some(json!({"source": "public-example", "family": "user-scope"}));
38        let lesson_write = client.remember(lesson).await?;
39
40        let mut lessons = serde_json::Value::Null;
41        for _ in 0..24 {
42            let current = client
43                .control
44                .lessons(json!({"run_id": seed_run, "user_id": user_a, "limit": 10}))
45                .await?;
46            let has_lesson = current
47                .get("lessons")
48                .and_then(|v| v.as_array())
49                .map(|items| !items.is_empty())
50                .unwrap_or(false);
51            lessons = current;
52            if has_lesson {
53                break;
54            }
55            sleep(Duration::from_millis(500)).await;
56        }
57        let lesson_id = lessons.get("lessons").and_then(|v| v.as_array()).and_then(|items| items.iter().find_map(|item| item.get("id").and_then(|v| v.as_str()))).ok_or_else(|| boxed_error(format!("expected lesson for isolation scenario: {lessons}")))?.to_string();
58
59        let mut allowed = RecallOptions::new(
60            "A claim is missing a city. Before escalating, what note should I check?",
61        );
62        allowed.run_id = Some(allowed_run.clone());
63        allowed.user_id = Some(user_a.clone());
64        allowed.entry_types = vec!["lesson".into()];
65        allowed.limit = 10;
66        let allowed_response = client.recall(allowed).await?;
67
68        let mut blocked = RecallOptions::new(
69            "A claim is missing a city. Before escalating, what note should I check?",
70        );
71        blocked.run_id = Some(blocked_run.clone());
72        blocked.user_id = Some(user_b.clone());
73        blocked.entry_types = vec!["lesson".into()];
74        blocked.limit = 10;
75        let blocked_response = client.recall(blocked).await?;
76
77        let allowed_text = format!("{} {}",
78            allowed_response.get("final_answer").and_then(|v| v.as_str()).unwrap_or(""),
79            allowed_response.get("evidence").and_then(|v| v.as_array()).map(|items| items.iter().filter_map(|item| item.get("content").and_then(|v| v.as_str())).collect::<Vec<_>>().join(" ")).unwrap_or_default()
80        ).to_lowercase();
81        let blocked_text = format!("{} {}",
82            blocked_response.get("final_answer").and_then(|v| v.as_str()).unwrap_or(""),
83            blocked_response.get("evidence").and_then(|v| v.as_array()).map(|items| items.iter().filter_map(|item| item.get("content").and_then(|v| v.as_str())).collect::<Vec<_>>().join(" ")).unwrap_or_default()
84        ).to_lowercase();
85
86        require(lesson_write.get("accepted").and_then(|v| v.as_bool()).unwrap_or(false) || lesson_write.get("job_id").is_some(), format!("lesson write failed: {lesson_write}"))?;
87        require(allowed_text.contains("original intake note"), format!("same-user cross-run lesson reuse failed: {allowed_response}"))?;
88        require(!blocked_text.contains("original intake note"), format!("cross-user leak detected: {blocked_response}"))?;
89
90        metrics = json!({
91            "seed_run": seed_run,
92            "allowed_run": allowed_run,
93            "blocked_run": blocked_run,
94            "lesson_id": lesson_id,
95            "allowed_evidence_count": allowed_response.get("evidence").and_then(|v| v.as_array()).map(|items| items.len()).unwrap_or(0),
96            "blocked_evidence_count": blocked_response.get("evidence").and_then(|v| v.as_array()).map(|items| items.len()).unwrap_or(0),
97        });
98        Ok::<(), Box<dyn Error>>(())
99    }
100    .await;
101
102    if let Err(err) = scenario {
103        passed = false;
104        detail = err.to_string();
105    }
106
107    let mut cleanup_ok = true;
108    for run_id in [&seed_run, &allowed_run, &blocked_run] {
109        cleanup_ok = cleanup_ok && cleanup_run(&client, run_id).await;
110    }
111    if !cleanup_ok {
112        passed = false;
113        detail = format!("{detail} | cleanup failures");
114    }
115
116    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
117    if passed { Ok(()) } else { Err(boxed_error(detail)) }
118}
examples/public/11_temporal_entity_mental_model.rs (line 70)
11async fn main() -> Result<(), Box<dyn Error>> {
12    let name = "public_11_temporal_entity_mental_model";
13    let started = Instant::now();
14    let client = create_client().await?;
15    let run_id = new_run_id("public_temporal_entity");
16    client.set_run_id(Some(run_id.clone()));
17    client.set_transport(TransportMode::Http);
18
19    let mut passed = true;
20    let mut detail =
21        "validated temporal queries, entity aliasing, and mental model priority".to_string();
22    let mut metrics = json!({});
23
24    let scenario = async {
25        // 1. Store facts with occurrence_time
26        let now = std::time::SystemTime::now()
27            .duration_since(std::time::UNIX_EPOCH)
28            .unwrap()
29            .as_secs() as i64;
30
31        let mut fact1 =
32            RememberOptions::new("Alice Chen joined the platform team in March 2024.");
33        fact1.run_id = Some(run_id.clone());
34        fact1.intent = Some("fact".to_string());
35        fact1.occurrence_time = Some(now - 86400 * 365); // ~1 year ago
36        fact1.metadata = Some(json!({"speaker": "Alice Chen"}));
37        client.remember(fact1).await?;
38
39        let mut fact2 =
40            RememberOptions::new("Alice was promoted to Senior Engineer in January 2025.");
41        fact2.run_id = Some(run_id.clone());
42        fact2.intent = Some("fact".to_string());
43        fact2.occurrence_time = Some(now - 86400 * 60); // ~2 months ago
44        fact2.metadata = Some(json!({"speaker": "Alice Chen"}));
45        client.remember(fact2).await?;
46
47        let mut fact3 =
48            RememberOptions::new("Dr. Chen published a paper on distributed consensus.");
49        fact3.run_id = Some(run_id.clone());
50        fact3.intent = Some("fact".to_string());
51        fact3.metadata = Some(json!({"speaker": "Alice Chen"}));
52        client.remember(fact3).await?;
53
54        // 2. Store a mental model (curated summary)
55        let mut mental = RememberOptions::new(
56            "Alice Chen (Dr. Chen) is a Senior Engineer on the platform team. \
57             She specializes in distributed consensus and was promoted in January 2025.",
58        );
59        mental.run_id = Some(run_id.clone());
60        mental.intent = Some("mental_model".to_string());
61        mental.importance = Some("critical".to_string());
62        mental.metadata = Some(json!({"entity": "alice chen", "consolidated": true}));
63        client.remember(mental).await?;
64
65        // 3. Recall with temporal bounds (last 90 days)
66        let mut temporal_recall = RecallOptions::new("What happened recently with Alice?");
67        temporal_recall.run_id = Some(run_id.clone());
68        temporal_recall.min_timestamp = Some(now - 86400 * 90);
69        temporal_recall.max_timestamp = Some(now);
70        let temporal_result = client.recall(temporal_recall).await?;
71        let temporal_evidence = temporal_result
72            .get("evidence")
73            .and_then(|v| v.as_array())
74            .ok_or_else(|| {
75                boxed_error("temporal recall missing evidence".to_string())
76            })?;
77        require(
78            !temporal_evidence.is_empty(),
79            format!("temporal recall should return evidence: {temporal_result}"),
80        )?;
81
82        // 4. Recall with budget tier
83        let mut budget_recall = RecallOptions::new("Tell me about Alice Chen");
84        budget_recall.run_id = Some(run_id.clone());
85        budget_recall.budget = Some("high".to_string());
86        let budget_result = client.recall(budget_recall).await?;
87        let budget_evidence = budget_result
88            .get("evidence")
89            .and_then(|v| v.as_array())
90            .ok_or_else(|| {
91                boxed_error("budget recall missing evidence".to_string())
92            })?;
93        require(
94            !budget_evidence.is_empty(),
95            format!("budget recall should return evidence: {budget_result}"),
96        )?;
97
98        // 5. get_context should show Mental Models section first
99        let mut ctx_opts = GetContextOptions::default();
100        ctx_opts.run_id = Some(run_id.clone());
101        ctx_opts.query = Some("Who is Alice Chen?".to_string());
102        ctx_opts.entry_types = vec!["mental_model".to_string(), "fact".to_string()];
103        ctx_opts.limit = Some(10);
104        let ctx = client.get_context(ctx_opts).await?;
105        let context_block = ctx
106            .get("context_block")
107            .and_then(|v| v.as_str())
108            .unwrap_or("");
109        // Mental Models section should appear before Facts
110        let has_mental = context_block.contains("Mental Model");
111        require(
112            has_mental || context_block.contains("mental_model"),
113            format!(
114                "context should include mental model section: {}",
115                &context_block[..context_block.len().min(300)]
116            ),
117        )?;
118
119        metrics = json!({
120            "run_id": run_id,
121            "temporal_evidence_count": temporal_evidence.len(),
122            "budget_evidence_count": budget_evidence.len(),
123            "context_has_mental_model": has_mental,
124            "context_block_length": context_block.len(),
125        });
126        Ok::<(), Box<dyn Error>>(())
127    }
128    .await;
129
130    if let Err(err) = scenario {
131        passed = false;
132        detail = err.to_string();
133    }
134
135    let cleanup_ok = cleanup_run(&client, &run_id).await;
136    if !cleanup_ok {
137        passed = false;
138        detail = format!("{detail} | cleanup failures");
139    }
140
141    print_summary(
142        name,
143        passed,
144        &detail,
145        &metrics,
146        started.elapsed().as_secs_f64(),
147        cleanup_ok,
148    );
149    if passed {
150        Ok(())
151    } else {
152        Err(boxed_error(detail))
153    }
154}
examples/public/08_multi_agent_claims_or_support_flow.rs (line 94)
11async fn main() -> Result<(), Box<dyn Error>> {
12    let name = "public_08_multi_agent_claims_or_support_flow";
13    let started = Instant::now();
14    let client = create_client().await?;
15    let run_id = new_run_id("public_claims_flow");
16    client.set_run_id(Some(run_id.clone()));
17    client.set_transport(TransportMode::Http);
18
19    let mut passed = true;
20    let mut detail = "validated multi-agent claims/support flow".to_string();
21    let mut metrics = json!({});
22
23    let scenario = async {
24        for (agent_id, role, read_scopes, write_scopes) in [
25            ("intake", "intake", vec!["fact", "archive_block"], vec!["fact", "archive_block", "trace"]),
26            ("coverage", "coverage", vec!["fact", "rule", "archive_block", "handoff", "feedback"], vec!["fact", "trace", "lesson"]),
27            ("reviewer", "reviewer", vec!["fact", "archive_block", "handoff", "feedback", "rule"], vec!["feedback", "rule"]),
28        ] {
29            let mut agent = RegisterAgentOptions::new(agent_id);
30            agent.run_id = Some(run_id.clone());
31            agent.role = role.to_string();
32            agent.read_scopes = read_scopes.into_iter().map(String::from).collect();
33            agent.write_scopes = write_scopes.into_iter().map(String::from).collect();
34            agent.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
35            client.register_agent(agent).await?;
36        }
37
38        let mut fact = RememberOptions::new("Policy P-8842 covers windshield damage with a 250 GBP deductible.");
39        fact.run_id = Some(run_id.clone());
40        fact.agent_id = Some("intake".into());
41        fact.intent = Some("fact".into());
42        fact.metadata = Some(json!({"claim_id": "CLM-8842", "source": "intake-form"}));
43        client.remember(fact).await?;
44
45        let mut archive = ArchiveOptions::new("Exact adjuster note: customer confirmed the damage happened on the motorway and no third party was involved.", "adjuster_note");
46        archive.run_id = Some(run_id.clone());
47        archive.agent_id = Some("intake".into());
48        archive.origin_agent_id = Some("intake".into());
49        archive.source_attempt_id = Some("attempt-1".into());
50        archive.source_tool = Some("claim-review".into());
51        archive.labels = vec!["claims".into(), "coverage".into()];
52        archive.family = Some("windshield".into());
53        let archived = client.archive(archive).await?;
54        let reference_id = archived.get("reference_id").and_then(|v| v.as_str()).ok_or_else(|| boxed_error(format!("archive reference missing: {archived}")))?.to_string();
55
56        let mut checkpoint = CheckpointOptions::new("Coverage verified deductible and adjuster note before escalation.");
57        checkpoint.run_id = Some(run_id.clone());
58        checkpoint.label = Some("pre-review".into());
59        checkpoint.agent_id = Some("coverage".into());
60        checkpoint.metadata = Some(json!({"claim_id": "CLM-8842"}));
61        let checkpoint_response = client.checkpoint(checkpoint).await?;
62
63        let mut handoff = HandoffOptions::new("claim-8842", "coverage", "reviewer", "Review whether the adjuster note is enough to approve the claim.");
64        handoff.run_id = Some(run_id.clone());
65        handoff.requested_action = "review".into();
66        handoff.metadata = Some(json!({"claim_id": "CLM-8842"}));
67        let handoff_response = client.handoff(handoff).await?;
68        let handoff_id = handoff_response.get("handoff_id").and_then(|v| v.as_str()).ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?.to_string();
69
70        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
71        feedback.run_id = Some(run_id.clone());
72        feedback.from_agent_id = Some("reviewer".into());
73        feedback.comments = "Deductible and adjuster note are sufficient for routing.".into();
74        feedback.metadata = Some(json!({"claim_id": "CLM-8842"}));
75        let feedback_response = client.feedback(feedback).await?;
76
77        let mut context_opts = GetContextOptions::default();
78        context_opts.run_id = Some(run_id.clone());
79        context_opts.query = Some("Prepare the final claims routing summary.".into());
80        context_opts.agent_id = Some("coverage".into());
81        context_opts.sections = vec!["archive".into(), "facts".into(), "handoffs".into(), "feedback".into()];
82        context_opts.mode = Some("sections".into());
83        let context = client.get_context(context_opts).await?;
84
85        let mut dereference = DereferenceOptions::new(reference_id.clone());
86        dereference.run_id = Some(run_id.clone());
87        dereference.agent_id = Some("coverage".into());
88        let exact = client.dereference(dereference).await?;
89
90        let mut recall = RecallOptions::new("What deductible applies and what did the adjuster confirm?");
91        recall.run_id = Some(run_id.clone());
92        recall.agent_id = Some("coverage".into());
93        recall.entry_types = vec!["fact".into(), "archive_block".into(), "feedback".into()];
94        let recall_response = client.recall(recall).await?;
95
96        require(checkpoint_response.get("success").and_then(|v| v.as_bool()).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
97        require(handoff_response.get("success").and_then(|v| v.as_bool()).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
98        require(feedback_response.get("success").and_then(|v| v.as_bool()).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
99        require(exact.get("found").and_then(|v| v.as_bool()).unwrap_or(false), format!("dereference failed: {exact}"))?;
100        let context_text = context.get("context_block").and_then(|v| v.as_str()).unwrap_or("").to_lowercase();
101        let recall_text = recall_response.get("final_answer").and_then(|v| v.as_str()).unwrap_or("").to_lowercase();
102        let has_archive_source = context
103            .get("sources")
104            .and_then(|v| v.as_array())
105            .map(|sources| {
106                sources.iter().any(|source| {
107                    source
108                        .get("entry_type")
109                        .and_then(|v| v.as_str())
110                        == Some("archive_block")
111                })
112            })
113            .unwrap_or(false);
114        let exact_refs_surfaced = context
115            .get("exact_references_surfaced")
116            .and_then(|v| v.as_u64())
117            .unwrap_or(0);
118        require(
119            context_text.contains("adjuster note")
120                || context_text.contains("motorway")
121                || has_archive_source
122                || exact_refs_surfaced > 0,
123            format!("expected explicit or telemetry-backed exact reuse in context: {context}"),
124        )?;
125        require(recall_text.contains("250") && (recall_text.contains("motorway") || recall_text.contains("third party")), format!("expected recall to include fact + archive content: {recall_response}"))?;
126
127        metrics = json!({
128            "run_id": run_id,
129            "handoff_id": handoff_id,
130            "reference_id": reference_id,
131            "feedback_id": feedback_response.get("feedback_id").cloned().unwrap_or(serde_json::Value::Null),
132        });
133        Ok::<(), Box<dyn Error>>(())
134    }
135    .await;
136
137    if let Err(err) = scenario {
138        passed = false;
139        detail = err.to_string();
140    }
141
142    let cleanup_ok = cleanup_run(&client, &run_id).await;
143    if !cleanup_ok {
144        passed = false;
145        detail = format!("{detail} | cleanup failures");
146    }
147
148    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
149    if passed { Ok(()) } else { Err(boxed_error(detail)) }
150}
examples/public/10_full_learning_loop_smoke.rs (line 62)
16async fn main() -> Result<(), Box<dyn Error>> {
17    let name = "public_10_full_learning_loop_smoke";
18    let started = Instant::now();
19    let client = create_client().await?;
20    let run_id = new_run_id("public_10_full_learning_loop_smoke");
21    client.set_run_id(Some(run_id.clone()));
22    client.set_transport(TransportMode::Http);
23
24    let mut passed = true;
25    let mut detail = "validated all helper flows".to_string();
26    let mut metrics = json!({});
27
28    let scenario = async {
29        let mut remember = RememberOptions::new("Policy limit is 5000 and claimant city is Leeds.");
30        remember.run_id = Some(run_id.clone());
31        remember.agent_id = Some("planner".to_string());
32        remember.intent = Some("fact".to_string());
33        remember.metadata = Some(json!({"suite": "all-helpers", "family": "claims"}));
34        remember.importance = Some("high".to_string());
35        remember.occurrence_time = Some(std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as i64 - 86400);
36        let remember_response = client.remember(remember).await?;
37
38        let mut lesson = RememberOptions::new("If city is missing from the latest step, check stored claim facts before escalating.");
39        lesson.run_id = Some(run_id.clone());
40        lesson.agent_id = Some("planner".to_string());
41        lesson.intent = Some("lesson".to_string());
42        lesson.lesson_type = Some("success".to_string());
43        lesson.lesson_scope = Some("session".to_string());
44        lesson.lesson_importance = Some("high".to_string());
45        let lesson_response = client.remember(lesson).await?;
46
47        let mut mental_model = RememberOptions::new(
48            "Claims case overview: Policy limit 5000 GBP, claimant city Leeds, \
49             missing-city branch resolved via stored claim facts. Lesson: check stored facts before escalating.",
50        );
51        mental_model.run_id = Some(run_id.clone());
52        mental_model.agent_id = Some("planner".to_string());
53        mental_model.intent = Some("mental_model".to_string());
54        mental_model.importance = Some("critical".to_string());
55        mental_model.metadata = Some(json!({"suite": "all-helpers", "entity": "claims-case", "consolidated": true}));
56        let mental_model_response = client.remember(mental_model).await?;
57
58        let mut recall = RecallOptions::new("What is the policy limit?");
59        recall.run_id = Some(run_id.clone());
60        recall.agent_id = Some("planner".to_string());
61        recall.limit = 5;
62        let recall_response = client.recall(recall).await?;
63
64        let mut context = GetContextOptions::default();
65        context.run_id = Some(run_id.clone());
66        context.query = Some("Prepare a short adjuster summary".to_string());
67        context.agent_id = Some("planner".to_string());
68        context.limit = Some(6);
69        context.max_token_budget = Some(700);
70        let context_response = client.get_context(context).await?;
71
72        let mut health = MemoryHealthOptions::default();
73        health.run_id = Some(run_id.clone());
74        health.limit = 50;
75        let health_response = client.memory_health(health).await?;
76
77        let mut diagnose = DiagnoseOptions::new("policy limit lookup returned empty");
78        diagnose.run_id = Some(run_id.clone());
79        diagnose.error_type = Some("retrieval".to_string());
80        diagnose.limit = 5;
81        let diagnose_response = client.diagnose(diagnose).await?;
82
83        let mut reflect = ReflectOptions::default();
84        reflect.run_id = Some(run_id.clone());
85        let reflect_response = client.reflect(reflect).await?;
86
87        let mut register = RegisterAgentOptions::new("planner");
88        register.run_id = Some(run_id.clone());
89        register.role = "planner".to_string();
90        register.read_scopes = vec!["fact".into(), "lesson".into(), "rule".into(), "mental_model".into(), "archive_block".into(), "handoff".into(), "feedback".into()];
91        register.write_scopes = vec!["fact".into(), "trace".into(), "lesson".into(), "observation".into(), "archive_block".into()];
92        register.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
93        let register_response = client.register_agent(register).await?;
94
95        let mut list_agents = ListAgentsOptions::default();
96        list_agents.run_id = Some(run_id.clone());
97        let agents_response = client.list_agents(list_agents).await?;
98
99        let mut archive = ArchiveOptions::new(
100            "Exact adjuster note: claimant confirmed city is Leeds during triage.",
101            "adjuster_note",
102        );
103        archive.run_id = Some(run_id.clone());
104        archive.agent_id = Some("planner".to_string());
105        archive.origin_agent_id = Some("planner".to_string());
106        archive.source_attempt_id = Some("attempt-1".to_string());
107        archive.source_tool = Some("phone_call".to_string());
108        archive.labels = vec!["claims".to_string(), "triage".to_string()];
109        archive.family = Some("claims-adjustment".to_string());
110        archive.metadata = Some(json!({"case": "all-helpers"}));
111        let archive_response = client.archive(archive).await?;
112        let reference_id = archive_response
113            .get("reference_id")
114            .and_then(Value::as_str)
115            .ok_or_else(|| boxed_error(format!("archive reference missing: {archive_response}")))?
116            .to_string();
117
118        let mut dereference = DereferenceOptions::new(reference_id.clone());
119        dereference.run_id = Some(run_id.clone());
120        dereference.agent_id = Some("planner".to_string());
121        let dereference_response = client.dereference(dereference).await?;
122
123        let mut checkpoint = CheckpointOptions::new("Planner captured claim facts before window compaction.");
124        checkpoint.run_id = Some(run_id.clone());
125        checkpoint.label = Some("pre-compaction".to_string());
126        checkpoint.metadata = Some(json!({"stage": "analysis"}));
127        checkpoint.agent_id = Some("planner".to_string());
128        let checkpoint_response = client.checkpoint(checkpoint).await?;
129
130        let lessons_response = client.control.lessons(json!({"run_id": run_id, "limit": 20})).await?;
131        let lesson_id = lessons_response
132            .get("lessons")
133            .and_then(Value::as_array)
134            .and_then(|items| items.iter().find_map(|item| item.get("id").and_then(Value::as_str)))
135            .ok_or_else(|| boxed_error(format!("expected lesson id for outcome flow: {lessons_response}")))?
136            .to_string();
137
138        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
139        outcome.run_id = Some(run_id.clone());
140        outcome.signal = 0.75;
141        outcome.rationale = "Planner reused stored claim fact and resolved the missing-city branch.".to_string();
142        outcome.agent_id = Some("planner".to_string());
143        let outcome_response = client.record_outcome(outcome).await?;
144
145        let mut strategies = SurfaceStrategiesOptions::default();
146        strategies.run_id = Some(run_id.clone());
147        strategies.lesson_types = vec!["success".to_string(), "rule".to_string()];
148        strategies.max_strategies = 5;
149        let strategies_response = client.surface_strategies(strategies).await?;
150
151        let mut handoff = HandoffOptions::new(
152            "claim-1",
153            "planner",
154            "reviewer",
155            "Review whether the stored claimant city is sufficient for routing.",
156        );
157        handoff.run_id = Some(run_id.clone());
158        handoff.requested_action = "review".to_string();
159        handoff.metadata = Some(json!({"team": "claims"}));
160        let handoff_response = client.handoff(handoff).await?;
161        let handoff_id = handoff_response
162            .get("handoff_id")
163            .and_then(Value::as_str)
164            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
165            .to_string();
166
167        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
168        feedback.run_id = Some(run_id.clone());
169        feedback.comments = "Stored fact is sufficient; proceed without escalation.".to_string();
170        feedback.from_agent_id = Some("reviewer".to_string());
171        feedback.metadata = Some(json!({"team": "claims"}));
172        let feedback_response = client.feedback(feedback).await?;
173
174        require(remember_response.get("job_id").is_some() || remember_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("remember failed: {remember_response}"))?;
175        require(mental_model_response.get("job_id").is_some() || mental_model_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("mental_model remember failed: {mental_model_response}"))?;
176        require(lesson_response.get("job_id").is_some() || lesson_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("lesson remember failed: {lesson_response}"))?;
177        require(recall_response.get("final_answer").is_some() || recall_response.get("evidence").is_some(), format!("recall failed: {recall_response}"))?;
178        require(context_response.get("sources").and_then(Value::as_array).is_some(), format!("context malformed: {context_response}"))?;
179        require(health_response.get("entry_counts").and_then(Value::as_object).is_some(), format!("memory_health malformed: {health_response}"))?;
180        require(diagnose_response.get("failure_lessons").and_then(Value::as_array).is_some(), format!("diagnose malformed: {diagnose_response}"))?;
181        require(reflect_response.get("lessons").and_then(Value::as_array).is_some(), format!("reflect malformed: {reflect_response}"))?;
182        require(register_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("register_agent failed: {register_response}"))?;
183        require(agents_response.get("agents").and_then(Value::as_array).map(|items| !items.is_empty()).unwrap_or(false), format!("list_agents failed: {agents_response}"))?;
184        require(archive_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("archive failed: {archive_response}"))?;
185        require(dereference_response.get("found").and_then(Value::as_bool).unwrap_or(false), format!("dereference failed: {dereference_response}"))?;
186        require(checkpoint_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
187        require(outcome_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("record_outcome failed: {outcome_response}"))?;
188        require(strategies_response.get("strategies").and_then(Value::as_array).is_some(), format!("surface_strategies malformed: {strategies_response}"))?;
189        require(handoff_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
190        require(feedback_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
191
192        let strategy_count = strategies_response
193            .get("strategies")
194            .and_then(Value::as_array)
195            .map(|items| items.len())
196            .unwrap_or(0);
197        let agent_count = agents_response
198            .get("agents")
199            .and_then(Value::as_array)
200            .map(|items| items.len())
201            .unwrap_or(0);
202        let lesson_count = lessons_response
203            .get("lessons")
204            .and_then(Value::as_array)
205            .map(|items| items.len())
206            .unwrap_or(0);
207
208        metrics = json!({
209            "run_id": run_id,
210            "agent_count": agent_count,
211            "strategy_count": strategy_count,
212            "reference_id": reference_id,
213            "lesson_count": lesson_count,
214        });
215
216        Ok::<(), Box<dyn Error>>(())
217    }
218    .await;
219
220    if let Err(err) = scenario {
221        passed = false;
222        detail = err.to_string();
223    }
224
225    let cleanup_ok = cleanup_run(&client, &run_id).await;
226    if !cleanup_ok {
227        passed = false;
228        detail = format!("{detail} | cleanup failures");
229    }
230
231    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
232
233    if passed { Ok(()) } else { Err(boxed_error(detail)) }
234}
Source

pub async fn get_context(&self, options: GetContextOptions) -> Result<Value>

Examples found in repository?
examples/public/04_memory_health_and_diagnose.rs (line 43)
13async fn main() -> Result<(), Box<dyn Error>> {
14    let name = "public_04_memory_health_and_diagnose";
15    let started = Instant::now();
16    let client = create_client().await?;
17    let run_id = new_run_id("public_04_memory_health_and_diagnose");
18    client.set_run_id(Some(run_id.clone()));
19    client.set_transport(TransportMode::Http);
20
21    let mut passed = true;
22    let mut detail = "validated helper context + diagnose + memory health flow".to_string();
23    let mut metrics = json!({});
24
25    let scenario = async {
26        let mut remember = RememberOptions::new(
27            "Deploys fail when the migration checksum is stale after a force-push.",
28        );
29        remember.run_id = Some(run_id.clone());
30        remember.agent_id = Some("observer".to_string());
31        remember.intent = Some("lesson".to_string());
32        remember.lesson_type = Some("failure".to_string());
33        remember.lesson_scope = Some("session".to_string());
34        remember.lesson_importance = Some("high".to_string());
35        remember.metadata = Some(json!({ "source": "rust-helper-example" }));
36        client.remember(remember).await?;
37
38        let mut context_opts = GetContextOptions::default();
39        context_opts.run_id = Some(run_id.clone());
40        context_opts.query = Some("Why did the deploy fail?".to_string());
41        context_opts.entry_types = vec!["lesson".to_string()];
42        context_opts.mode = Some("summary".to_string());
43        let context = client.get_context(context_opts).await?;
44
45        let mut diagnose = DiagnoseOptions::new("deploy failed because migration checksum is stale");
46        diagnose.run_id = Some(run_id.clone());
47        diagnose.error_type = Some("deploy".to_string());
48        diagnose.limit = 5;
49        let diagnosis = client.diagnose(diagnose).await?;
50
51        let mut health_opts = MemoryHealthOptions::default();
52        health_opts.run_id = Some(run_id.clone());
53        health_opts.limit = 100;
54        let health = client.memory_health(health_opts).await?;
55
56        let section_summaries = context
57            .get("section_summaries")
58            .and_then(|value| value.as_array())
59            .ok_or_else(|| boxed_error(format!("section summaries missing: {context}")))?;
60        require(
61            diagnosis
62                .get("total_failure_lessons")
63                .and_then(|value| value.as_u64())
64                .unwrap_or(0)
65                >= 1,
66            format!("diagnose should surface a failure lesson: {diagnosis}"),
67        )?;
68        require(
69            health.get("entry_counts").and_then(|value| value.as_object()).is_some(),
70            format!("memory health missing entry counts: {health}"),
71        )?;
72
73        metrics = json!({
74            "run_id": run_id,
75            "section_count": section_summaries.len(),
76            "total_failure_lessons": diagnosis.get("total_failure_lessons").cloned().unwrap_or(serde_json::Value::Null),
77            "entry_count_keys": health.get("entry_counts").and_then(|value| value.as_object()).map(|map| map.len()).unwrap_or(0),
78        });
79
80        Ok::<(), Box<dyn Error>>(())
81    }
82    .await;
83
84    if let Err(err) = scenario {
85        passed = false;
86        detail = err.to_string();
87    }
88
89    let cleanup_ok = cleanup_run(&client, &run_id).await;
90    if !cleanup_ok {
91        passed = false;
92        detail = format!("{detail} | cleanup failures");
93    }
94
95    print_summary(
96        name,
97        passed,
98        &detail,
99        &metrics,
100        started.elapsed().as_secs_f64(),
101        cleanup_ok,
102    );
103
104    if passed {
105        Ok(())
106    } else {
107        Err(boxed_error(detail))
108    }
109}
More examples
Hide additional examples
examples/helper_context_diagnose_memory_health.rs (line 43)
13async fn main() -> Result<(), Box<dyn Error>> {
14    let name = "helper_context_diagnose_memory_health";
15    let started = Instant::now();
16    let client = create_client().await?;
17    let run_id = new_run_id("helper_context_diagnose_memory_health");
18    client.set_run_id(Some(run_id.clone()));
19    client.set_transport(TransportMode::Http);
20
21    let mut passed = true;
22    let mut detail = "validated helper context + diagnose + memory health flow".to_string();
23    let mut metrics = json!({});
24
25    let scenario = async {
26        let mut remember = RememberOptions::new(
27            "Deploys fail when the migration checksum is stale after a force-push.",
28        );
29        remember.run_id = Some(run_id.clone());
30        remember.agent_id = Some("observer".to_string());
31        remember.intent = Some("lesson".to_string());
32        remember.lesson_type = Some("failure".to_string());
33        remember.lesson_scope = Some("session".to_string());
34        remember.lesson_importance = Some("high".to_string());
35        remember.metadata = Some(json!({ "source": "rust-helper-example" }));
36        client.remember(remember).await?;
37
38        let mut context_opts = GetContextOptions::default();
39        context_opts.run_id = Some(run_id.clone());
40        context_opts.query = Some("Why did the deploy fail?".to_string());
41        context_opts.entry_types = vec!["lesson".to_string()];
42        context_opts.mode = Some("summary".to_string());
43        let context = client.get_context(context_opts).await?;
44
45        let mut diagnose = DiagnoseOptions::new("deploy failed because migration checksum is stale");
46        diagnose.run_id = Some(run_id.clone());
47        diagnose.error_type = Some("deploy".to_string());
48        diagnose.limit = 5;
49        let diagnosis = client.diagnose(diagnose).await?;
50
51        let mut health_opts = MemoryHealthOptions::default();
52        health_opts.run_id = Some(run_id.clone());
53        health_opts.limit = 100;
54        let health = client.memory_health(health_opts).await?;
55
56        let section_summaries = context
57            .get("section_summaries")
58            .and_then(|value| value.as_array())
59            .ok_or_else(|| boxed_error(format!("section summaries missing: {context}")))?;
60        require(
61            diagnosis
62                .get("total_failure_lessons")
63                .and_then(|value| value.as_u64())
64                .unwrap_or(0)
65                >= 1,
66            format!("diagnose should surface a failure lesson: {diagnosis}"),
67        )?;
68        require(
69            health.get("entry_counts").and_then(|value| value.as_object()).is_some(),
70            format!("memory health missing entry counts: {health}"),
71        )?;
72
73        metrics = json!({
74            "run_id": run_id,
75            "section_count": section_summaries.len(),
76            "total_failure_lessons": diagnosis.get("total_failure_lessons").cloned().unwrap_or(serde_json::Value::Null),
77            "entry_count_keys": health.get("entry_counts").and_then(|value| value.as_object()).map(|map| map.len()).unwrap_or(0),
78        });
79
80        Ok::<(), Box<dyn Error>>(())
81    }
82    .await;
83
84    if let Err(err) = scenario {
85        passed = false;
86        detail = err.to_string();
87    }
88
89    let cleanup_ok = cleanup_run(&client, &run_id).await;
90    if !cleanup_ok {
91        passed = false;
92        detail = format!("{detail} | cleanup failures");
93    }
94
95    print_summary(
96        name,
97        passed,
98        &detail,
99        &metrics,
100        started.elapsed().as_secs_f64(),
101        cleanup_ok,
102    );
103
104    if passed {
105        Ok(())
106    } else {
107        Err(boxed_error(detail))
108    }
109}
examples/helper_handoff_feedback.rs (line 64)
13async fn main() -> Result<(), Box<dyn Error>> {
14    let name = "helper_handoff_feedback";
15    let started = Instant::now();
16    let client = create_client().await?;
17    let run_id = new_run_id("helper_handoff_feedback");
18    client.set_run_id(Some(run_id.clone()));
19    client.set_transport(TransportMode::Http);
20
21    let mut passed = true;
22    let mut detail = "validated helper handoff + feedback flow".to_string();
23    let mut metrics = json!({});
24
25    let scenario = async {
26        let mut planner = RegisterAgentOptions::new("planner");
27        planner.run_id = Some(run_id.clone());
28        planner.role = "planner".to_string();
29        client.register_agent(planner).await?;
30
31        let mut reviewer = RegisterAgentOptions::new("reviewer");
32        reviewer.run_id = Some(run_id.clone());
33        reviewer.role = "reviewer".to_string();
34        client.register_agent(reviewer).await?;
35
36        let mut handoff = HandoffOptions::new(
37            "task-1",
38            "planner",
39            "reviewer",
40            "Review the retry policy patch before rollout.",
41        );
42        handoff.run_id = Some(run_id.clone());
43        handoff.requested_action = "review".to_string();
44        handoff.metadata = Some(json!({ "source": "rust-helper-example" }));
45        let handoff_response = client.handoff(handoff).await?;
46        let handoff_id = handoff_response
47            .get("handoff_id")
48            .and_then(|value| value.as_str())
49            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
50            .to_string();
51
52        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
53        feedback.run_id = Some(run_id.clone());
54        feedback.comments = "Patch looks safe for rollout.".to_string();
55        feedback.from_agent_id = Some("reviewer".to_string());
56        feedback.metadata = Some(json!({ "source": "rust-helper-example" }));
57        let feedback_response = client.feedback(feedback).await?;
58
59        let mut context = GetContextOptions::default();
60        context.run_id = Some(run_id.clone());
61        context.query = Some("What coordination artifacts were recorded for this review handoff?".to_string());
62        context.mode = Some("sections".to_string());
63        context.sections = vec!["handoffs".to_string(), "feedback".to_string()];
64        let context_response = client.get_context(context).await?;
65
66        require(
67            handoff_response
68                .get("success")
69                .and_then(|value| value.as_bool())
70                .unwrap_or(false),
71            format!("handoff failed: {handoff_response}"),
72        )?;
73        require(
74            feedback_response
75                .get("success")
76                .and_then(|value| value.as_bool())
77                .unwrap_or(false),
78            format!("feedback failed: {feedback_response}"),
79        )?;
80        let section_count = context_response
81            .get("section_summaries")
82            .and_then(|value| value.as_array())
83            .map(|items| items.len())
84            .unwrap_or(0);
85
86        metrics = json!({
87            "run_id": run_id,
88            "handoff_id": handoff_id,
89            "feedback_id": feedback_response.get("feedback_id").cloned().unwrap_or(serde_json::Value::Null),
90            "section_count": section_count,
91        });
92
93        Ok::<(), Box<dyn Error>>(())
94    }
95    .await;
96
97    if let Err(err) = scenario {
98        passed = false;
99        detail = err.to_string();
100    }
101
102    let cleanup_ok = cleanup_run(&client, &run_id).await;
103    if !cleanup_ok {
104        passed = false;
105        detail = format!("{detail} | cleanup failures");
106    }
107
108    print_summary(
109        name,
110        passed,
111        &detail,
112        &metrics,
113        started.elapsed().as_secs_f64(),
114        cleanup_ok,
115    );
116
117    if passed {
118        Ok(())
119    } else {
120        Err(boxed_error(detail))
121    }
122}
examples/public/06_handoff_feedback.rs (line 64)
13async fn main() -> Result<(), Box<dyn Error>> {
14    let name = "public_06_handoff_feedback";
15    let started = Instant::now();
16    let client = create_client().await?;
17    let run_id = new_run_id("public_06_handoff_feedback");
18    client.set_run_id(Some(run_id.clone()));
19    client.set_transport(TransportMode::Http);
20
21    let mut passed = true;
22    let mut detail = "validated helper handoff + feedback flow".to_string();
23    let mut metrics = json!({});
24
25    let scenario = async {
26        let mut planner = RegisterAgentOptions::new("planner");
27        planner.run_id = Some(run_id.clone());
28        planner.role = "planner".to_string();
29        client.register_agent(planner).await?;
30
31        let mut reviewer = RegisterAgentOptions::new("reviewer");
32        reviewer.run_id = Some(run_id.clone());
33        reviewer.role = "reviewer".to_string();
34        client.register_agent(reviewer).await?;
35
36        let mut handoff = HandoffOptions::new(
37            "task-1",
38            "planner",
39            "reviewer",
40            "Review the retry policy patch before rollout.",
41        );
42        handoff.run_id = Some(run_id.clone());
43        handoff.requested_action = "review".to_string();
44        handoff.metadata = Some(json!({ "source": "rust-helper-example" }));
45        let handoff_response = client.handoff(handoff).await?;
46        let handoff_id = handoff_response
47            .get("handoff_id")
48            .and_then(|value| value.as_str())
49            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
50            .to_string();
51
52        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
53        feedback.run_id = Some(run_id.clone());
54        feedback.comments = "Patch looks safe for rollout.".to_string();
55        feedback.from_agent_id = Some("reviewer".to_string());
56        feedback.metadata = Some(json!({ "source": "rust-helper-example" }));
57        let feedback_response = client.feedback(feedback).await?;
58
59        let mut context = GetContextOptions::default();
60        context.run_id = Some(run_id.clone());
61        context.query = Some("What coordination artifacts were recorded for this review handoff?".to_string());
62        context.mode = Some("sections".to_string());
63        context.sections = vec!["handoffs".to_string(), "feedback".to_string()];
64        let context_response = client.get_context(context).await?;
65
66        require(
67            handoff_response
68                .get("success")
69                .and_then(|value| value.as_bool())
70                .unwrap_or(false),
71            format!("handoff failed: {handoff_response}"),
72        )?;
73        require(
74            feedback_response
75                .get("success")
76                .and_then(|value| value.as_bool())
77                .unwrap_or(false),
78            format!("feedback failed: {feedback_response}"),
79        )?;
80        let section_count = context_response
81            .get("section_summaries")
82            .and_then(|value| value.as_array())
83            .map(|items| items.len())
84            .unwrap_or(0);
85
86        metrics = json!({
87            "run_id": run_id,
88            "handoff_id": handoff_id,
89            "feedback_id": feedback_response.get("feedback_id").cloned().unwrap_or(serde_json::Value::Null),
90            "section_count": section_count,
91        });
92
93        Ok::<(), Box<dyn Error>>(())
94    }
95    .await;
96
97    if let Err(err) = scenario {
98        passed = false;
99        detail = err.to_string();
100    }
101
102    let cleanup_ok = cleanup_run(&client, &run_id).await;
103    if !cleanup_ok {
104        passed = false;
105        detail = format!("{detail} | cleanup failures");
106    }
107
108    print_summary(
109        name,
110        passed,
111        &detail,
112        &metrics,
113        started.elapsed().as_secs_f64(),
114        cleanup_ok,
115    );
116
117    if passed {
118        Ok(())
119    } else {
120        Err(boxed_error(detail))
121    }
122}
examples/public/02_context_budget_and_sections.rs (line 63)
11async fn main() -> Result<(), Box<dyn Error>> {
12    let name = "public_02_context_budget_and_sections";
13    let started = Instant::now();
14    let client = create_client().await?;
15    let run_id = new_run_id("public_context_budget");
16    client.set_run_id(Some(run_id.clone()));
17    client.set_transport(TransportMode::Http);
18
19    let mut passed = true;
20    let mut detail = "validated context budgeting and sectioned disclosure".to_string();
21    let mut metrics = json!({});
22
23    let scenario = async {
24        let mut rule = RememberOptions::new("Always lead with policy facts before escalation notes.");
25        rule.run_id = Some(run_id.clone());
26        rule.agent_id = Some("planner".to_string());
27        rule.intent = Some("rule".to_string());
28        rule.metadata = Some(json!({"source": "public-example", "section": "rules"}));
29        rule.importance = Some("critical".to_string());
30        client.remember(rule).await?;
31
32        let mut fact = RememberOptions::new("Claim CLM-4242 has a policy limit of 5000 GBP and a deductible of 250 GBP.");
33        fact.run_id = Some(run_id.clone());
34        fact.agent_id = Some("planner".to_string());
35        fact.intent = Some("fact".to_string());
36        fact.metadata = Some(json!({"source": "public-example", "section": "facts"}));
37        fact.importance = Some("high".to_string());
38        client.remember(fact).await?;
39
40        let mut trace = RememberOptions::new("Planner noted that the claimant is waiting on a same-day callback.");
41        trace.run_id = Some(run_id.clone());
42        trace.agent_id = Some("planner".to_string());
43        trace.intent = Some("trace".to_string());
44        trace.metadata = Some(json!({"source": "public-example", "section": "traces"}));
45        trace.importance = Some("medium".to_string());
46        client.remember(trace).await?;
47
48        let mut mental = RememberOptions::new("Claim CLM-4242 overview: 5000 GBP policy limit, 250 GBP deductible, claimant awaiting same-day callback. Priority: high.");
49        mental.run_id = Some(run_id.clone());
50        mental.agent_id = Some("planner".to_string());
51        mental.intent = Some("mental_model".to_string());
52        mental.metadata = Some(json!({"source": "public-example", "section": "mental_models"}));
53        mental.importance = Some("critical".to_string());
54        client.remember(mental).await?;
55
56        let mut summary_opts = GetContextOptions::default();
57        summary_opts.run_id = Some(run_id.clone());
58        summary_opts.query = Some("Prepare a claims summary.".to_string());
59        summary_opts.mode = Some("summary".to_string());
60        summary_opts.entry_types = vec!["rule".to_string(), "fact".to_string(), "trace".to_string()];
61        summary_opts.max_token_budget = Some(220);
62        summary_opts.limit = Some(6);
63        let summary = client.get_context(summary_opts).await?;
64
65        let mut sections_opts = GetContextOptions::default();
66        sections_opts.run_id = Some(run_id.clone());
67        sections_opts.query = Some("Prepare a claims summary.".to_string());
68        sections_opts.mode = Some("sections".to_string());
69        sections_opts.sections = vec!["mental_models".to_string(), "rules".to_string(), "facts".to_string()];
70        sections_opts.entry_types = vec!["rule".to_string(), "fact".to_string(), "trace".to_string()];
71        sections_opts.max_token_budget = Some(220);
72        sections_opts.limit = Some(6);
73        let sections = client.get_context(sections_opts).await?;
74
75        require(summary.get("context_block").and_then(|v| v.as_str()).unwrap_or("").is_empty(), format!("summary mode should suppress context_block: {summary}"))?;
76        let summary_sections = summary.get("section_summaries").and_then(|v| v.as_array()).ok_or_else(|| boxed_error(format!("summary mode missing section summaries: {summary}")))?;
77        let section_sources = sections.get("sources").and_then(|v| v.as_array()).ok_or_else(|| boxed_error(format!("sections mode missing sources: {sections}")))?;
78        require(!summary_sections.is_empty(), format!("summary mode missing section summaries: {summary}"))?;
79        require(!section_sources.is_empty(), format!("sections mode missing sources: {sections}"))?;
80        require(sections.get("budget_used").and_then(|v| v.as_u64()).unwrap_or(0) >= 1, format!("budget_used missing: {sections}"))?;
81        require(sections.get("budget_remaining").and_then(|v| v.as_u64()).unwrap_or(0) <= 220, format!("budget_remaining missing: {sections}"))?;
82        require(section_sources.iter().any(|s| s.get("entry_type").and_then(|v| v.as_str()) == Some("rule")), format!("expected rule source in sections mode: {sections}"))?;
83
84        metrics = json!({
85            "run_id": run_id,
86            "summary_section_count": summary_sections.len(),
87            "section_source_count": section_sources.len(),
88            "budget_used": sections.get("budget_used").cloned().unwrap_or(serde_json::Value::Null),
89            "budget_remaining": sections.get("budget_remaining").cloned().unwrap_or(serde_json::Value::Null),
90        });
91        Ok::<(), Box<dyn Error>>(())
92    }
93    .await;
94
95    if let Err(err) = scenario {
96        passed = false;
97        detail = err.to_string();
98    }
99
100    let cleanup_ok = cleanup_run(&client, &run_id).await;
101    if !cleanup_ok {
102        passed = false;
103        detail = format!("{detail} | cleanup failures");
104    }
105
106    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
107    if passed { Ok(()) } else { Err(boxed_error(detail)) }
108}
examples/public/11_temporal_entity_mental_model.rs (line 104)
11async fn main() -> Result<(), Box<dyn Error>> {
12    let name = "public_11_temporal_entity_mental_model";
13    let started = Instant::now();
14    let client = create_client().await?;
15    let run_id = new_run_id("public_temporal_entity");
16    client.set_run_id(Some(run_id.clone()));
17    client.set_transport(TransportMode::Http);
18
19    let mut passed = true;
20    let mut detail =
21        "validated temporal queries, entity aliasing, and mental model priority".to_string();
22    let mut metrics = json!({});
23
24    let scenario = async {
25        // 1. Store facts with occurrence_time
26        let now = std::time::SystemTime::now()
27            .duration_since(std::time::UNIX_EPOCH)
28            .unwrap()
29            .as_secs() as i64;
30
31        let mut fact1 =
32            RememberOptions::new("Alice Chen joined the platform team in March 2024.");
33        fact1.run_id = Some(run_id.clone());
34        fact1.intent = Some("fact".to_string());
35        fact1.occurrence_time = Some(now - 86400 * 365); // ~1 year ago
36        fact1.metadata = Some(json!({"speaker": "Alice Chen"}));
37        client.remember(fact1).await?;
38
39        let mut fact2 =
40            RememberOptions::new("Alice was promoted to Senior Engineer in January 2025.");
41        fact2.run_id = Some(run_id.clone());
42        fact2.intent = Some("fact".to_string());
43        fact2.occurrence_time = Some(now - 86400 * 60); // ~2 months ago
44        fact2.metadata = Some(json!({"speaker": "Alice Chen"}));
45        client.remember(fact2).await?;
46
47        let mut fact3 =
48            RememberOptions::new("Dr. Chen published a paper on distributed consensus.");
49        fact3.run_id = Some(run_id.clone());
50        fact3.intent = Some("fact".to_string());
51        fact3.metadata = Some(json!({"speaker": "Alice Chen"}));
52        client.remember(fact3).await?;
53
54        // 2. Store a mental model (curated summary)
55        let mut mental = RememberOptions::new(
56            "Alice Chen (Dr. Chen) is a Senior Engineer on the platform team. \
57             She specializes in distributed consensus and was promoted in January 2025.",
58        );
59        mental.run_id = Some(run_id.clone());
60        mental.intent = Some("mental_model".to_string());
61        mental.importance = Some("critical".to_string());
62        mental.metadata = Some(json!({"entity": "alice chen", "consolidated": true}));
63        client.remember(mental).await?;
64
65        // 3. Recall with temporal bounds (last 90 days)
66        let mut temporal_recall = RecallOptions::new("What happened recently with Alice?");
67        temporal_recall.run_id = Some(run_id.clone());
68        temporal_recall.min_timestamp = Some(now - 86400 * 90);
69        temporal_recall.max_timestamp = Some(now);
70        let temporal_result = client.recall(temporal_recall).await?;
71        let temporal_evidence = temporal_result
72            .get("evidence")
73            .and_then(|v| v.as_array())
74            .ok_or_else(|| {
75                boxed_error("temporal recall missing evidence".to_string())
76            })?;
77        require(
78            !temporal_evidence.is_empty(),
79            format!("temporal recall should return evidence: {temporal_result}"),
80        )?;
81
82        // 4. Recall with budget tier
83        let mut budget_recall = RecallOptions::new("Tell me about Alice Chen");
84        budget_recall.run_id = Some(run_id.clone());
85        budget_recall.budget = Some("high".to_string());
86        let budget_result = client.recall(budget_recall).await?;
87        let budget_evidence = budget_result
88            .get("evidence")
89            .and_then(|v| v.as_array())
90            .ok_or_else(|| {
91                boxed_error("budget recall missing evidence".to_string())
92            })?;
93        require(
94            !budget_evidence.is_empty(),
95            format!("budget recall should return evidence: {budget_result}"),
96        )?;
97
98        // 5. get_context should show Mental Models section first
99        let mut ctx_opts = GetContextOptions::default();
100        ctx_opts.run_id = Some(run_id.clone());
101        ctx_opts.query = Some("Who is Alice Chen?".to_string());
102        ctx_opts.entry_types = vec!["mental_model".to_string(), "fact".to_string()];
103        ctx_opts.limit = Some(10);
104        let ctx = client.get_context(ctx_opts).await?;
105        let context_block = ctx
106            .get("context_block")
107            .and_then(|v| v.as_str())
108            .unwrap_or("");
109        // Mental Models section should appear before Facts
110        let has_mental = context_block.contains("Mental Model");
111        require(
112            has_mental || context_block.contains("mental_model"),
113            format!(
114                "context should include mental model section: {}",
115                &context_block[..context_block.len().min(300)]
116            ),
117        )?;
118
119        metrics = json!({
120            "run_id": run_id,
121            "temporal_evidence_count": temporal_evidence.len(),
122            "budget_evidence_count": budget_evidence.len(),
123            "context_has_mental_model": has_mental,
124            "context_block_length": context_block.len(),
125        });
126        Ok::<(), Box<dyn Error>>(())
127    }
128    .await;
129
130    if let Err(err) = scenario {
131        passed = false;
132        detail = err.to_string();
133    }
134
135    let cleanup_ok = cleanup_run(&client, &run_id).await;
136    if !cleanup_ok {
137        passed = false;
138        detail = format!("{detail} | cleanup failures");
139    }
140
141    print_summary(
142        name,
143        passed,
144        &detail,
145        &metrics,
146        started.elapsed().as_secs_f64(),
147        cleanup_ok,
148    );
149    if passed {
150        Ok(())
151    } else {
152        Err(boxed_error(detail))
153    }
154}
Source

pub async fn archive(&self, options: ArchiveOptions) -> Result<Value>

Examples found in repository?
examples/helper_archive_dereference.rs (line 35)
11async fn main() -> Result<(), Box<dyn Error>> {
12    let name = "helper_archive_dereference";
13    let started = Instant::now();
14    let client = create_client().await?;
15    let run_id = new_run_id("helper_archive_dereference");
16    client.set_run_id(Some(run_id.clone()));
17    client.set_transport(TransportMode::Http);
18
19    let mut passed = true;
20    let mut detail = "validated helper archive + dereference flow".to_string();
21    let mut metrics = json!({});
22
23    let scenario = async {
24        let content =
25            "AssertionError: expected queryset ordering to preserve annotated alias.";
26        let mut archive = ArchiveOptions::new(content, "failing_test_summary");
27        archive.run_id = Some(run_id.clone());
28        archive.agent_id = Some("solver".to_string());
29        archive.source_attempt_id = Some("attempt-1".to_string());
30        archive.source_tool = Some("pytest".to_string());
31        archive.labels = vec!["django".to_string(), "query".to_string()];
32        archive.family = Some("patch-repair".to_string());
33        archive.metadata = Some(json!({ "source": "rust-helper-example" }));
34
35        let archived = client.archive(archive).await?;
36        let reference_id = archived
37            .get("reference_id")
38            .and_then(|value| value.as_str())
39            .ok_or_else(|| boxed_error(format!("archive reference missing: {archived}")))?
40            .to_string();
41
42        let mut dereference = DereferenceOptions::new(reference_id.clone());
43        dereference.run_id = Some(run_id.clone());
44        dereference.agent_id = Some("solver".to_string());
45        let exact = client.dereference(dereference).await?;
46
47        require(
48            archived
49                .get("success")
50                .and_then(|value| value.as_bool())
51                .unwrap_or(false),
52            format!("archive failed: {archived}"),
53        )?;
54        require(
55            exact.get("found")
56                .and_then(|value| value.as_bool())
57                .unwrap_or(false),
58            format!("dereference failed: {exact}"),
59        )?;
60        require(
61            exact.get("evidence")
62                .and_then(|value| value.get("content"))
63                .and_then(|value| value.as_str())
64                == Some(content),
65            format!("dereferenced content mismatch: {exact}"),
66        )?;
67
68        metrics = json!({
69            "run_id": run_id,
70            "reference_id": reference_id,
71            "entry_type": archived.get("entry_type").cloned().unwrap_or(serde_json::Value::Null),
72        });
73
74        Ok::<(), Box<dyn Error>>(())
75    }
76    .await;
77
78    if let Err(err) = scenario {
79        passed = false;
80        detail = err.to_string();
81    }
82
83    let cleanup_ok = cleanup_run(&client, &run_id).await;
84    if !cleanup_ok {
85        passed = false;
86        detail = format!("{detail} | cleanup failures");
87    }
88
89    print_summary(
90        name,
91        passed,
92        &detail,
93        &metrics,
94        started.elapsed().as_secs_f64(),
95        cleanup_ok,
96    );
97
98    if passed {
99        Ok(())
100    } else {
101        Err(boxed_error(detail))
102    }
103}
More examples
Hide additional examples
examples/public/07_archive_dereference.rs (line 35)
11async fn main() -> Result<(), Box<dyn Error>> {
12    let name = "public_07_archive_dereference";
13    let started = Instant::now();
14    let client = create_client().await?;
15    let run_id = new_run_id("public_07_archive_dereference");
16    client.set_run_id(Some(run_id.clone()));
17    client.set_transport(TransportMode::Http);
18
19    let mut passed = true;
20    let mut detail = "validated helper archive + dereference flow".to_string();
21    let mut metrics = json!({});
22
23    let scenario = async {
24        let content =
25            "AssertionError: expected queryset ordering to preserve annotated alias.";
26        let mut archive = ArchiveOptions::new(content, "failing_test_summary");
27        archive.run_id = Some(run_id.clone());
28        archive.agent_id = Some("solver".to_string());
29        archive.source_attempt_id = Some("attempt-1".to_string());
30        archive.source_tool = Some("pytest".to_string());
31        archive.labels = vec!["django".to_string(), "query".to_string()];
32        archive.family = Some("patch-repair".to_string());
33        archive.metadata = Some(json!({ "source": "rust-helper-example" }));
34
35        let archived = client.archive(archive).await?;
36        let reference_id = archived
37            .get("reference_id")
38            .and_then(|value| value.as_str())
39            .ok_or_else(|| boxed_error(format!("archive reference missing: {archived}")))?
40            .to_string();
41
42        let mut dereference = DereferenceOptions::new(reference_id.clone());
43        dereference.run_id = Some(run_id.clone());
44        dereference.agent_id = Some("solver".to_string());
45        let exact = client.dereference(dereference).await?;
46
47        require(
48            archived
49                .get("success")
50                .and_then(|value| value.as_bool())
51                .unwrap_or(false),
52            format!("archive failed: {archived}"),
53        )?;
54        require(
55            exact.get("found")
56                .and_then(|value| value.as_bool())
57                .unwrap_or(false),
58            format!("dereference failed: {exact}"),
59        )?;
60        require(
61            exact.get("evidence")
62                .and_then(|value| value.get("content"))
63                .and_then(|value| value.as_str())
64                == Some(content),
65            format!("dereferenced content mismatch: {exact}"),
66        )?;
67
68        metrics = json!({
69            "run_id": run_id,
70            "reference_id": reference_id,
71            "entry_type": archived.get("entry_type").cloned().unwrap_or(serde_json::Value::Null),
72        });
73
74        Ok::<(), Box<dyn Error>>(())
75    }
76    .await;
77
78    if let Err(err) = scenario {
79        passed = false;
80        detail = err.to_string();
81    }
82
83    let cleanup_ok = cleanup_run(&client, &run_id).await;
84    if !cleanup_ok {
85        passed = false;
86        detail = format!("{detail} | cleanup failures");
87    }
88
89    print_summary(
90        name,
91        passed,
92        &detail,
93        &metrics,
94        started.elapsed().as_secs_f64(),
95        cleanup_ok,
96    );
97
98    if passed {
99        Ok(())
100    } else {
101        Err(boxed_error(detail))
102    }
103}
examples/public/08_multi_agent_claims_or_support_flow.rs (line 53)
11async fn main() -> Result<(), Box<dyn Error>> {
12    let name = "public_08_multi_agent_claims_or_support_flow";
13    let started = Instant::now();
14    let client = create_client().await?;
15    let run_id = new_run_id("public_claims_flow");
16    client.set_run_id(Some(run_id.clone()));
17    client.set_transport(TransportMode::Http);
18
19    let mut passed = true;
20    let mut detail = "validated multi-agent claims/support flow".to_string();
21    let mut metrics = json!({});
22
23    let scenario = async {
24        for (agent_id, role, read_scopes, write_scopes) in [
25            ("intake", "intake", vec!["fact", "archive_block"], vec!["fact", "archive_block", "trace"]),
26            ("coverage", "coverage", vec!["fact", "rule", "archive_block", "handoff", "feedback"], vec!["fact", "trace", "lesson"]),
27            ("reviewer", "reviewer", vec!["fact", "archive_block", "handoff", "feedback", "rule"], vec!["feedback", "rule"]),
28        ] {
29            let mut agent = RegisterAgentOptions::new(agent_id);
30            agent.run_id = Some(run_id.clone());
31            agent.role = role.to_string();
32            agent.read_scopes = read_scopes.into_iter().map(String::from).collect();
33            agent.write_scopes = write_scopes.into_iter().map(String::from).collect();
34            agent.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
35            client.register_agent(agent).await?;
36        }
37
38        let mut fact = RememberOptions::new("Policy P-8842 covers windshield damage with a 250 GBP deductible.");
39        fact.run_id = Some(run_id.clone());
40        fact.agent_id = Some("intake".into());
41        fact.intent = Some("fact".into());
42        fact.metadata = Some(json!({"claim_id": "CLM-8842", "source": "intake-form"}));
43        client.remember(fact).await?;
44
45        let mut archive = ArchiveOptions::new("Exact adjuster note: customer confirmed the damage happened on the motorway and no third party was involved.", "adjuster_note");
46        archive.run_id = Some(run_id.clone());
47        archive.agent_id = Some("intake".into());
48        archive.origin_agent_id = Some("intake".into());
49        archive.source_attempt_id = Some("attempt-1".into());
50        archive.source_tool = Some("claim-review".into());
51        archive.labels = vec!["claims".into(), "coverage".into()];
52        archive.family = Some("windshield".into());
53        let archived = client.archive(archive).await?;
54        let reference_id = archived.get("reference_id").and_then(|v| v.as_str()).ok_or_else(|| boxed_error(format!("archive reference missing: {archived}")))?.to_string();
55
56        let mut checkpoint = CheckpointOptions::new("Coverage verified deductible and adjuster note before escalation.");
57        checkpoint.run_id = Some(run_id.clone());
58        checkpoint.label = Some("pre-review".into());
59        checkpoint.agent_id = Some("coverage".into());
60        checkpoint.metadata = Some(json!({"claim_id": "CLM-8842"}));
61        let checkpoint_response = client.checkpoint(checkpoint).await?;
62
63        let mut handoff = HandoffOptions::new("claim-8842", "coverage", "reviewer", "Review whether the adjuster note is enough to approve the claim.");
64        handoff.run_id = Some(run_id.clone());
65        handoff.requested_action = "review".into();
66        handoff.metadata = Some(json!({"claim_id": "CLM-8842"}));
67        let handoff_response = client.handoff(handoff).await?;
68        let handoff_id = handoff_response.get("handoff_id").and_then(|v| v.as_str()).ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?.to_string();
69
70        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
71        feedback.run_id = Some(run_id.clone());
72        feedback.from_agent_id = Some("reviewer".into());
73        feedback.comments = "Deductible and adjuster note are sufficient for routing.".into();
74        feedback.metadata = Some(json!({"claim_id": "CLM-8842"}));
75        let feedback_response = client.feedback(feedback).await?;
76
77        let mut context_opts = GetContextOptions::default();
78        context_opts.run_id = Some(run_id.clone());
79        context_opts.query = Some("Prepare the final claims routing summary.".into());
80        context_opts.agent_id = Some("coverage".into());
81        context_opts.sections = vec!["archive".into(), "facts".into(), "handoffs".into(), "feedback".into()];
82        context_opts.mode = Some("sections".into());
83        let context = client.get_context(context_opts).await?;
84
85        let mut dereference = DereferenceOptions::new(reference_id.clone());
86        dereference.run_id = Some(run_id.clone());
87        dereference.agent_id = Some("coverage".into());
88        let exact = client.dereference(dereference).await?;
89
90        let mut recall = RecallOptions::new("What deductible applies and what did the adjuster confirm?");
91        recall.run_id = Some(run_id.clone());
92        recall.agent_id = Some("coverage".into());
93        recall.entry_types = vec!["fact".into(), "archive_block".into(), "feedback".into()];
94        let recall_response = client.recall(recall).await?;
95
96        require(checkpoint_response.get("success").and_then(|v| v.as_bool()).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
97        require(handoff_response.get("success").and_then(|v| v.as_bool()).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
98        require(feedback_response.get("success").and_then(|v| v.as_bool()).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
99        require(exact.get("found").and_then(|v| v.as_bool()).unwrap_or(false), format!("dereference failed: {exact}"))?;
100        let context_text = context.get("context_block").and_then(|v| v.as_str()).unwrap_or("").to_lowercase();
101        let recall_text = recall_response.get("final_answer").and_then(|v| v.as_str()).unwrap_or("").to_lowercase();
102        let has_archive_source = context
103            .get("sources")
104            .and_then(|v| v.as_array())
105            .map(|sources| {
106                sources.iter().any(|source| {
107                    source
108                        .get("entry_type")
109                        .and_then(|v| v.as_str())
110                        == Some("archive_block")
111                })
112            })
113            .unwrap_or(false);
114        let exact_refs_surfaced = context
115            .get("exact_references_surfaced")
116            .and_then(|v| v.as_u64())
117            .unwrap_or(0);
118        require(
119            context_text.contains("adjuster note")
120                || context_text.contains("motorway")
121                || has_archive_source
122                || exact_refs_surfaced > 0,
123            format!("expected explicit or telemetry-backed exact reuse in context: {context}"),
124        )?;
125        require(recall_text.contains("250") && (recall_text.contains("motorway") || recall_text.contains("third party")), format!("expected recall to include fact + archive content: {recall_response}"))?;
126
127        metrics = json!({
128            "run_id": run_id,
129            "handoff_id": handoff_id,
130            "reference_id": reference_id,
131            "feedback_id": feedback_response.get("feedback_id").cloned().unwrap_or(serde_json::Value::Null),
132        });
133        Ok::<(), Box<dyn Error>>(())
134    }
135    .await;
136
137    if let Err(err) = scenario {
138        passed = false;
139        detail = err.to_string();
140    }
141
142    let cleanup_ok = cleanup_run(&client, &run_id).await;
143    if !cleanup_ok {
144        passed = false;
145        detail = format!("{detail} | cleanup failures");
146    }
147
148    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
149    if passed { Ok(()) } else { Err(boxed_error(detail)) }
150}
examples/public/10_full_learning_loop_smoke.rs (line 111)
16async fn main() -> Result<(), Box<dyn Error>> {
17    let name = "public_10_full_learning_loop_smoke";
18    let started = Instant::now();
19    let client = create_client().await?;
20    let run_id = new_run_id("public_10_full_learning_loop_smoke");
21    client.set_run_id(Some(run_id.clone()));
22    client.set_transport(TransportMode::Http);
23
24    let mut passed = true;
25    let mut detail = "validated all helper flows".to_string();
26    let mut metrics = json!({});
27
28    let scenario = async {
29        let mut remember = RememberOptions::new("Policy limit is 5000 and claimant city is Leeds.");
30        remember.run_id = Some(run_id.clone());
31        remember.agent_id = Some("planner".to_string());
32        remember.intent = Some("fact".to_string());
33        remember.metadata = Some(json!({"suite": "all-helpers", "family": "claims"}));
34        remember.importance = Some("high".to_string());
35        remember.occurrence_time = Some(std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as i64 - 86400);
36        let remember_response = client.remember(remember).await?;
37
38        let mut lesson = RememberOptions::new("If city is missing from the latest step, check stored claim facts before escalating.");
39        lesson.run_id = Some(run_id.clone());
40        lesson.agent_id = Some("planner".to_string());
41        lesson.intent = Some("lesson".to_string());
42        lesson.lesson_type = Some("success".to_string());
43        lesson.lesson_scope = Some("session".to_string());
44        lesson.lesson_importance = Some("high".to_string());
45        let lesson_response = client.remember(lesson).await?;
46
47        let mut mental_model = RememberOptions::new(
48            "Claims case overview: Policy limit 5000 GBP, claimant city Leeds, \
49             missing-city branch resolved via stored claim facts. Lesson: check stored facts before escalating.",
50        );
51        mental_model.run_id = Some(run_id.clone());
52        mental_model.agent_id = Some("planner".to_string());
53        mental_model.intent = Some("mental_model".to_string());
54        mental_model.importance = Some("critical".to_string());
55        mental_model.metadata = Some(json!({"suite": "all-helpers", "entity": "claims-case", "consolidated": true}));
56        let mental_model_response = client.remember(mental_model).await?;
57
58        let mut recall = RecallOptions::new("What is the policy limit?");
59        recall.run_id = Some(run_id.clone());
60        recall.agent_id = Some("planner".to_string());
61        recall.limit = 5;
62        let recall_response = client.recall(recall).await?;
63
64        let mut context = GetContextOptions::default();
65        context.run_id = Some(run_id.clone());
66        context.query = Some("Prepare a short adjuster summary".to_string());
67        context.agent_id = Some("planner".to_string());
68        context.limit = Some(6);
69        context.max_token_budget = Some(700);
70        let context_response = client.get_context(context).await?;
71
72        let mut health = MemoryHealthOptions::default();
73        health.run_id = Some(run_id.clone());
74        health.limit = 50;
75        let health_response = client.memory_health(health).await?;
76
77        let mut diagnose = DiagnoseOptions::new("policy limit lookup returned empty");
78        diagnose.run_id = Some(run_id.clone());
79        diagnose.error_type = Some("retrieval".to_string());
80        diagnose.limit = 5;
81        let diagnose_response = client.diagnose(diagnose).await?;
82
83        let mut reflect = ReflectOptions::default();
84        reflect.run_id = Some(run_id.clone());
85        let reflect_response = client.reflect(reflect).await?;
86
87        let mut register = RegisterAgentOptions::new("planner");
88        register.run_id = Some(run_id.clone());
89        register.role = "planner".to_string();
90        register.read_scopes = vec!["fact".into(), "lesson".into(), "rule".into(), "mental_model".into(), "archive_block".into(), "handoff".into(), "feedback".into()];
91        register.write_scopes = vec!["fact".into(), "trace".into(), "lesson".into(), "observation".into(), "archive_block".into()];
92        register.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
93        let register_response = client.register_agent(register).await?;
94
95        let mut list_agents = ListAgentsOptions::default();
96        list_agents.run_id = Some(run_id.clone());
97        let agents_response = client.list_agents(list_agents).await?;
98
99        let mut archive = ArchiveOptions::new(
100            "Exact adjuster note: claimant confirmed city is Leeds during triage.",
101            "adjuster_note",
102        );
103        archive.run_id = Some(run_id.clone());
104        archive.agent_id = Some("planner".to_string());
105        archive.origin_agent_id = Some("planner".to_string());
106        archive.source_attempt_id = Some("attempt-1".to_string());
107        archive.source_tool = Some("phone_call".to_string());
108        archive.labels = vec!["claims".to_string(), "triage".to_string()];
109        archive.family = Some("claims-adjustment".to_string());
110        archive.metadata = Some(json!({"case": "all-helpers"}));
111        let archive_response = client.archive(archive).await?;
112        let reference_id = archive_response
113            .get("reference_id")
114            .and_then(Value::as_str)
115            .ok_or_else(|| boxed_error(format!("archive reference missing: {archive_response}")))?
116            .to_string();
117
118        let mut dereference = DereferenceOptions::new(reference_id.clone());
119        dereference.run_id = Some(run_id.clone());
120        dereference.agent_id = Some("planner".to_string());
121        let dereference_response = client.dereference(dereference).await?;
122
123        let mut checkpoint = CheckpointOptions::new("Planner captured claim facts before window compaction.");
124        checkpoint.run_id = Some(run_id.clone());
125        checkpoint.label = Some("pre-compaction".to_string());
126        checkpoint.metadata = Some(json!({"stage": "analysis"}));
127        checkpoint.agent_id = Some("planner".to_string());
128        let checkpoint_response = client.checkpoint(checkpoint).await?;
129
130        let lessons_response = client.control.lessons(json!({"run_id": run_id, "limit": 20})).await?;
131        let lesson_id = lessons_response
132            .get("lessons")
133            .and_then(Value::as_array)
134            .and_then(|items| items.iter().find_map(|item| item.get("id").and_then(Value::as_str)))
135            .ok_or_else(|| boxed_error(format!("expected lesson id for outcome flow: {lessons_response}")))?
136            .to_string();
137
138        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
139        outcome.run_id = Some(run_id.clone());
140        outcome.signal = 0.75;
141        outcome.rationale = "Planner reused stored claim fact and resolved the missing-city branch.".to_string();
142        outcome.agent_id = Some("planner".to_string());
143        let outcome_response = client.record_outcome(outcome).await?;
144
145        let mut strategies = SurfaceStrategiesOptions::default();
146        strategies.run_id = Some(run_id.clone());
147        strategies.lesson_types = vec!["success".to_string(), "rule".to_string()];
148        strategies.max_strategies = 5;
149        let strategies_response = client.surface_strategies(strategies).await?;
150
151        let mut handoff = HandoffOptions::new(
152            "claim-1",
153            "planner",
154            "reviewer",
155            "Review whether the stored claimant city is sufficient for routing.",
156        );
157        handoff.run_id = Some(run_id.clone());
158        handoff.requested_action = "review".to_string();
159        handoff.metadata = Some(json!({"team": "claims"}));
160        let handoff_response = client.handoff(handoff).await?;
161        let handoff_id = handoff_response
162            .get("handoff_id")
163            .and_then(Value::as_str)
164            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
165            .to_string();
166
167        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
168        feedback.run_id = Some(run_id.clone());
169        feedback.comments = "Stored fact is sufficient; proceed without escalation.".to_string();
170        feedback.from_agent_id = Some("reviewer".to_string());
171        feedback.metadata = Some(json!({"team": "claims"}));
172        let feedback_response = client.feedback(feedback).await?;
173
174        require(remember_response.get("job_id").is_some() || remember_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("remember failed: {remember_response}"))?;
175        require(mental_model_response.get("job_id").is_some() || mental_model_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("mental_model remember failed: {mental_model_response}"))?;
176        require(lesson_response.get("job_id").is_some() || lesson_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("lesson remember failed: {lesson_response}"))?;
177        require(recall_response.get("final_answer").is_some() || recall_response.get("evidence").is_some(), format!("recall failed: {recall_response}"))?;
178        require(context_response.get("sources").and_then(Value::as_array).is_some(), format!("context malformed: {context_response}"))?;
179        require(health_response.get("entry_counts").and_then(Value::as_object).is_some(), format!("memory_health malformed: {health_response}"))?;
180        require(diagnose_response.get("failure_lessons").and_then(Value::as_array).is_some(), format!("diagnose malformed: {diagnose_response}"))?;
181        require(reflect_response.get("lessons").and_then(Value::as_array).is_some(), format!("reflect malformed: {reflect_response}"))?;
182        require(register_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("register_agent failed: {register_response}"))?;
183        require(agents_response.get("agents").and_then(Value::as_array).map(|items| !items.is_empty()).unwrap_or(false), format!("list_agents failed: {agents_response}"))?;
184        require(archive_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("archive failed: {archive_response}"))?;
185        require(dereference_response.get("found").and_then(Value::as_bool).unwrap_or(false), format!("dereference failed: {dereference_response}"))?;
186        require(checkpoint_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
187        require(outcome_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("record_outcome failed: {outcome_response}"))?;
188        require(strategies_response.get("strategies").and_then(Value::as_array).is_some(), format!("surface_strategies malformed: {strategies_response}"))?;
189        require(handoff_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
190        require(feedback_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
191
192        let strategy_count = strategies_response
193            .get("strategies")
194            .and_then(Value::as_array)
195            .map(|items| items.len())
196            .unwrap_or(0);
197        let agent_count = agents_response
198            .get("agents")
199            .and_then(Value::as_array)
200            .map(|items| items.len())
201            .unwrap_or(0);
202        let lesson_count = lessons_response
203            .get("lessons")
204            .and_then(Value::as_array)
205            .map(|items| items.len())
206            .unwrap_or(0);
207
208        metrics = json!({
209            "run_id": run_id,
210            "agent_count": agent_count,
211            "strategy_count": strategy_count,
212            "reference_id": reference_id,
213            "lesson_count": lesson_count,
214        });
215
216        Ok::<(), Box<dyn Error>>(())
217    }
218    .await;
219
220    if let Err(err) = scenario {
221        passed = false;
222        detail = err.to_string();
223    }
224
225    let cleanup_ok = cleanup_run(&client, &run_id).await;
226    if !cleanup_ok {
227        passed = false;
228        detail = format!("{detail} | cleanup failures");
229    }
230
231    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
232
233    if passed { Ok(()) } else { Err(boxed_error(detail)) }
234}
examples/helper_all_helpers.rs (line 99)
16async fn main() -> Result<(), Box<dyn Error>> {
17    let name = "helper_all_helpers";
18    let started = Instant::now();
19    let client = create_client().await?;
20    let run_id = new_run_id("helper_all_helpers");
21    client.set_run_id(Some(run_id.clone()));
22    client.set_transport(TransportMode::Http);
23
24    let mut passed = true;
25    let mut detail = "validated all helper flows".to_string();
26    let mut metrics = json!({});
27
28    let scenario = async {
29        let mut remember = RememberOptions::new("Policy limit is 5000 and claimant city is Leeds.");
30        remember.run_id = Some(run_id.clone());
31        remember.agent_id = Some("planner".to_string());
32        remember.intent = Some("fact".to_string());
33        remember.metadata = Some(json!({"suite": "all-helpers", "family": "claims"}));
34        remember.importance = Some("high".to_string());
35        let remember_response = client.remember(remember).await?;
36
37        let mut lesson = RememberOptions::new("If city is missing from the latest step, check stored claim facts before escalating.");
38        lesson.run_id = Some(run_id.clone());
39        lesson.agent_id = Some("planner".to_string());
40        lesson.intent = Some("lesson".to_string());
41        lesson.lesson_type = Some("success".to_string());
42        lesson.lesson_scope = Some("session".to_string());
43        lesson.lesson_importance = Some("high".to_string());
44        let lesson_response = client.remember(lesson).await?;
45
46        let mut recall = RecallOptions::new("What is the policy limit?");
47        recall.run_id = Some(run_id.clone());
48        recall.agent_id = Some("planner".to_string());
49        recall.limit = 5;
50        let recall_response = client.recall(recall).await?;
51
52        let mut context = GetContextOptions::default();
53        context.run_id = Some(run_id.clone());
54        context.query = Some("Prepare a short adjuster summary".to_string());
55        context.agent_id = Some("planner".to_string());
56        context.limit = Some(6);
57        context.max_token_budget = Some(700);
58        let context_response = client.get_context(context).await?;
59
60        let mut health = MemoryHealthOptions::default();
61        health.run_id = Some(run_id.clone());
62        health.limit = 50;
63        let health_response = client.memory_health(health).await?;
64
65        let mut diagnose = DiagnoseOptions::new("policy limit lookup returned empty");
66        diagnose.run_id = Some(run_id.clone());
67        diagnose.error_type = Some("retrieval".to_string());
68        diagnose.limit = 5;
69        let diagnose_response = client.diagnose(diagnose).await?;
70
71        let mut reflect = ReflectOptions::default();
72        reflect.run_id = Some(run_id.clone());
73        let reflect_response = client.reflect(reflect).await?;
74
75        let mut register = RegisterAgentOptions::new("planner");
76        register.run_id = Some(run_id.clone());
77        register.role = "planner".to_string();
78        register.read_scopes = vec!["fact".into(), "lesson".into(), "rule".into(), "archive_block".into(), "handoff".into(), "feedback".into()];
79        register.write_scopes = vec!["fact".into(), "trace".into(), "lesson".into(), "observation".into(), "archive_block".into()];
80        register.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
81        let register_response = client.register_agent(register).await?;
82
83        let mut list_agents = ListAgentsOptions::default();
84        list_agents.run_id = Some(run_id.clone());
85        let agents_response = client.list_agents(list_agents).await?;
86
87        let mut archive = ArchiveOptions::new(
88            "Exact adjuster note: claimant confirmed city is Leeds during triage.",
89            "adjuster_note",
90        );
91        archive.run_id = Some(run_id.clone());
92        archive.agent_id = Some("planner".to_string());
93        archive.origin_agent_id = Some("planner".to_string());
94        archive.source_attempt_id = Some("attempt-1".to_string());
95        archive.source_tool = Some("phone_call".to_string());
96        archive.labels = vec!["claims".to_string(), "triage".to_string()];
97        archive.family = Some("claims-adjustment".to_string());
98        archive.metadata = Some(json!({"case": "all-helpers"}));
99        let archive_response = client.archive(archive).await?;
100        let reference_id = archive_response
101            .get("reference_id")
102            .and_then(Value::as_str)
103            .ok_or_else(|| boxed_error(format!("archive reference missing: {archive_response}")))?
104            .to_string();
105
106        let mut dereference = DereferenceOptions::new(reference_id.clone());
107        dereference.run_id = Some(run_id.clone());
108        dereference.agent_id = Some("planner".to_string());
109        let dereference_response = client.dereference(dereference).await?;
110
111        let mut checkpoint = CheckpointOptions::new("Planner captured claim facts before window compaction.");
112        checkpoint.run_id = Some(run_id.clone());
113        checkpoint.label = Some("pre-compaction".to_string());
114        checkpoint.metadata = Some(json!({"stage": "analysis"}));
115        checkpoint.agent_id = Some("planner".to_string());
116        let checkpoint_response = client.checkpoint(checkpoint).await?;
117
118        let lessons_response = client.control.lessons(json!({"run_id": run_id, "limit": 20})).await?;
119        let lesson_id = lessons_response
120            .get("lessons")
121            .and_then(Value::as_array)
122            .and_then(|items| items.iter().find_map(|item| item.get("id").and_then(Value::as_str)))
123            .ok_or_else(|| boxed_error(format!("expected lesson id for outcome flow: {lessons_response}")))?
124            .to_string();
125
126        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
127        outcome.run_id = Some(run_id.clone());
128        outcome.signal = 0.75;
129        outcome.rationale = "Planner reused stored claim fact and resolved the missing-city branch.".to_string();
130        outcome.agent_id = Some("planner".to_string());
131        let outcome_response = client.record_outcome(outcome).await?;
132
133        let mut strategies = SurfaceStrategiesOptions::default();
134        strategies.run_id = Some(run_id.clone());
135        strategies.lesson_types = vec!["success".to_string(), "rule".to_string()];
136        strategies.max_strategies = 5;
137        let strategies_response = client.surface_strategies(strategies).await?;
138
139        let mut handoff = HandoffOptions::new(
140            "claim-1",
141            "planner",
142            "reviewer",
143            "Review whether the stored claimant city is sufficient for routing.",
144        );
145        handoff.run_id = Some(run_id.clone());
146        handoff.requested_action = "review".to_string();
147        handoff.metadata = Some(json!({"team": "claims"}));
148        let handoff_response = client.handoff(handoff).await?;
149        let handoff_id = handoff_response
150            .get("handoff_id")
151            .and_then(Value::as_str)
152            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
153            .to_string();
154
155        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
156        feedback.run_id = Some(run_id.clone());
157        feedback.comments = "Stored fact is sufficient; proceed without escalation.".to_string();
158        feedback.from_agent_id = Some("reviewer".to_string());
159        feedback.metadata = Some(json!({"team": "claims"}));
160        let feedback_response = client.feedback(feedback).await?;
161
162        let scratch_run = format!("{run_id}_forget");
163        let mut scratch = RememberOptions::new("Scratch run for forget helper coverage.");
164        scratch.run_id = Some(scratch_run.clone());
165        scratch.agent_id = Some("planner".to_string());
166        scratch.intent = Some("fact".to_string());
167        scratch.metadata = Some(json!({"suite": "all-helpers", "temporary": true}));
168        let scratch_response = client.remember(scratch).await?;
169
170        let forget_response = client
171            .forget(ForgetOptions::for_run(scratch_run.clone()))
172            .await?;
173
174        let mut forgotten = RecallOptions::new("What temporary scratch fact exists?");
175        forgotten.run_id = Some(scratch_run.clone());
176        forgotten.limit = 3;
177        let forgotten_response = client.recall(forgotten).await?;
178
179        require(remember_response.get("job_id").is_some() || remember_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("remember failed: {remember_response}"))?;
180        require(lesson_response.get("job_id").is_some() || lesson_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("lesson remember failed: {lesson_response}"))?;
181        require(recall_response.get("final_answer").is_some() || recall_response.get("evidence").is_some(), format!("recall failed: {recall_response}"))?;
182        require(context_response.get("sources").and_then(Value::as_array).is_some(), format!("context malformed: {context_response}"))?;
183        require(health_response.get("entry_counts").and_then(Value::as_object).is_some(), format!("memory_health malformed: {health_response}"))?;
184        require(diagnose_response.get("failure_lessons").and_then(Value::as_array).is_some(), format!("diagnose malformed: {diagnose_response}"))?;
185        require(reflect_response.get("lessons").and_then(Value::as_array).is_some(), format!("reflect malformed: {reflect_response}"))?;
186        require(register_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("register_agent failed: {register_response}"))?;
187        require(agents_response.get("agents").and_then(Value::as_array).map(|items| !items.is_empty()).unwrap_or(false), format!("list_agents failed: {agents_response}"))?;
188        require(archive_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("archive failed: {archive_response}"))?;
189        require(dereference_response.get("found").and_then(Value::as_bool).unwrap_or(false), format!("dereference failed: {dereference_response}"))?;
190        require(checkpoint_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
191        require(outcome_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("record_outcome failed: {outcome_response}"))?;
192        require(strategies_response.get("strategies").and_then(Value::as_array).is_some(), format!("surface_strategies malformed: {strategies_response}"))?;
193        require(handoff_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
194        require(feedback_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
195        require(scratch_response.get("job_id").is_some() || scratch_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("scratch remember failed: {scratch_response}"))?;
196        require(forget_response.get("success").and_then(Value::as_bool).unwrap_or(true), format!("forget failed: {forget_response}"))?;
197        let scratch_fact_visible = forgotten_response
198            .get("evidence")
199            .and_then(Value::as_array)
200            .map(|items| {
201                items.iter().any(|item| {
202                    item.get("run_id").and_then(Value::as_str) == Some(scratch_run.as_str())
203                        || item
204                            .get("content")
205                            .and_then(Value::as_str)
206                            .map(|content| {
207                                content
208                                    .to_ascii_lowercase()
209                                    .contains("scratch run for forget helper coverage")
210                            })
211                            .unwrap_or(false)
212                })
213            })
214            .unwrap_or(false);
215        require(!scratch_fact_visible, format!("scratch fact should be forgotten even if same-user lessons still surface: {forgotten_response}"))?;
216
217        let strategy_count = strategies_response
218            .get("strategies")
219            .and_then(Value::as_array)
220            .map(|items| items.len())
221            .unwrap_or(0);
222        let agent_count = agents_response
223            .get("agents")
224            .and_then(Value::as_array)
225            .map(|items| items.len())
226            .unwrap_or(0);
227        let lesson_count = lessons_response
228            .get("lessons")
229            .and_then(Value::as_array)
230            .map(|items| items.len())
231            .unwrap_or(0);
232
233        metrics = json!({
234            "run_id": run_id,
235            "agent_count": agent_count,
236            "strategy_count": strategy_count,
237            "reference_id": reference_id,
238            "lesson_count": lesson_count,
239            "forgotten_run": scratch_run,
240        });
241
242        Ok::<(), Box<dyn Error>>(())
243    }
244    .await;
245
246    if let Err(err) = scenario {
247        passed = false;
248        detail = err.to_string();
249    }
250
251    let cleanup_ok = cleanup_run(&client, &run_id).await;
252    if !cleanup_ok {
253        passed = false;
254        detail = format!("{detail} | cleanup failures");
255    }
256
257    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
258
259    if passed { Ok(()) } else { Err(boxed_error(detail)) }
260}
Source

pub async fn archive_block(&self, options: ArchiveOptions) -> Result<Value>

Source

pub async fn dereference(&self, options: DereferenceOptions) -> Result<Value>

Examples found in repository?
examples/helper_archive_dereference.rs (line 45)
11async fn main() -> Result<(), Box<dyn Error>> {
12    let name = "helper_archive_dereference";
13    let started = Instant::now();
14    let client = create_client().await?;
15    let run_id = new_run_id("helper_archive_dereference");
16    client.set_run_id(Some(run_id.clone()));
17    client.set_transport(TransportMode::Http);
18
19    let mut passed = true;
20    let mut detail = "validated helper archive + dereference flow".to_string();
21    let mut metrics = json!({});
22
23    let scenario = async {
24        let content =
25            "AssertionError: expected queryset ordering to preserve annotated alias.";
26        let mut archive = ArchiveOptions::new(content, "failing_test_summary");
27        archive.run_id = Some(run_id.clone());
28        archive.agent_id = Some("solver".to_string());
29        archive.source_attempt_id = Some("attempt-1".to_string());
30        archive.source_tool = Some("pytest".to_string());
31        archive.labels = vec!["django".to_string(), "query".to_string()];
32        archive.family = Some("patch-repair".to_string());
33        archive.metadata = Some(json!({ "source": "rust-helper-example" }));
34
35        let archived = client.archive(archive).await?;
36        let reference_id = archived
37            .get("reference_id")
38            .and_then(|value| value.as_str())
39            .ok_or_else(|| boxed_error(format!("archive reference missing: {archived}")))?
40            .to_string();
41
42        let mut dereference = DereferenceOptions::new(reference_id.clone());
43        dereference.run_id = Some(run_id.clone());
44        dereference.agent_id = Some("solver".to_string());
45        let exact = client.dereference(dereference).await?;
46
47        require(
48            archived
49                .get("success")
50                .and_then(|value| value.as_bool())
51                .unwrap_or(false),
52            format!("archive failed: {archived}"),
53        )?;
54        require(
55            exact.get("found")
56                .and_then(|value| value.as_bool())
57                .unwrap_or(false),
58            format!("dereference failed: {exact}"),
59        )?;
60        require(
61            exact.get("evidence")
62                .and_then(|value| value.get("content"))
63                .and_then(|value| value.as_str())
64                == Some(content),
65            format!("dereferenced content mismatch: {exact}"),
66        )?;
67
68        metrics = json!({
69            "run_id": run_id,
70            "reference_id": reference_id,
71            "entry_type": archived.get("entry_type").cloned().unwrap_or(serde_json::Value::Null),
72        });
73
74        Ok::<(), Box<dyn Error>>(())
75    }
76    .await;
77
78    if let Err(err) = scenario {
79        passed = false;
80        detail = err.to_string();
81    }
82
83    let cleanup_ok = cleanup_run(&client, &run_id).await;
84    if !cleanup_ok {
85        passed = false;
86        detail = format!("{detail} | cleanup failures");
87    }
88
89    print_summary(
90        name,
91        passed,
92        &detail,
93        &metrics,
94        started.elapsed().as_secs_f64(),
95        cleanup_ok,
96    );
97
98    if passed {
99        Ok(())
100    } else {
101        Err(boxed_error(detail))
102    }
103}
More examples
Hide additional examples
examples/public/07_archive_dereference.rs (line 45)
11async fn main() -> Result<(), Box<dyn Error>> {
12    let name = "public_07_archive_dereference";
13    let started = Instant::now();
14    let client = create_client().await?;
15    let run_id = new_run_id("public_07_archive_dereference");
16    client.set_run_id(Some(run_id.clone()));
17    client.set_transport(TransportMode::Http);
18
19    let mut passed = true;
20    let mut detail = "validated helper archive + dereference flow".to_string();
21    let mut metrics = json!({});
22
23    let scenario = async {
24        let content =
25            "AssertionError: expected queryset ordering to preserve annotated alias.";
26        let mut archive = ArchiveOptions::new(content, "failing_test_summary");
27        archive.run_id = Some(run_id.clone());
28        archive.agent_id = Some("solver".to_string());
29        archive.source_attempt_id = Some("attempt-1".to_string());
30        archive.source_tool = Some("pytest".to_string());
31        archive.labels = vec!["django".to_string(), "query".to_string()];
32        archive.family = Some("patch-repair".to_string());
33        archive.metadata = Some(json!({ "source": "rust-helper-example" }));
34
35        let archived = client.archive(archive).await?;
36        let reference_id = archived
37            .get("reference_id")
38            .and_then(|value| value.as_str())
39            .ok_or_else(|| boxed_error(format!("archive reference missing: {archived}")))?
40            .to_string();
41
42        let mut dereference = DereferenceOptions::new(reference_id.clone());
43        dereference.run_id = Some(run_id.clone());
44        dereference.agent_id = Some("solver".to_string());
45        let exact = client.dereference(dereference).await?;
46
47        require(
48            archived
49                .get("success")
50                .and_then(|value| value.as_bool())
51                .unwrap_or(false),
52            format!("archive failed: {archived}"),
53        )?;
54        require(
55            exact.get("found")
56                .and_then(|value| value.as_bool())
57                .unwrap_or(false),
58            format!("dereference failed: {exact}"),
59        )?;
60        require(
61            exact.get("evidence")
62                .and_then(|value| value.get("content"))
63                .and_then(|value| value.as_str())
64                == Some(content),
65            format!("dereferenced content mismatch: {exact}"),
66        )?;
67
68        metrics = json!({
69            "run_id": run_id,
70            "reference_id": reference_id,
71            "entry_type": archived.get("entry_type").cloned().unwrap_or(serde_json::Value::Null),
72        });
73
74        Ok::<(), Box<dyn Error>>(())
75    }
76    .await;
77
78    if let Err(err) = scenario {
79        passed = false;
80        detail = err.to_string();
81    }
82
83    let cleanup_ok = cleanup_run(&client, &run_id).await;
84    if !cleanup_ok {
85        passed = false;
86        detail = format!("{detail} | cleanup failures");
87    }
88
89    print_summary(
90        name,
91        passed,
92        &detail,
93        &metrics,
94        started.elapsed().as_secs_f64(),
95        cleanup_ok,
96    );
97
98    if passed {
99        Ok(())
100    } else {
101        Err(boxed_error(detail))
102    }
103}
examples/public/08_multi_agent_claims_or_support_flow.rs (line 88)
11async fn main() -> Result<(), Box<dyn Error>> {
12    let name = "public_08_multi_agent_claims_or_support_flow";
13    let started = Instant::now();
14    let client = create_client().await?;
15    let run_id = new_run_id("public_claims_flow");
16    client.set_run_id(Some(run_id.clone()));
17    client.set_transport(TransportMode::Http);
18
19    let mut passed = true;
20    let mut detail = "validated multi-agent claims/support flow".to_string();
21    let mut metrics = json!({});
22
23    let scenario = async {
24        for (agent_id, role, read_scopes, write_scopes) in [
25            ("intake", "intake", vec!["fact", "archive_block"], vec!["fact", "archive_block", "trace"]),
26            ("coverage", "coverage", vec!["fact", "rule", "archive_block", "handoff", "feedback"], vec!["fact", "trace", "lesson"]),
27            ("reviewer", "reviewer", vec!["fact", "archive_block", "handoff", "feedback", "rule"], vec!["feedback", "rule"]),
28        ] {
29            let mut agent = RegisterAgentOptions::new(agent_id);
30            agent.run_id = Some(run_id.clone());
31            agent.role = role.to_string();
32            agent.read_scopes = read_scopes.into_iter().map(String::from).collect();
33            agent.write_scopes = write_scopes.into_iter().map(String::from).collect();
34            agent.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
35            client.register_agent(agent).await?;
36        }
37
38        let mut fact = RememberOptions::new("Policy P-8842 covers windshield damage with a 250 GBP deductible.");
39        fact.run_id = Some(run_id.clone());
40        fact.agent_id = Some("intake".into());
41        fact.intent = Some("fact".into());
42        fact.metadata = Some(json!({"claim_id": "CLM-8842", "source": "intake-form"}));
43        client.remember(fact).await?;
44
45        let mut archive = ArchiveOptions::new("Exact adjuster note: customer confirmed the damage happened on the motorway and no third party was involved.", "adjuster_note");
46        archive.run_id = Some(run_id.clone());
47        archive.agent_id = Some("intake".into());
48        archive.origin_agent_id = Some("intake".into());
49        archive.source_attempt_id = Some("attempt-1".into());
50        archive.source_tool = Some("claim-review".into());
51        archive.labels = vec!["claims".into(), "coverage".into()];
52        archive.family = Some("windshield".into());
53        let archived = client.archive(archive).await?;
54        let reference_id = archived.get("reference_id").and_then(|v| v.as_str()).ok_or_else(|| boxed_error(format!("archive reference missing: {archived}")))?.to_string();
55
56        let mut checkpoint = CheckpointOptions::new("Coverage verified deductible and adjuster note before escalation.");
57        checkpoint.run_id = Some(run_id.clone());
58        checkpoint.label = Some("pre-review".into());
59        checkpoint.agent_id = Some("coverage".into());
60        checkpoint.metadata = Some(json!({"claim_id": "CLM-8842"}));
61        let checkpoint_response = client.checkpoint(checkpoint).await?;
62
63        let mut handoff = HandoffOptions::new("claim-8842", "coverage", "reviewer", "Review whether the adjuster note is enough to approve the claim.");
64        handoff.run_id = Some(run_id.clone());
65        handoff.requested_action = "review".into();
66        handoff.metadata = Some(json!({"claim_id": "CLM-8842"}));
67        let handoff_response = client.handoff(handoff).await?;
68        let handoff_id = handoff_response.get("handoff_id").and_then(|v| v.as_str()).ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?.to_string();
69
70        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
71        feedback.run_id = Some(run_id.clone());
72        feedback.from_agent_id = Some("reviewer".into());
73        feedback.comments = "Deductible and adjuster note are sufficient for routing.".into();
74        feedback.metadata = Some(json!({"claim_id": "CLM-8842"}));
75        let feedback_response = client.feedback(feedback).await?;
76
77        let mut context_opts = GetContextOptions::default();
78        context_opts.run_id = Some(run_id.clone());
79        context_opts.query = Some("Prepare the final claims routing summary.".into());
80        context_opts.agent_id = Some("coverage".into());
81        context_opts.sections = vec!["archive".into(), "facts".into(), "handoffs".into(), "feedback".into()];
82        context_opts.mode = Some("sections".into());
83        let context = client.get_context(context_opts).await?;
84
85        let mut dereference = DereferenceOptions::new(reference_id.clone());
86        dereference.run_id = Some(run_id.clone());
87        dereference.agent_id = Some("coverage".into());
88        let exact = client.dereference(dereference).await?;
89
90        let mut recall = RecallOptions::new("What deductible applies and what did the adjuster confirm?");
91        recall.run_id = Some(run_id.clone());
92        recall.agent_id = Some("coverage".into());
93        recall.entry_types = vec!["fact".into(), "archive_block".into(), "feedback".into()];
94        let recall_response = client.recall(recall).await?;
95
96        require(checkpoint_response.get("success").and_then(|v| v.as_bool()).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
97        require(handoff_response.get("success").and_then(|v| v.as_bool()).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
98        require(feedback_response.get("success").and_then(|v| v.as_bool()).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
99        require(exact.get("found").and_then(|v| v.as_bool()).unwrap_or(false), format!("dereference failed: {exact}"))?;
100        let context_text = context.get("context_block").and_then(|v| v.as_str()).unwrap_or("").to_lowercase();
101        let recall_text = recall_response.get("final_answer").and_then(|v| v.as_str()).unwrap_or("").to_lowercase();
102        let has_archive_source = context
103            .get("sources")
104            .and_then(|v| v.as_array())
105            .map(|sources| {
106                sources.iter().any(|source| {
107                    source
108                        .get("entry_type")
109                        .and_then(|v| v.as_str())
110                        == Some("archive_block")
111                })
112            })
113            .unwrap_or(false);
114        let exact_refs_surfaced = context
115            .get("exact_references_surfaced")
116            .and_then(|v| v.as_u64())
117            .unwrap_or(0);
118        require(
119            context_text.contains("adjuster note")
120                || context_text.contains("motorway")
121                || has_archive_source
122                || exact_refs_surfaced > 0,
123            format!("expected explicit or telemetry-backed exact reuse in context: {context}"),
124        )?;
125        require(recall_text.contains("250") && (recall_text.contains("motorway") || recall_text.contains("third party")), format!("expected recall to include fact + archive content: {recall_response}"))?;
126
127        metrics = json!({
128            "run_id": run_id,
129            "handoff_id": handoff_id,
130            "reference_id": reference_id,
131            "feedback_id": feedback_response.get("feedback_id").cloned().unwrap_or(serde_json::Value::Null),
132        });
133        Ok::<(), Box<dyn Error>>(())
134    }
135    .await;
136
137    if let Err(err) = scenario {
138        passed = false;
139        detail = err.to_string();
140    }
141
142    let cleanup_ok = cleanup_run(&client, &run_id).await;
143    if !cleanup_ok {
144        passed = false;
145        detail = format!("{detail} | cleanup failures");
146    }
147
148    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
149    if passed { Ok(()) } else { Err(boxed_error(detail)) }
150}
examples/public/10_full_learning_loop_smoke.rs (line 121)
16async fn main() -> Result<(), Box<dyn Error>> {
17    let name = "public_10_full_learning_loop_smoke";
18    let started = Instant::now();
19    let client = create_client().await?;
20    let run_id = new_run_id("public_10_full_learning_loop_smoke");
21    client.set_run_id(Some(run_id.clone()));
22    client.set_transport(TransportMode::Http);
23
24    let mut passed = true;
25    let mut detail = "validated all helper flows".to_string();
26    let mut metrics = json!({});
27
28    let scenario = async {
29        let mut remember = RememberOptions::new("Policy limit is 5000 and claimant city is Leeds.");
30        remember.run_id = Some(run_id.clone());
31        remember.agent_id = Some("planner".to_string());
32        remember.intent = Some("fact".to_string());
33        remember.metadata = Some(json!({"suite": "all-helpers", "family": "claims"}));
34        remember.importance = Some("high".to_string());
35        remember.occurrence_time = Some(std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as i64 - 86400);
36        let remember_response = client.remember(remember).await?;
37
38        let mut lesson = RememberOptions::new("If city is missing from the latest step, check stored claim facts before escalating.");
39        lesson.run_id = Some(run_id.clone());
40        lesson.agent_id = Some("planner".to_string());
41        lesson.intent = Some("lesson".to_string());
42        lesson.lesson_type = Some("success".to_string());
43        lesson.lesson_scope = Some("session".to_string());
44        lesson.lesson_importance = Some("high".to_string());
45        let lesson_response = client.remember(lesson).await?;
46
47        let mut mental_model = RememberOptions::new(
48            "Claims case overview: Policy limit 5000 GBP, claimant city Leeds, \
49             missing-city branch resolved via stored claim facts. Lesson: check stored facts before escalating.",
50        );
51        mental_model.run_id = Some(run_id.clone());
52        mental_model.agent_id = Some("planner".to_string());
53        mental_model.intent = Some("mental_model".to_string());
54        mental_model.importance = Some("critical".to_string());
55        mental_model.metadata = Some(json!({"suite": "all-helpers", "entity": "claims-case", "consolidated": true}));
56        let mental_model_response = client.remember(mental_model).await?;
57
58        let mut recall = RecallOptions::new("What is the policy limit?");
59        recall.run_id = Some(run_id.clone());
60        recall.agent_id = Some("planner".to_string());
61        recall.limit = 5;
62        let recall_response = client.recall(recall).await?;
63
64        let mut context = GetContextOptions::default();
65        context.run_id = Some(run_id.clone());
66        context.query = Some("Prepare a short adjuster summary".to_string());
67        context.agent_id = Some("planner".to_string());
68        context.limit = Some(6);
69        context.max_token_budget = Some(700);
70        let context_response = client.get_context(context).await?;
71
72        let mut health = MemoryHealthOptions::default();
73        health.run_id = Some(run_id.clone());
74        health.limit = 50;
75        let health_response = client.memory_health(health).await?;
76
77        let mut diagnose = DiagnoseOptions::new("policy limit lookup returned empty");
78        diagnose.run_id = Some(run_id.clone());
79        diagnose.error_type = Some("retrieval".to_string());
80        diagnose.limit = 5;
81        let diagnose_response = client.diagnose(diagnose).await?;
82
83        let mut reflect = ReflectOptions::default();
84        reflect.run_id = Some(run_id.clone());
85        let reflect_response = client.reflect(reflect).await?;
86
87        let mut register = RegisterAgentOptions::new("planner");
88        register.run_id = Some(run_id.clone());
89        register.role = "planner".to_string();
90        register.read_scopes = vec!["fact".into(), "lesson".into(), "rule".into(), "mental_model".into(), "archive_block".into(), "handoff".into(), "feedback".into()];
91        register.write_scopes = vec!["fact".into(), "trace".into(), "lesson".into(), "observation".into(), "archive_block".into()];
92        register.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
93        let register_response = client.register_agent(register).await?;
94
95        let mut list_agents = ListAgentsOptions::default();
96        list_agents.run_id = Some(run_id.clone());
97        let agents_response = client.list_agents(list_agents).await?;
98
99        let mut archive = ArchiveOptions::new(
100            "Exact adjuster note: claimant confirmed city is Leeds during triage.",
101            "adjuster_note",
102        );
103        archive.run_id = Some(run_id.clone());
104        archive.agent_id = Some("planner".to_string());
105        archive.origin_agent_id = Some("planner".to_string());
106        archive.source_attempt_id = Some("attempt-1".to_string());
107        archive.source_tool = Some("phone_call".to_string());
108        archive.labels = vec!["claims".to_string(), "triage".to_string()];
109        archive.family = Some("claims-adjustment".to_string());
110        archive.metadata = Some(json!({"case": "all-helpers"}));
111        let archive_response = client.archive(archive).await?;
112        let reference_id = archive_response
113            .get("reference_id")
114            .and_then(Value::as_str)
115            .ok_or_else(|| boxed_error(format!("archive reference missing: {archive_response}")))?
116            .to_string();
117
118        let mut dereference = DereferenceOptions::new(reference_id.clone());
119        dereference.run_id = Some(run_id.clone());
120        dereference.agent_id = Some("planner".to_string());
121        let dereference_response = client.dereference(dereference).await?;
122
123        let mut checkpoint = CheckpointOptions::new("Planner captured claim facts before window compaction.");
124        checkpoint.run_id = Some(run_id.clone());
125        checkpoint.label = Some("pre-compaction".to_string());
126        checkpoint.metadata = Some(json!({"stage": "analysis"}));
127        checkpoint.agent_id = Some("planner".to_string());
128        let checkpoint_response = client.checkpoint(checkpoint).await?;
129
130        let lessons_response = client.control.lessons(json!({"run_id": run_id, "limit": 20})).await?;
131        let lesson_id = lessons_response
132            .get("lessons")
133            .and_then(Value::as_array)
134            .and_then(|items| items.iter().find_map(|item| item.get("id").and_then(Value::as_str)))
135            .ok_or_else(|| boxed_error(format!("expected lesson id for outcome flow: {lessons_response}")))?
136            .to_string();
137
138        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
139        outcome.run_id = Some(run_id.clone());
140        outcome.signal = 0.75;
141        outcome.rationale = "Planner reused stored claim fact and resolved the missing-city branch.".to_string();
142        outcome.agent_id = Some("planner".to_string());
143        let outcome_response = client.record_outcome(outcome).await?;
144
145        let mut strategies = SurfaceStrategiesOptions::default();
146        strategies.run_id = Some(run_id.clone());
147        strategies.lesson_types = vec!["success".to_string(), "rule".to_string()];
148        strategies.max_strategies = 5;
149        let strategies_response = client.surface_strategies(strategies).await?;
150
151        let mut handoff = HandoffOptions::new(
152            "claim-1",
153            "planner",
154            "reviewer",
155            "Review whether the stored claimant city is sufficient for routing.",
156        );
157        handoff.run_id = Some(run_id.clone());
158        handoff.requested_action = "review".to_string();
159        handoff.metadata = Some(json!({"team": "claims"}));
160        let handoff_response = client.handoff(handoff).await?;
161        let handoff_id = handoff_response
162            .get("handoff_id")
163            .and_then(Value::as_str)
164            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
165            .to_string();
166
167        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
168        feedback.run_id = Some(run_id.clone());
169        feedback.comments = "Stored fact is sufficient; proceed without escalation.".to_string();
170        feedback.from_agent_id = Some("reviewer".to_string());
171        feedback.metadata = Some(json!({"team": "claims"}));
172        let feedback_response = client.feedback(feedback).await?;
173
174        require(remember_response.get("job_id").is_some() || remember_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("remember failed: {remember_response}"))?;
175        require(mental_model_response.get("job_id").is_some() || mental_model_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("mental_model remember failed: {mental_model_response}"))?;
176        require(lesson_response.get("job_id").is_some() || lesson_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("lesson remember failed: {lesson_response}"))?;
177        require(recall_response.get("final_answer").is_some() || recall_response.get("evidence").is_some(), format!("recall failed: {recall_response}"))?;
178        require(context_response.get("sources").and_then(Value::as_array).is_some(), format!("context malformed: {context_response}"))?;
179        require(health_response.get("entry_counts").and_then(Value::as_object).is_some(), format!("memory_health malformed: {health_response}"))?;
180        require(diagnose_response.get("failure_lessons").and_then(Value::as_array).is_some(), format!("diagnose malformed: {diagnose_response}"))?;
181        require(reflect_response.get("lessons").and_then(Value::as_array).is_some(), format!("reflect malformed: {reflect_response}"))?;
182        require(register_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("register_agent failed: {register_response}"))?;
183        require(agents_response.get("agents").and_then(Value::as_array).map(|items| !items.is_empty()).unwrap_or(false), format!("list_agents failed: {agents_response}"))?;
184        require(archive_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("archive failed: {archive_response}"))?;
185        require(dereference_response.get("found").and_then(Value::as_bool).unwrap_or(false), format!("dereference failed: {dereference_response}"))?;
186        require(checkpoint_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
187        require(outcome_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("record_outcome failed: {outcome_response}"))?;
188        require(strategies_response.get("strategies").and_then(Value::as_array).is_some(), format!("surface_strategies malformed: {strategies_response}"))?;
189        require(handoff_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
190        require(feedback_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
191
192        let strategy_count = strategies_response
193            .get("strategies")
194            .and_then(Value::as_array)
195            .map(|items| items.len())
196            .unwrap_or(0);
197        let agent_count = agents_response
198            .get("agents")
199            .and_then(Value::as_array)
200            .map(|items| items.len())
201            .unwrap_or(0);
202        let lesson_count = lessons_response
203            .get("lessons")
204            .and_then(Value::as_array)
205            .map(|items| items.len())
206            .unwrap_or(0);
207
208        metrics = json!({
209            "run_id": run_id,
210            "agent_count": agent_count,
211            "strategy_count": strategy_count,
212            "reference_id": reference_id,
213            "lesson_count": lesson_count,
214        });
215
216        Ok::<(), Box<dyn Error>>(())
217    }
218    .await;
219
220    if let Err(err) = scenario {
221        passed = false;
222        detail = err.to_string();
223    }
224
225    let cleanup_ok = cleanup_run(&client, &run_id).await;
226    if !cleanup_ok {
227        passed = false;
228        detail = format!("{detail} | cleanup failures");
229    }
230
231    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
232
233    if passed { Ok(()) } else { Err(boxed_error(detail)) }
234}
examples/helper_all_helpers.rs (line 109)
16async fn main() -> Result<(), Box<dyn Error>> {
17    let name = "helper_all_helpers";
18    let started = Instant::now();
19    let client = create_client().await?;
20    let run_id = new_run_id("helper_all_helpers");
21    client.set_run_id(Some(run_id.clone()));
22    client.set_transport(TransportMode::Http);
23
24    let mut passed = true;
25    let mut detail = "validated all helper flows".to_string();
26    let mut metrics = json!({});
27
28    let scenario = async {
29        let mut remember = RememberOptions::new("Policy limit is 5000 and claimant city is Leeds.");
30        remember.run_id = Some(run_id.clone());
31        remember.agent_id = Some("planner".to_string());
32        remember.intent = Some("fact".to_string());
33        remember.metadata = Some(json!({"suite": "all-helpers", "family": "claims"}));
34        remember.importance = Some("high".to_string());
35        let remember_response = client.remember(remember).await?;
36
37        let mut lesson = RememberOptions::new("If city is missing from the latest step, check stored claim facts before escalating.");
38        lesson.run_id = Some(run_id.clone());
39        lesson.agent_id = Some("planner".to_string());
40        lesson.intent = Some("lesson".to_string());
41        lesson.lesson_type = Some("success".to_string());
42        lesson.lesson_scope = Some("session".to_string());
43        lesson.lesson_importance = Some("high".to_string());
44        let lesson_response = client.remember(lesson).await?;
45
46        let mut recall = RecallOptions::new("What is the policy limit?");
47        recall.run_id = Some(run_id.clone());
48        recall.agent_id = Some("planner".to_string());
49        recall.limit = 5;
50        let recall_response = client.recall(recall).await?;
51
52        let mut context = GetContextOptions::default();
53        context.run_id = Some(run_id.clone());
54        context.query = Some("Prepare a short adjuster summary".to_string());
55        context.agent_id = Some("planner".to_string());
56        context.limit = Some(6);
57        context.max_token_budget = Some(700);
58        let context_response = client.get_context(context).await?;
59
60        let mut health = MemoryHealthOptions::default();
61        health.run_id = Some(run_id.clone());
62        health.limit = 50;
63        let health_response = client.memory_health(health).await?;
64
65        let mut diagnose = DiagnoseOptions::new("policy limit lookup returned empty");
66        diagnose.run_id = Some(run_id.clone());
67        diagnose.error_type = Some("retrieval".to_string());
68        diagnose.limit = 5;
69        let diagnose_response = client.diagnose(diagnose).await?;
70
71        let mut reflect = ReflectOptions::default();
72        reflect.run_id = Some(run_id.clone());
73        let reflect_response = client.reflect(reflect).await?;
74
75        let mut register = RegisterAgentOptions::new("planner");
76        register.run_id = Some(run_id.clone());
77        register.role = "planner".to_string();
78        register.read_scopes = vec!["fact".into(), "lesson".into(), "rule".into(), "archive_block".into(), "handoff".into(), "feedback".into()];
79        register.write_scopes = vec!["fact".into(), "trace".into(), "lesson".into(), "observation".into(), "archive_block".into()];
80        register.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
81        let register_response = client.register_agent(register).await?;
82
83        let mut list_agents = ListAgentsOptions::default();
84        list_agents.run_id = Some(run_id.clone());
85        let agents_response = client.list_agents(list_agents).await?;
86
87        let mut archive = ArchiveOptions::new(
88            "Exact adjuster note: claimant confirmed city is Leeds during triage.",
89            "adjuster_note",
90        );
91        archive.run_id = Some(run_id.clone());
92        archive.agent_id = Some("planner".to_string());
93        archive.origin_agent_id = Some("planner".to_string());
94        archive.source_attempt_id = Some("attempt-1".to_string());
95        archive.source_tool = Some("phone_call".to_string());
96        archive.labels = vec!["claims".to_string(), "triage".to_string()];
97        archive.family = Some("claims-adjustment".to_string());
98        archive.metadata = Some(json!({"case": "all-helpers"}));
99        let archive_response = client.archive(archive).await?;
100        let reference_id = archive_response
101            .get("reference_id")
102            .and_then(Value::as_str)
103            .ok_or_else(|| boxed_error(format!("archive reference missing: {archive_response}")))?
104            .to_string();
105
106        let mut dereference = DereferenceOptions::new(reference_id.clone());
107        dereference.run_id = Some(run_id.clone());
108        dereference.agent_id = Some("planner".to_string());
109        let dereference_response = client.dereference(dereference).await?;
110
111        let mut checkpoint = CheckpointOptions::new("Planner captured claim facts before window compaction.");
112        checkpoint.run_id = Some(run_id.clone());
113        checkpoint.label = Some("pre-compaction".to_string());
114        checkpoint.metadata = Some(json!({"stage": "analysis"}));
115        checkpoint.agent_id = Some("planner".to_string());
116        let checkpoint_response = client.checkpoint(checkpoint).await?;
117
118        let lessons_response = client.control.lessons(json!({"run_id": run_id, "limit": 20})).await?;
119        let lesson_id = lessons_response
120            .get("lessons")
121            .and_then(Value::as_array)
122            .and_then(|items| items.iter().find_map(|item| item.get("id").and_then(Value::as_str)))
123            .ok_or_else(|| boxed_error(format!("expected lesson id for outcome flow: {lessons_response}")))?
124            .to_string();
125
126        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
127        outcome.run_id = Some(run_id.clone());
128        outcome.signal = 0.75;
129        outcome.rationale = "Planner reused stored claim fact and resolved the missing-city branch.".to_string();
130        outcome.agent_id = Some("planner".to_string());
131        let outcome_response = client.record_outcome(outcome).await?;
132
133        let mut strategies = SurfaceStrategiesOptions::default();
134        strategies.run_id = Some(run_id.clone());
135        strategies.lesson_types = vec!["success".to_string(), "rule".to_string()];
136        strategies.max_strategies = 5;
137        let strategies_response = client.surface_strategies(strategies).await?;
138
139        let mut handoff = HandoffOptions::new(
140            "claim-1",
141            "planner",
142            "reviewer",
143            "Review whether the stored claimant city is sufficient for routing.",
144        );
145        handoff.run_id = Some(run_id.clone());
146        handoff.requested_action = "review".to_string();
147        handoff.metadata = Some(json!({"team": "claims"}));
148        let handoff_response = client.handoff(handoff).await?;
149        let handoff_id = handoff_response
150            .get("handoff_id")
151            .and_then(Value::as_str)
152            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
153            .to_string();
154
155        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
156        feedback.run_id = Some(run_id.clone());
157        feedback.comments = "Stored fact is sufficient; proceed without escalation.".to_string();
158        feedback.from_agent_id = Some("reviewer".to_string());
159        feedback.metadata = Some(json!({"team": "claims"}));
160        let feedback_response = client.feedback(feedback).await?;
161
162        let scratch_run = format!("{run_id}_forget");
163        let mut scratch = RememberOptions::new("Scratch run for forget helper coverage.");
164        scratch.run_id = Some(scratch_run.clone());
165        scratch.agent_id = Some("planner".to_string());
166        scratch.intent = Some("fact".to_string());
167        scratch.metadata = Some(json!({"suite": "all-helpers", "temporary": true}));
168        let scratch_response = client.remember(scratch).await?;
169
170        let forget_response = client
171            .forget(ForgetOptions::for_run(scratch_run.clone()))
172            .await?;
173
174        let mut forgotten = RecallOptions::new("What temporary scratch fact exists?");
175        forgotten.run_id = Some(scratch_run.clone());
176        forgotten.limit = 3;
177        let forgotten_response = client.recall(forgotten).await?;
178
179        require(remember_response.get("job_id").is_some() || remember_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("remember failed: {remember_response}"))?;
180        require(lesson_response.get("job_id").is_some() || lesson_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("lesson remember failed: {lesson_response}"))?;
181        require(recall_response.get("final_answer").is_some() || recall_response.get("evidence").is_some(), format!("recall failed: {recall_response}"))?;
182        require(context_response.get("sources").and_then(Value::as_array).is_some(), format!("context malformed: {context_response}"))?;
183        require(health_response.get("entry_counts").and_then(Value::as_object).is_some(), format!("memory_health malformed: {health_response}"))?;
184        require(diagnose_response.get("failure_lessons").and_then(Value::as_array).is_some(), format!("diagnose malformed: {diagnose_response}"))?;
185        require(reflect_response.get("lessons").and_then(Value::as_array).is_some(), format!("reflect malformed: {reflect_response}"))?;
186        require(register_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("register_agent failed: {register_response}"))?;
187        require(agents_response.get("agents").and_then(Value::as_array).map(|items| !items.is_empty()).unwrap_or(false), format!("list_agents failed: {agents_response}"))?;
188        require(archive_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("archive failed: {archive_response}"))?;
189        require(dereference_response.get("found").and_then(Value::as_bool).unwrap_or(false), format!("dereference failed: {dereference_response}"))?;
190        require(checkpoint_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
191        require(outcome_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("record_outcome failed: {outcome_response}"))?;
192        require(strategies_response.get("strategies").and_then(Value::as_array).is_some(), format!("surface_strategies malformed: {strategies_response}"))?;
193        require(handoff_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
194        require(feedback_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
195        require(scratch_response.get("job_id").is_some() || scratch_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("scratch remember failed: {scratch_response}"))?;
196        require(forget_response.get("success").and_then(Value::as_bool).unwrap_or(true), format!("forget failed: {forget_response}"))?;
197        let scratch_fact_visible = forgotten_response
198            .get("evidence")
199            .and_then(Value::as_array)
200            .map(|items| {
201                items.iter().any(|item| {
202                    item.get("run_id").and_then(Value::as_str) == Some(scratch_run.as_str())
203                        || item
204                            .get("content")
205                            .and_then(Value::as_str)
206                            .map(|content| {
207                                content
208                                    .to_ascii_lowercase()
209                                    .contains("scratch run for forget helper coverage")
210                            })
211                            .unwrap_or(false)
212                })
213            })
214            .unwrap_or(false);
215        require(!scratch_fact_visible, format!("scratch fact should be forgotten even if same-user lessons still surface: {forgotten_response}"))?;
216
217        let strategy_count = strategies_response
218            .get("strategies")
219            .and_then(Value::as_array)
220            .map(|items| items.len())
221            .unwrap_or(0);
222        let agent_count = agents_response
223            .get("agents")
224            .and_then(Value::as_array)
225            .map(|items| items.len())
226            .unwrap_or(0);
227        let lesson_count = lessons_response
228            .get("lessons")
229            .and_then(Value::as_array)
230            .map(|items| items.len())
231            .unwrap_or(0);
232
233        metrics = json!({
234            "run_id": run_id,
235            "agent_count": agent_count,
236            "strategy_count": strategy_count,
237            "reference_id": reference_id,
238            "lesson_count": lesson_count,
239            "forgotten_run": scratch_run,
240        });
241
242        Ok::<(), Box<dyn Error>>(())
243    }
244    .await;
245
246    if let Err(err) = scenario {
247        passed = false;
248        detail = err.to_string();
249    }
250
251    let cleanup_ok = cleanup_run(&client, &run_id).await;
252    if !cleanup_ok {
253        passed = false;
254        detail = format!("{detail} | cleanup failures");
255    }
256
257    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
258
259    if passed { Ok(()) } else { Err(boxed_error(detail)) }
260}
Source

pub async fn memory_health(&self, options: MemoryHealthOptions) -> Result<Value>

Examples found in repository?
examples/public/04_memory_health_and_diagnose.rs (line 54)
13async fn main() -> Result<(), Box<dyn Error>> {
14    let name = "public_04_memory_health_and_diagnose";
15    let started = Instant::now();
16    let client = create_client().await?;
17    let run_id = new_run_id("public_04_memory_health_and_diagnose");
18    client.set_run_id(Some(run_id.clone()));
19    client.set_transport(TransportMode::Http);
20
21    let mut passed = true;
22    let mut detail = "validated helper context + diagnose + memory health flow".to_string();
23    let mut metrics = json!({});
24
25    let scenario = async {
26        let mut remember = RememberOptions::new(
27            "Deploys fail when the migration checksum is stale after a force-push.",
28        );
29        remember.run_id = Some(run_id.clone());
30        remember.agent_id = Some("observer".to_string());
31        remember.intent = Some("lesson".to_string());
32        remember.lesson_type = Some("failure".to_string());
33        remember.lesson_scope = Some("session".to_string());
34        remember.lesson_importance = Some("high".to_string());
35        remember.metadata = Some(json!({ "source": "rust-helper-example" }));
36        client.remember(remember).await?;
37
38        let mut context_opts = GetContextOptions::default();
39        context_opts.run_id = Some(run_id.clone());
40        context_opts.query = Some("Why did the deploy fail?".to_string());
41        context_opts.entry_types = vec!["lesson".to_string()];
42        context_opts.mode = Some("summary".to_string());
43        let context = client.get_context(context_opts).await?;
44
45        let mut diagnose = DiagnoseOptions::new("deploy failed because migration checksum is stale");
46        diagnose.run_id = Some(run_id.clone());
47        diagnose.error_type = Some("deploy".to_string());
48        diagnose.limit = 5;
49        let diagnosis = client.diagnose(diagnose).await?;
50
51        let mut health_opts = MemoryHealthOptions::default();
52        health_opts.run_id = Some(run_id.clone());
53        health_opts.limit = 100;
54        let health = client.memory_health(health_opts).await?;
55
56        let section_summaries = context
57            .get("section_summaries")
58            .and_then(|value| value.as_array())
59            .ok_or_else(|| boxed_error(format!("section summaries missing: {context}")))?;
60        require(
61            diagnosis
62                .get("total_failure_lessons")
63                .and_then(|value| value.as_u64())
64                .unwrap_or(0)
65                >= 1,
66            format!("diagnose should surface a failure lesson: {diagnosis}"),
67        )?;
68        require(
69            health.get("entry_counts").and_then(|value| value.as_object()).is_some(),
70            format!("memory health missing entry counts: {health}"),
71        )?;
72
73        metrics = json!({
74            "run_id": run_id,
75            "section_count": section_summaries.len(),
76            "total_failure_lessons": diagnosis.get("total_failure_lessons").cloned().unwrap_or(serde_json::Value::Null),
77            "entry_count_keys": health.get("entry_counts").and_then(|value| value.as_object()).map(|map| map.len()).unwrap_or(0),
78        });
79
80        Ok::<(), Box<dyn Error>>(())
81    }
82    .await;
83
84    if let Err(err) = scenario {
85        passed = false;
86        detail = err.to_string();
87    }
88
89    let cleanup_ok = cleanup_run(&client, &run_id).await;
90    if !cleanup_ok {
91        passed = false;
92        detail = format!("{detail} | cleanup failures");
93    }
94
95    print_summary(
96        name,
97        passed,
98        &detail,
99        &metrics,
100        started.elapsed().as_secs_f64(),
101        cleanup_ok,
102    );
103
104    if passed {
105        Ok(())
106    } else {
107        Err(boxed_error(detail))
108    }
109}
More examples
Hide additional examples
examples/helper_context_diagnose_memory_health.rs (line 54)
13async fn main() -> Result<(), Box<dyn Error>> {
14    let name = "helper_context_diagnose_memory_health";
15    let started = Instant::now();
16    let client = create_client().await?;
17    let run_id = new_run_id("helper_context_diagnose_memory_health");
18    client.set_run_id(Some(run_id.clone()));
19    client.set_transport(TransportMode::Http);
20
21    let mut passed = true;
22    let mut detail = "validated helper context + diagnose + memory health flow".to_string();
23    let mut metrics = json!({});
24
25    let scenario = async {
26        let mut remember = RememberOptions::new(
27            "Deploys fail when the migration checksum is stale after a force-push.",
28        );
29        remember.run_id = Some(run_id.clone());
30        remember.agent_id = Some("observer".to_string());
31        remember.intent = Some("lesson".to_string());
32        remember.lesson_type = Some("failure".to_string());
33        remember.lesson_scope = Some("session".to_string());
34        remember.lesson_importance = Some("high".to_string());
35        remember.metadata = Some(json!({ "source": "rust-helper-example" }));
36        client.remember(remember).await?;
37
38        let mut context_opts = GetContextOptions::default();
39        context_opts.run_id = Some(run_id.clone());
40        context_opts.query = Some("Why did the deploy fail?".to_string());
41        context_opts.entry_types = vec!["lesson".to_string()];
42        context_opts.mode = Some("summary".to_string());
43        let context = client.get_context(context_opts).await?;
44
45        let mut diagnose = DiagnoseOptions::new("deploy failed because migration checksum is stale");
46        diagnose.run_id = Some(run_id.clone());
47        diagnose.error_type = Some("deploy".to_string());
48        diagnose.limit = 5;
49        let diagnosis = client.diagnose(diagnose).await?;
50
51        let mut health_opts = MemoryHealthOptions::default();
52        health_opts.run_id = Some(run_id.clone());
53        health_opts.limit = 100;
54        let health = client.memory_health(health_opts).await?;
55
56        let section_summaries = context
57            .get("section_summaries")
58            .and_then(|value| value.as_array())
59            .ok_or_else(|| boxed_error(format!("section summaries missing: {context}")))?;
60        require(
61            diagnosis
62                .get("total_failure_lessons")
63                .and_then(|value| value.as_u64())
64                .unwrap_or(0)
65                >= 1,
66            format!("diagnose should surface a failure lesson: {diagnosis}"),
67        )?;
68        require(
69            health.get("entry_counts").and_then(|value| value.as_object()).is_some(),
70            format!("memory health missing entry counts: {health}"),
71        )?;
72
73        metrics = json!({
74            "run_id": run_id,
75            "section_count": section_summaries.len(),
76            "total_failure_lessons": diagnosis.get("total_failure_lessons").cloned().unwrap_or(serde_json::Value::Null),
77            "entry_count_keys": health.get("entry_counts").and_then(|value| value.as_object()).map(|map| map.len()).unwrap_or(0),
78        });
79
80        Ok::<(), Box<dyn Error>>(())
81    }
82    .await;
83
84    if let Err(err) = scenario {
85        passed = false;
86        detail = err.to_string();
87    }
88
89    let cleanup_ok = cleanup_run(&client, &run_id).await;
90    if !cleanup_ok {
91        passed = false;
92        detail = format!("{detail} | cleanup failures");
93    }
94
95    print_summary(
96        name,
97        passed,
98        &detail,
99        &metrics,
100        started.elapsed().as_secs_f64(),
101        cleanup_ok,
102    );
103
104    if passed {
105        Ok(())
106    } else {
107        Err(boxed_error(detail))
108    }
109}
examples/public/10_full_learning_loop_smoke.rs (line 75)
16async fn main() -> Result<(), Box<dyn Error>> {
17    let name = "public_10_full_learning_loop_smoke";
18    let started = Instant::now();
19    let client = create_client().await?;
20    let run_id = new_run_id("public_10_full_learning_loop_smoke");
21    client.set_run_id(Some(run_id.clone()));
22    client.set_transport(TransportMode::Http);
23
24    let mut passed = true;
25    let mut detail = "validated all helper flows".to_string();
26    let mut metrics = json!({});
27
28    let scenario = async {
29        let mut remember = RememberOptions::new("Policy limit is 5000 and claimant city is Leeds.");
30        remember.run_id = Some(run_id.clone());
31        remember.agent_id = Some("planner".to_string());
32        remember.intent = Some("fact".to_string());
33        remember.metadata = Some(json!({"suite": "all-helpers", "family": "claims"}));
34        remember.importance = Some("high".to_string());
35        remember.occurrence_time = Some(std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as i64 - 86400);
36        let remember_response = client.remember(remember).await?;
37
38        let mut lesson = RememberOptions::new("If city is missing from the latest step, check stored claim facts before escalating.");
39        lesson.run_id = Some(run_id.clone());
40        lesson.agent_id = Some("planner".to_string());
41        lesson.intent = Some("lesson".to_string());
42        lesson.lesson_type = Some("success".to_string());
43        lesson.lesson_scope = Some("session".to_string());
44        lesson.lesson_importance = Some("high".to_string());
45        let lesson_response = client.remember(lesson).await?;
46
47        let mut mental_model = RememberOptions::new(
48            "Claims case overview: Policy limit 5000 GBP, claimant city Leeds, \
49             missing-city branch resolved via stored claim facts. Lesson: check stored facts before escalating.",
50        );
51        mental_model.run_id = Some(run_id.clone());
52        mental_model.agent_id = Some("planner".to_string());
53        mental_model.intent = Some("mental_model".to_string());
54        mental_model.importance = Some("critical".to_string());
55        mental_model.metadata = Some(json!({"suite": "all-helpers", "entity": "claims-case", "consolidated": true}));
56        let mental_model_response = client.remember(mental_model).await?;
57
58        let mut recall = RecallOptions::new("What is the policy limit?");
59        recall.run_id = Some(run_id.clone());
60        recall.agent_id = Some("planner".to_string());
61        recall.limit = 5;
62        let recall_response = client.recall(recall).await?;
63
64        let mut context = GetContextOptions::default();
65        context.run_id = Some(run_id.clone());
66        context.query = Some("Prepare a short adjuster summary".to_string());
67        context.agent_id = Some("planner".to_string());
68        context.limit = Some(6);
69        context.max_token_budget = Some(700);
70        let context_response = client.get_context(context).await?;
71
72        let mut health = MemoryHealthOptions::default();
73        health.run_id = Some(run_id.clone());
74        health.limit = 50;
75        let health_response = client.memory_health(health).await?;
76
77        let mut diagnose = DiagnoseOptions::new("policy limit lookup returned empty");
78        diagnose.run_id = Some(run_id.clone());
79        diagnose.error_type = Some("retrieval".to_string());
80        diagnose.limit = 5;
81        let diagnose_response = client.diagnose(diagnose).await?;
82
83        let mut reflect = ReflectOptions::default();
84        reflect.run_id = Some(run_id.clone());
85        let reflect_response = client.reflect(reflect).await?;
86
87        let mut register = RegisterAgentOptions::new("planner");
88        register.run_id = Some(run_id.clone());
89        register.role = "planner".to_string();
90        register.read_scopes = vec!["fact".into(), "lesson".into(), "rule".into(), "mental_model".into(), "archive_block".into(), "handoff".into(), "feedback".into()];
91        register.write_scopes = vec!["fact".into(), "trace".into(), "lesson".into(), "observation".into(), "archive_block".into()];
92        register.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
93        let register_response = client.register_agent(register).await?;
94
95        let mut list_agents = ListAgentsOptions::default();
96        list_agents.run_id = Some(run_id.clone());
97        let agents_response = client.list_agents(list_agents).await?;
98
99        let mut archive = ArchiveOptions::new(
100            "Exact adjuster note: claimant confirmed city is Leeds during triage.",
101            "adjuster_note",
102        );
103        archive.run_id = Some(run_id.clone());
104        archive.agent_id = Some("planner".to_string());
105        archive.origin_agent_id = Some("planner".to_string());
106        archive.source_attempt_id = Some("attempt-1".to_string());
107        archive.source_tool = Some("phone_call".to_string());
108        archive.labels = vec!["claims".to_string(), "triage".to_string()];
109        archive.family = Some("claims-adjustment".to_string());
110        archive.metadata = Some(json!({"case": "all-helpers"}));
111        let archive_response = client.archive(archive).await?;
112        let reference_id = archive_response
113            .get("reference_id")
114            .and_then(Value::as_str)
115            .ok_or_else(|| boxed_error(format!("archive reference missing: {archive_response}")))?
116            .to_string();
117
118        let mut dereference = DereferenceOptions::new(reference_id.clone());
119        dereference.run_id = Some(run_id.clone());
120        dereference.agent_id = Some("planner".to_string());
121        let dereference_response = client.dereference(dereference).await?;
122
123        let mut checkpoint = CheckpointOptions::new("Planner captured claim facts before window compaction.");
124        checkpoint.run_id = Some(run_id.clone());
125        checkpoint.label = Some("pre-compaction".to_string());
126        checkpoint.metadata = Some(json!({"stage": "analysis"}));
127        checkpoint.agent_id = Some("planner".to_string());
128        let checkpoint_response = client.checkpoint(checkpoint).await?;
129
130        let lessons_response = client.control.lessons(json!({"run_id": run_id, "limit": 20})).await?;
131        let lesson_id = lessons_response
132            .get("lessons")
133            .and_then(Value::as_array)
134            .and_then(|items| items.iter().find_map(|item| item.get("id").and_then(Value::as_str)))
135            .ok_or_else(|| boxed_error(format!("expected lesson id for outcome flow: {lessons_response}")))?
136            .to_string();
137
138        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
139        outcome.run_id = Some(run_id.clone());
140        outcome.signal = 0.75;
141        outcome.rationale = "Planner reused stored claim fact and resolved the missing-city branch.".to_string();
142        outcome.agent_id = Some("planner".to_string());
143        let outcome_response = client.record_outcome(outcome).await?;
144
145        let mut strategies = SurfaceStrategiesOptions::default();
146        strategies.run_id = Some(run_id.clone());
147        strategies.lesson_types = vec!["success".to_string(), "rule".to_string()];
148        strategies.max_strategies = 5;
149        let strategies_response = client.surface_strategies(strategies).await?;
150
151        let mut handoff = HandoffOptions::new(
152            "claim-1",
153            "planner",
154            "reviewer",
155            "Review whether the stored claimant city is sufficient for routing.",
156        );
157        handoff.run_id = Some(run_id.clone());
158        handoff.requested_action = "review".to_string();
159        handoff.metadata = Some(json!({"team": "claims"}));
160        let handoff_response = client.handoff(handoff).await?;
161        let handoff_id = handoff_response
162            .get("handoff_id")
163            .and_then(Value::as_str)
164            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
165            .to_string();
166
167        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
168        feedback.run_id = Some(run_id.clone());
169        feedback.comments = "Stored fact is sufficient; proceed without escalation.".to_string();
170        feedback.from_agent_id = Some("reviewer".to_string());
171        feedback.metadata = Some(json!({"team": "claims"}));
172        let feedback_response = client.feedback(feedback).await?;
173
174        require(remember_response.get("job_id").is_some() || remember_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("remember failed: {remember_response}"))?;
175        require(mental_model_response.get("job_id").is_some() || mental_model_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("mental_model remember failed: {mental_model_response}"))?;
176        require(lesson_response.get("job_id").is_some() || lesson_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("lesson remember failed: {lesson_response}"))?;
177        require(recall_response.get("final_answer").is_some() || recall_response.get("evidence").is_some(), format!("recall failed: {recall_response}"))?;
178        require(context_response.get("sources").and_then(Value::as_array).is_some(), format!("context malformed: {context_response}"))?;
179        require(health_response.get("entry_counts").and_then(Value::as_object).is_some(), format!("memory_health malformed: {health_response}"))?;
180        require(diagnose_response.get("failure_lessons").and_then(Value::as_array).is_some(), format!("diagnose malformed: {diagnose_response}"))?;
181        require(reflect_response.get("lessons").and_then(Value::as_array).is_some(), format!("reflect malformed: {reflect_response}"))?;
182        require(register_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("register_agent failed: {register_response}"))?;
183        require(agents_response.get("agents").and_then(Value::as_array).map(|items| !items.is_empty()).unwrap_or(false), format!("list_agents failed: {agents_response}"))?;
184        require(archive_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("archive failed: {archive_response}"))?;
185        require(dereference_response.get("found").and_then(Value::as_bool).unwrap_or(false), format!("dereference failed: {dereference_response}"))?;
186        require(checkpoint_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
187        require(outcome_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("record_outcome failed: {outcome_response}"))?;
188        require(strategies_response.get("strategies").and_then(Value::as_array).is_some(), format!("surface_strategies malformed: {strategies_response}"))?;
189        require(handoff_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
190        require(feedback_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
191
192        let strategy_count = strategies_response
193            .get("strategies")
194            .and_then(Value::as_array)
195            .map(|items| items.len())
196            .unwrap_or(0);
197        let agent_count = agents_response
198            .get("agents")
199            .and_then(Value::as_array)
200            .map(|items| items.len())
201            .unwrap_or(0);
202        let lesson_count = lessons_response
203            .get("lessons")
204            .and_then(Value::as_array)
205            .map(|items| items.len())
206            .unwrap_or(0);
207
208        metrics = json!({
209            "run_id": run_id,
210            "agent_count": agent_count,
211            "strategy_count": strategy_count,
212            "reference_id": reference_id,
213            "lesson_count": lesson_count,
214        });
215
216        Ok::<(), Box<dyn Error>>(())
217    }
218    .await;
219
220    if let Err(err) = scenario {
221        passed = false;
222        detail = err.to_string();
223    }
224
225    let cleanup_ok = cleanup_run(&client, &run_id).await;
226    if !cleanup_ok {
227        passed = false;
228        detail = format!("{detail} | cleanup failures");
229    }
230
231    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
232
233    if passed { Ok(()) } else { Err(boxed_error(detail)) }
234}
examples/helper_all_helpers.rs (line 63)
16async fn main() -> Result<(), Box<dyn Error>> {
17    let name = "helper_all_helpers";
18    let started = Instant::now();
19    let client = create_client().await?;
20    let run_id = new_run_id("helper_all_helpers");
21    client.set_run_id(Some(run_id.clone()));
22    client.set_transport(TransportMode::Http);
23
24    let mut passed = true;
25    let mut detail = "validated all helper flows".to_string();
26    let mut metrics = json!({});
27
28    let scenario = async {
29        let mut remember = RememberOptions::new("Policy limit is 5000 and claimant city is Leeds.");
30        remember.run_id = Some(run_id.clone());
31        remember.agent_id = Some("planner".to_string());
32        remember.intent = Some("fact".to_string());
33        remember.metadata = Some(json!({"suite": "all-helpers", "family": "claims"}));
34        remember.importance = Some("high".to_string());
35        let remember_response = client.remember(remember).await?;
36
37        let mut lesson = RememberOptions::new("If city is missing from the latest step, check stored claim facts before escalating.");
38        lesson.run_id = Some(run_id.clone());
39        lesson.agent_id = Some("planner".to_string());
40        lesson.intent = Some("lesson".to_string());
41        lesson.lesson_type = Some("success".to_string());
42        lesson.lesson_scope = Some("session".to_string());
43        lesson.lesson_importance = Some("high".to_string());
44        let lesson_response = client.remember(lesson).await?;
45
46        let mut recall = RecallOptions::new("What is the policy limit?");
47        recall.run_id = Some(run_id.clone());
48        recall.agent_id = Some("planner".to_string());
49        recall.limit = 5;
50        let recall_response = client.recall(recall).await?;
51
52        let mut context = GetContextOptions::default();
53        context.run_id = Some(run_id.clone());
54        context.query = Some("Prepare a short adjuster summary".to_string());
55        context.agent_id = Some("planner".to_string());
56        context.limit = Some(6);
57        context.max_token_budget = Some(700);
58        let context_response = client.get_context(context).await?;
59
60        let mut health = MemoryHealthOptions::default();
61        health.run_id = Some(run_id.clone());
62        health.limit = 50;
63        let health_response = client.memory_health(health).await?;
64
65        let mut diagnose = DiagnoseOptions::new("policy limit lookup returned empty");
66        diagnose.run_id = Some(run_id.clone());
67        diagnose.error_type = Some("retrieval".to_string());
68        diagnose.limit = 5;
69        let diagnose_response = client.diagnose(diagnose).await?;
70
71        let mut reflect = ReflectOptions::default();
72        reflect.run_id = Some(run_id.clone());
73        let reflect_response = client.reflect(reflect).await?;
74
75        let mut register = RegisterAgentOptions::new("planner");
76        register.run_id = Some(run_id.clone());
77        register.role = "planner".to_string();
78        register.read_scopes = vec!["fact".into(), "lesson".into(), "rule".into(), "archive_block".into(), "handoff".into(), "feedback".into()];
79        register.write_scopes = vec!["fact".into(), "trace".into(), "lesson".into(), "observation".into(), "archive_block".into()];
80        register.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
81        let register_response = client.register_agent(register).await?;
82
83        let mut list_agents = ListAgentsOptions::default();
84        list_agents.run_id = Some(run_id.clone());
85        let agents_response = client.list_agents(list_agents).await?;
86
87        let mut archive = ArchiveOptions::new(
88            "Exact adjuster note: claimant confirmed city is Leeds during triage.",
89            "adjuster_note",
90        );
91        archive.run_id = Some(run_id.clone());
92        archive.agent_id = Some("planner".to_string());
93        archive.origin_agent_id = Some("planner".to_string());
94        archive.source_attempt_id = Some("attempt-1".to_string());
95        archive.source_tool = Some("phone_call".to_string());
96        archive.labels = vec!["claims".to_string(), "triage".to_string()];
97        archive.family = Some("claims-adjustment".to_string());
98        archive.metadata = Some(json!({"case": "all-helpers"}));
99        let archive_response = client.archive(archive).await?;
100        let reference_id = archive_response
101            .get("reference_id")
102            .and_then(Value::as_str)
103            .ok_or_else(|| boxed_error(format!("archive reference missing: {archive_response}")))?
104            .to_string();
105
106        let mut dereference = DereferenceOptions::new(reference_id.clone());
107        dereference.run_id = Some(run_id.clone());
108        dereference.agent_id = Some("planner".to_string());
109        let dereference_response = client.dereference(dereference).await?;
110
111        let mut checkpoint = CheckpointOptions::new("Planner captured claim facts before window compaction.");
112        checkpoint.run_id = Some(run_id.clone());
113        checkpoint.label = Some("pre-compaction".to_string());
114        checkpoint.metadata = Some(json!({"stage": "analysis"}));
115        checkpoint.agent_id = Some("planner".to_string());
116        let checkpoint_response = client.checkpoint(checkpoint).await?;
117
118        let lessons_response = client.control.lessons(json!({"run_id": run_id, "limit": 20})).await?;
119        let lesson_id = lessons_response
120            .get("lessons")
121            .and_then(Value::as_array)
122            .and_then(|items| items.iter().find_map(|item| item.get("id").and_then(Value::as_str)))
123            .ok_or_else(|| boxed_error(format!("expected lesson id for outcome flow: {lessons_response}")))?
124            .to_string();
125
126        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
127        outcome.run_id = Some(run_id.clone());
128        outcome.signal = 0.75;
129        outcome.rationale = "Planner reused stored claim fact and resolved the missing-city branch.".to_string();
130        outcome.agent_id = Some("planner".to_string());
131        let outcome_response = client.record_outcome(outcome).await?;
132
133        let mut strategies = SurfaceStrategiesOptions::default();
134        strategies.run_id = Some(run_id.clone());
135        strategies.lesson_types = vec!["success".to_string(), "rule".to_string()];
136        strategies.max_strategies = 5;
137        let strategies_response = client.surface_strategies(strategies).await?;
138
139        let mut handoff = HandoffOptions::new(
140            "claim-1",
141            "planner",
142            "reviewer",
143            "Review whether the stored claimant city is sufficient for routing.",
144        );
145        handoff.run_id = Some(run_id.clone());
146        handoff.requested_action = "review".to_string();
147        handoff.metadata = Some(json!({"team": "claims"}));
148        let handoff_response = client.handoff(handoff).await?;
149        let handoff_id = handoff_response
150            .get("handoff_id")
151            .and_then(Value::as_str)
152            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
153            .to_string();
154
155        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
156        feedback.run_id = Some(run_id.clone());
157        feedback.comments = "Stored fact is sufficient; proceed without escalation.".to_string();
158        feedback.from_agent_id = Some("reviewer".to_string());
159        feedback.metadata = Some(json!({"team": "claims"}));
160        let feedback_response = client.feedback(feedback).await?;
161
162        let scratch_run = format!("{run_id}_forget");
163        let mut scratch = RememberOptions::new("Scratch run for forget helper coverage.");
164        scratch.run_id = Some(scratch_run.clone());
165        scratch.agent_id = Some("planner".to_string());
166        scratch.intent = Some("fact".to_string());
167        scratch.metadata = Some(json!({"suite": "all-helpers", "temporary": true}));
168        let scratch_response = client.remember(scratch).await?;
169
170        let forget_response = client
171            .forget(ForgetOptions::for_run(scratch_run.clone()))
172            .await?;
173
174        let mut forgotten = RecallOptions::new("What temporary scratch fact exists?");
175        forgotten.run_id = Some(scratch_run.clone());
176        forgotten.limit = 3;
177        let forgotten_response = client.recall(forgotten).await?;
178
179        require(remember_response.get("job_id").is_some() || remember_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("remember failed: {remember_response}"))?;
180        require(lesson_response.get("job_id").is_some() || lesson_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("lesson remember failed: {lesson_response}"))?;
181        require(recall_response.get("final_answer").is_some() || recall_response.get("evidence").is_some(), format!("recall failed: {recall_response}"))?;
182        require(context_response.get("sources").and_then(Value::as_array).is_some(), format!("context malformed: {context_response}"))?;
183        require(health_response.get("entry_counts").and_then(Value::as_object).is_some(), format!("memory_health malformed: {health_response}"))?;
184        require(diagnose_response.get("failure_lessons").and_then(Value::as_array).is_some(), format!("diagnose malformed: {diagnose_response}"))?;
185        require(reflect_response.get("lessons").and_then(Value::as_array).is_some(), format!("reflect malformed: {reflect_response}"))?;
186        require(register_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("register_agent failed: {register_response}"))?;
187        require(agents_response.get("agents").and_then(Value::as_array).map(|items| !items.is_empty()).unwrap_or(false), format!("list_agents failed: {agents_response}"))?;
188        require(archive_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("archive failed: {archive_response}"))?;
189        require(dereference_response.get("found").and_then(Value::as_bool).unwrap_or(false), format!("dereference failed: {dereference_response}"))?;
190        require(checkpoint_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
191        require(outcome_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("record_outcome failed: {outcome_response}"))?;
192        require(strategies_response.get("strategies").and_then(Value::as_array).is_some(), format!("surface_strategies malformed: {strategies_response}"))?;
193        require(handoff_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
194        require(feedback_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
195        require(scratch_response.get("job_id").is_some() || scratch_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("scratch remember failed: {scratch_response}"))?;
196        require(forget_response.get("success").and_then(Value::as_bool).unwrap_or(true), format!("forget failed: {forget_response}"))?;
197        let scratch_fact_visible = forgotten_response
198            .get("evidence")
199            .and_then(Value::as_array)
200            .map(|items| {
201                items.iter().any(|item| {
202                    item.get("run_id").and_then(Value::as_str) == Some(scratch_run.as_str())
203                        || item
204                            .get("content")
205                            .and_then(Value::as_str)
206                            .map(|content| {
207                                content
208                                    .to_ascii_lowercase()
209                                    .contains("scratch run for forget helper coverage")
210                            })
211                            .unwrap_or(false)
212                })
213            })
214            .unwrap_or(false);
215        require(!scratch_fact_visible, format!("scratch fact should be forgotten even if same-user lessons still surface: {forgotten_response}"))?;
216
217        let strategy_count = strategies_response
218            .get("strategies")
219            .and_then(Value::as_array)
220            .map(|items| items.len())
221            .unwrap_or(0);
222        let agent_count = agents_response
223            .get("agents")
224            .and_then(Value::as_array)
225            .map(|items| items.len())
226            .unwrap_or(0);
227        let lesson_count = lessons_response
228            .get("lessons")
229            .and_then(Value::as_array)
230            .map(|items| items.len())
231            .unwrap_or(0);
232
233        metrics = json!({
234            "run_id": run_id,
235            "agent_count": agent_count,
236            "strategy_count": strategy_count,
237            "reference_id": reference_id,
238            "lesson_count": lesson_count,
239            "forgotten_run": scratch_run,
240        });
241
242        Ok::<(), Box<dyn Error>>(())
243    }
244    .await;
245
246    if let Err(err) = scenario {
247        passed = false;
248        detail = err.to_string();
249    }
250
251    let cleanup_ok = cleanup_run(&client, &run_id).await;
252    if !cleanup_ok {
253        passed = false;
254        detail = format!("{detail} | cleanup failures");
255    }
256
257    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
258
259    if passed { Ok(()) } else { Err(boxed_error(detail)) }
260}
Source

pub async fn diagnose(&self, options: DiagnoseOptions) -> Result<Value>

Examples found in repository?
examples/public/04_memory_health_and_diagnose.rs (line 49)
13async fn main() -> Result<(), Box<dyn Error>> {
14    let name = "public_04_memory_health_and_diagnose";
15    let started = Instant::now();
16    let client = create_client().await?;
17    let run_id = new_run_id("public_04_memory_health_and_diagnose");
18    client.set_run_id(Some(run_id.clone()));
19    client.set_transport(TransportMode::Http);
20
21    let mut passed = true;
22    let mut detail = "validated helper context + diagnose + memory health flow".to_string();
23    let mut metrics = json!({});
24
25    let scenario = async {
26        let mut remember = RememberOptions::new(
27            "Deploys fail when the migration checksum is stale after a force-push.",
28        );
29        remember.run_id = Some(run_id.clone());
30        remember.agent_id = Some("observer".to_string());
31        remember.intent = Some("lesson".to_string());
32        remember.lesson_type = Some("failure".to_string());
33        remember.lesson_scope = Some("session".to_string());
34        remember.lesson_importance = Some("high".to_string());
35        remember.metadata = Some(json!({ "source": "rust-helper-example" }));
36        client.remember(remember).await?;
37
38        let mut context_opts = GetContextOptions::default();
39        context_opts.run_id = Some(run_id.clone());
40        context_opts.query = Some("Why did the deploy fail?".to_string());
41        context_opts.entry_types = vec!["lesson".to_string()];
42        context_opts.mode = Some("summary".to_string());
43        let context = client.get_context(context_opts).await?;
44
45        let mut diagnose = DiagnoseOptions::new("deploy failed because migration checksum is stale");
46        diagnose.run_id = Some(run_id.clone());
47        diagnose.error_type = Some("deploy".to_string());
48        diagnose.limit = 5;
49        let diagnosis = client.diagnose(diagnose).await?;
50
51        let mut health_opts = MemoryHealthOptions::default();
52        health_opts.run_id = Some(run_id.clone());
53        health_opts.limit = 100;
54        let health = client.memory_health(health_opts).await?;
55
56        let section_summaries = context
57            .get("section_summaries")
58            .and_then(|value| value.as_array())
59            .ok_or_else(|| boxed_error(format!("section summaries missing: {context}")))?;
60        require(
61            diagnosis
62                .get("total_failure_lessons")
63                .and_then(|value| value.as_u64())
64                .unwrap_or(0)
65                >= 1,
66            format!("diagnose should surface a failure lesson: {diagnosis}"),
67        )?;
68        require(
69            health.get("entry_counts").and_then(|value| value.as_object()).is_some(),
70            format!("memory health missing entry counts: {health}"),
71        )?;
72
73        metrics = json!({
74            "run_id": run_id,
75            "section_count": section_summaries.len(),
76            "total_failure_lessons": diagnosis.get("total_failure_lessons").cloned().unwrap_or(serde_json::Value::Null),
77            "entry_count_keys": health.get("entry_counts").and_then(|value| value.as_object()).map(|map| map.len()).unwrap_or(0),
78        });
79
80        Ok::<(), Box<dyn Error>>(())
81    }
82    .await;
83
84    if let Err(err) = scenario {
85        passed = false;
86        detail = err.to_string();
87    }
88
89    let cleanup_ok = cleanup_run(&client, &run_id).await;
90    if !cleanup_ok {
91        passed = false;
92        detail = format!("{detail} | cleanup failures");
93    }
94
95    print_summary(
96        name,
97        passed,
98        &detail,
99        &metrics,
100        started.elapsed().as_secs_f64(),
101        cleanup_ok,
102    );
103
104    if passed {
105        Ok(())
106    } else {
107        Err(boxed_error(detail))
108    }
109}
More examples
Hide additional examples
examples/helper_context_diagnose_memory_health.rs (line 49)
13async fn main() -> Result<(), Box<dyn Error>> {
14    let name = "helper_context_diagnose_memory_health";
15    let started = Instant::now();
16    let client = create_client().await?;
17    let run_id = new_run_id("helper_context_diagnose_memory_health");
18    client.set_run_id(Some(run_id.clone()));
19    client.set_transport(TransportMode::Http);
20
21    let mut passed = true;
22    let mut detail = "validated helper context + diagnose + memory health flow".to_string();
23    let mut metrics = json!({});
24
25    let scenario = async {
26        let mut remember = RememberOptions::new(
27            "Deploys fail when the migration checksum is stale after a force-push.",
28        );
29        remember.run_id = Some(run_id.clone());
30        remember.agent_id = Some("observer".to_string());
31        remember.intent = Some("lesson".to_string());
32        remember.lesson_type = Some("failure".to_string());
33        remember.lesson_scope = Some("session".to_string());
34        remember.lesson_importance = Some("high".to_string());
35        remember.metadata = Some(json!({ "source": "rust-helper-example" }));
36        client.remember(remember).await?;
37
38        let mut context_opts = GetContextOptions::default();
39        context_opts.run_id = Some(run_id.clone());
40        context_opts.query = Some("Why did the deploy fail?".to_string());
41        context_opts.entry_types = vec!["lesson".to_string()];
42        context_opts.mode = Some("summary".to_string());
43        let context = client.get_context(context_opts).await?;
44
45        let mut diagnose = DiagnoseOptions::new("deploy failed because migration checksum is stale");
46        diagnose.run_id = Some(run_id.clone());
47        diagnose.error_type = Some("deploy".to_string());
48        diagnose.limit = 5;
49        let diagnosis = client.diagnose(diagnose).await?;
50
51        let mut health_opts = MemoryHealthOptions::default();
52        health_opts.run_id = Some(run_id.clone());
53        health_opts.limit = 100;
54        let health = client.memory_health(health_opts).await?;
55
56        let section_summaries = context
57            .get("section_summaries")
58            .and_then(|value| value.as_array())
59            .ok_or_else(|| boxed_error(format!("section summaries missing: {context}")))?;
60        require(
61            diagnosis
62                .get("total_failure_lessons")
63                .and_then(|value| value.as_u64())
64                .unwrap_or(0)
65                >= 1,
66            format!("diagnose should surface a failure lesson: {diagnosis}"),
67        )?;
68        require(
69            health.get("entry_counts").and_then(|value| value.as_object()).is_some(),
70            format!("memory health missing entry counts: {health}"),
71        )?;
72
73        metrics = json!({
74            "run_id": run_id,
75            "section_count": section_summaries.len(),
76            "total_failure_lessons": diagnosis.get("total_failure_lessons").cloned().unwrap_or(serde_json::Value::Null),
77            "entry_count_keys": health.get("entry_counts").and_then(|value| value.as_object()).map(|map| map.len()).unwrap_or(0),
78        });
79
80        Ok::<(), Box<dyn Error>>(())
81    }
82    .await;
83
84    if let Err(err) = scenario {
85        passed = false;
86        detail = err.to_string();
87    }
88
89    let cleanup_ok = cleanup_run(&client, &run_id).await;
90    if !cleanup_ok {
91        passed = false;
92        detail = format!("{detail} | cleanup failures");
93    }
94
95    print_summary(
96        name,
97        passed,
98        &detail,
99        &metrics,
100        started.elapsed().as_secs_f64(),
101        cleanup_ok,
102    );
103
104    if passed {
105        Ok(())
106    } else {
107        Err(boxed_error(detail))
108    }
109}
examples/public/10_full_learning_loop_smoke.rs (line 81)
16async fn main() -> Result<(), Box<dyn Error>> {
17    let name = "public_10_full_learning_loop_smoke";
18    let started = Instant::now();
19    let client = create_client().await?;
20    let run_id = new_run_id("public_10_full_learning_loop_smoke");
21    client.set_run_id(Some(run_id.clone()));
22    client.set_transport(TransportMode::Http);
23
24    let mut passed = true;
25    let mut detail = "validated all helper flows".to_string();
26    let mut metrics = json!({});
27
28    let scenario = async {
29        let mut remember = RememberOptions::new("Policy limit is 5000 and claimant city is Leeds.");
30        remember.run_id = Some(run_id.clone());
31        remember.agent_id = Some("planner".to_string());
32        remember.intent = Some("fact".to_string());
33        remember.metadata = Some(json!({"suite": "all-helpers", "family": "claims"}));
34        remember.importance = Some("high".to_string());
35        remember.occurrence_time = Some(std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as i64 - 86400);
36        let remember_response = client.remember(remember).await?;
37
38        let mut lesson = RememberOptions::new("If city is missing from the latest step, check stored claim facts before escalating.");
39        lesson.run_id = Some(run_id.clone());
40        lesson.agent_id = Some("planner".to_string());
41        lesson.intent = Some("lesson".to_string());
42        lesson.lesson_type = Some("success".to_string());
43        lesson.lesson_scope = Some("session".to_string());
44        lesson.lesson_importance = Some("high".to_string());
45        let lesson_response = client.remember(lesson).await?;
46
47        let mut mental_model = RememberOptions::new(
48            "Claims case overview: Policy limit 5000 GBP, claimant city Leeds, \
49             missing-city branch resolved via stored claim facts. Lesson: check stored facts before escalating.",
50        );
51        mental_model.run_id = Some(run_id.clone());
52        mental_model.agent_id = Some("planner".to_string());
53        mental_model.intent = Some("mental_model".to_string());
54        mental_model.importance = Some("critical".to_string());
55        mental_model.metadata = Some(json!({"suite": "all-helpers", "entity": "claims-case", "consolidated": true}));
56        let mental_model_response = client.remember(mental_model).await?;
57
58        let mut recall = RecallOptions::new("What is the policy limit?");
59        recall.run_id = Some(run_id.clone());
60        recall.agent_id = Some("planner".to_string());
61        recall.limit = 5;
62        let recall_response = client.recall(recall).await?;
63
64        let mut context = GetContextOptions::default();
65        context.run_id = Some(run_id.clone());
66        context.query = Some("Prepare a short adjuster summary".to_string());
67        context.agent_id = Some("planner".to_string());
68        context.limit = Some(6);
69        context.max_token_budget = Some(700);
70        let context_response = client.get_context(context).await?;
71
72        let mut health = MemoryHealthOptions::default();
73        health.run_id = Some(run_id.clone());
74        health.limit = 50;
75        let health_response = client.memory_health(health).await?;
76
77        let mut diagnose = DiagnoseOptions::new("policy limit lookup returned empty");
78        diagnose.run_id = Some(run_id.clone());
79        diagnose.error_type = Some("retrieval".to_string());
80        diagnose.limit = 5;
81        let diagnose_response = client.diagnose(diagnose).await?;
82
83        let mut reflect = ReflectOptions::default();
84        reflect.run_id = Some(run_id.clone());
85        let reflect_response = client.reflect(reflect).await?;
86
87        let mut register = RegisterAgentOptions::new("planner");
88        register.run_id = Some(run_id.clone());
89        register.role = "planner".to_string();
90        register.read_scopes = vec!["fact".into(), "lesson".into(), "rule".into(), "mental_model".into(), "archive_block".into(), "handoff".into(), "feedback".into()];
91        register.write_scopes = vec!["fact".into(), "trace".into(), "lesson".into(), "observation".into(), "archive_block".into()];
92        register.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
93        let register_response = client.register_agent(register).await?;
94
95        let mut list_agents = ListAgentsOptions::default();
96        list_agents.run_id = Some(run_id.clone());
97        let agents_response = client.list_agents(list_agents).await?;
98
99        let mut archive = ArchiveOptions::new(
100            "Exact adjuster note: claimant confirmed city is Leeds during triage.",
101            "adjuster_note",
102        );
103        archive.run_id = Some(run_id.clone());
104        archive.agent_id = Some("planner".to_string());
105        archive.origin_agent_id = Some("planner".to_string());
106        archive.source_attempt_id = Some("attempt-1".to_string());
107        archive.source_tool = Some("phone_call".to_string());
108        archive.labels = vec!["claims".to_string(), "triage".to_string()];
109        archive.family = Some("claims-adjustment".to_string());
110        archive.metadata = Some(json!({"case": "all-helpers"}));
111        let archive_response = client.archive(archive).await?;
112        let reference_id = archive_response
113            .get("reference_id")
114            .and_then(Value::as_str)
115            .ok_or_else(|| boxed_error(format!("archive reference missing: {archive_response}")))?
116            .to_string();
117
118        let mut dereference = DereferenceOptions::new(reference_id.clone());
119        dereference.run_id = Some(run_id.clone());
120        dereference.agent_id = Some("planner".to_string());
121        let dereference_response = client.dereference(dereference).await?;
122
123        let mut checkpoint = CheckpointOptions::new("Planner captured claim facts before window compaction.");
124        checkpoint.run_id = Some(run_id.clone());
125        checkpoint.label = Some("pre-compaction".to_string());
126        checkpoint.metadata = Some(json!({"stage": "analysis"}));
127        checkpoint.agent_id = Some("planner".to_string());
128        let checkpoint_response = client.checkpoint(checkpoint).await?;
129
130        let lessons_response = client.control.lessons(json!({"run_id": run_id, "limit": 20})).await?;
131        let lesson_id = lessons_response
132            .get("lessons")
133            .and_then(Value::as_array)
134            .and_then(|items| items.iter().find_map(|item| item.get("id").and_then(Value::as_str)))
135            .ok_or_else(|| boxed_error(format!("expected lesson id for outcome flow: {lessons_response}")))?
136            .to_string();
137
138        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
139        outcome.run_id = Some(run_id.clone());
140        outcome.signal = 0.75;
141        outcome.rationale = "Planner reused stored claim fact and resolved the missing-city branch.".to_string();
142        outcome.agent_id = Some("planner".to_string());
143        let outcome_response = client.record_outcome(outcome).await?;
144
145        let mut strategies = SurfaceStrategiesOptions::default();
146        strategies.run_id = Some(run_id.clone());
147        strategies.lesson_types = vec!["success".to_string(), "rule".to_string()];
148        strategies.max_strategies = 5;
149        let strategies_response = client.surface_strategies(strategies).await?;
150
151        let mut handoff = HandoffOptions::new(
152            "claim-1",
153            "planner",
154            "reviewer",
155            "Review whether the stored claimant city is sufficient for routing.",
156        );
157        handoff.run_id = Some(run_id.clone());
158        handoff.requested_action = "review".to_string();
159        handoff.metadata = Some(json!({"team": "claims"}));
160        let handoff_response = client.handoff(handoff).await?;
161        let handoff_id = handoff_response
162            .get("handoff_id")
163            .and_then(Value::as_str)
164            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
165            .to_string();
166
167        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
168        feedback.run_id = Some(run_id.clone());
169        feedback.comments = "Stored fact is sufficient; proceed without escalation.".to_string();
170        feedback.from_agent_id = Some("reviewer".to_string());
171        feedback.metadata = Some(json!({"team": "claims"}));
172        let feedback_response = client.feedback(feedback).await?;
173
174        require(remember_response.get("job_id").is_some() || remember_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("remember failed: {remember_response}"))?;
175        require(mental_model_response.get("job_id").is_some() || mental_model_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("mental_model remember failed: {mental_model_response}"))?;
176        require(lesson_response.get("job_id").is_some() || lesson_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("lesson remember failed: {lesson_response}"))?;
177        require(recall_response.get("final_answer").is_some() || recall_response.get("evidence").is_some(), format!("recall failed: {recall_response}"))?;
178        require(context_response.get("sources").and_then(Value::as_array).is_some(), format!("context malformed: {context_response}"))?;
179        require(health_response.get("entry_counts").and_then(Value::as_object).is_some(), format!("memory_health malformed: {health_response}"))?;
180        require(diagnose_response.get("failure_lessons").and_then(Value::as_array).is_some(), format!("diagnose malformed: {diagnose_response}"))?;
181        require(reflect_response.get("lessons").and_then(Value::as_array).is_some(), format!("reflect malformed: {reflect_response}"))?;
182        require(register_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("register_agent failed: {register_response}"))?;
183        require(agents_response.get("agents").and_then(Value::as_array).map(|items| !items.is_empty()).unwrap_or(false), format!("list_agents failed: {agents_response}"))?;
184        require(archive_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("archive failed: {archive_response}"))?;
185        require(dereference_response.get("found").and_then(Value::as_bool).unwrap_or(false), format!("dereference failed: {dereference_response}"))?;
186        require(checkpoint_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
187        require(outcome_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("record_outcome failed: {outcome_response}"))?;
188        require(strategies_response.get("strategies").and_then(Value::as_array).is_some(), format!("surface_strategies malformed: {strategies_response}"))?;
189        require(handoff_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
190        require(feedback_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
191
192        let strategy_count = strategies_response
193            .get("strategies")
194            .and_then(Value::as_array)
195            .map(|items| items.len())
196            .unwrap_or(0);
197        let agent_count = agents_response
198            .get("agents")
199            .and_then(Value::as_array)
200            .map(|items| items.len())
201            .unwrap_or(0);
202        let lesson_count = lessons_response
203            .get("lessons")
204            .and_then(Value::as_array)
205            .map(|items| items.len())
206            .unwrap_or(0);
207
208        metrics = json!({
209            "run_id": run_id,
210            "agent_count": agent_count,
211            "strategy_count": strategy_count,
212            "reference_id": reference_id,
213            "lesson_count": lesson_count,
214        });
215
216        Ok::<(), Box<dyn Error>>(())
217    }
218    .await;
219
220    if let Err(err) = scenario {
221        passed = false;
222        detail = err.to_string();
223    }
224
225    let cleanup_ok = cleanup_run(&client, &run_id).await;
226    if !cleanup_ok {
227        passed = false;
228        detail = format!("{detail} | cleanup failures");
229    }
230
231    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
232
233    if passed { Ok(()) } else { Err(boxed_error(detail)) }
234}
examples/helper_all_helpers.rs (line 69)
16async fn main() -> Result<(), Box<dyn Error>> {
17    let name = "helper_all_helpers";
18    let started = Instant::now();
19    let client = create_client().await?;
20    let run_id = new_run_id("helper_all_helpers");
21    client.set_run_id(Some(run_id.clone()));
22    client.set_transport(TransportMode::Http);
23
24    let mut passed = true;
25    let mut detail = "validated all helper flows".to_string();
26    let mut metrics = json!({});
27
28    let scenario = async {
29        let mut remember = RememberOptions::new("Policy limit is 5000 and claimant city is Leeds.");
30        remember.run_id = Some(run_id.clone());
31        remember.agent_id = Some("planner".to_string());
32        remember.intent = Some("fact".to_string());
33        remember.metadata = Some(json!({"suite": "all-helpers", "family": "claims"}));
34        remember.importance = Some("high".to_string());
35        let remember_response = client.remember(remember).await?;
36
37        let mut lesson = RememberOptions::new("If city is missing from the latest step, check stored claim facts before escalating.");
38        lesson.run_id = Some(run_id.clone());
39        lesson.agent_id = Some("planner".to_string());
40        lesson.intent = Some("lesson".to_string());
41        lesson.lesson_type = Some("success".to_string());
42        lesson.lesson_scope = Some("session".to_string());
43        lesson.lesson_importance = Some("high".to_string());
44        let lesson_response = client.remember(lesson).await?;
45
46        let mut recall = RecallOptions::new("What is the policy limit?");
47        recall.run_id = Some(run_id.clone());
48        recall.agent_id = Some("planner".to_string());
49        recall.limit = 5;
50        let recall_response = client.recall(recall).await?;
51
52        let mut context = GetContextOptions::default();
53        context.run_id = Some(run_id.clone());
54        context.query = Some("Prepare a short adjuster summary".to_string());
55        context.agent_id = Some("planner".to_string());
56        context.limit = Some(6);
57        context.max_token_budget = Some(700);
58        let context_response = client.get_context(context).await?;
59
60        let mut health = MemoryHealthOptions::default();
61        health.run_id = Some(run_id.clone());
62        health.limit = 50;
63        let health_response = client.memory_health(health).await?;
64
65        let mut diagnose = DiagnoseOptions::new("policy limit lookup returned empty");
66        diagnose.run_id = Some(run_id.clone());
67        diagnose.error_type = Some("retrieval".to_string());
68        diagnose.limit = 5;
69        let diagnose_response = client.diagnose(diagnose).await?;
70
71        let mut reflect = ReflectOptions::default();
72        reflect.run_id = Some(run_id.clone());
73        let reflect_response = client.reflect(reflect).await?;
74
75        let mut register = RegisterAgentOptions::new("planner");
76        register.run_id = Some(run_id.clone());
77        register.role = "planner".to_string();
78        register.read_scopes = vec!["fact".into(), "lesson".into(), "rule".into(), "archive_block".into(), "handoff".into(), "feedback".into()];
79        register.write_scopes = vec!["fact".into(), "trace".into(), "lesson".into(), "observation".into(), "archive_block".into()];
80        register.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
81        let register_response = client.register_agent(register).await?;
82
83        let mut list_agents = ListAgentsOptions::default();
84        list_agents.run_id = Some(run_id.clone());
85        let agents_response = client.list_agents(list_agents).await?;
86
87        let mut archive = ArchiveOptions::new(
88            "Exact adjuster note: claimant confirmed city is Leeds during triage.",
89            "adjuster_note",
90        );
91        archive.run_id = Some(run_id.clone());
92        archive.agent_id = Some("planner".to_string());
93        archive.origin_agent_id = Some("planner".to_string());
94        archive.source_attempt_id = Some("attempt-1".to_string());
95        archive.source_tool = Some("phone_call".to_string());
96        archive.labels = vec!["claims".to_string(), "triage".to_string()];
97        archive.family = Some("claims-adjustment".to_string());
98        archive.metadata = Some(json!({"case": "all-helpers"}));
99        let archive_response = client.archive(archive).await?;
100        let reference_id = archive_response
101            .get("reference_id")
102            .and_then(Value::as_str)
103            .ok_or_else(|| boxed_error(format!("archive reference missing: {archive_response}")))?
104            .to_string();
105
106        let mut dereference = DereferenceOptions::new(reference_id.clone());
107        dereference.run_id = Some(run_id.clone());
108        dereference.agent_id = Some("planner".to_string());
109        let dereference_response = client.dereference(dereference).await?;
110
111        let mut checkpoint = CheckpointOptions::new("Planner captured claim facts before window compaction.");
112        checkpoint.run_id = Some(run_id.clone());
113        checkpoint.label = Some("pre-compaction".to_string());
114        checkpoint.metadata = Some(json!({"stage": "analysis"}));
115        checkpoint.agent_id = Some("planner".to_string());
116        let checkpoint_response = client.checkpoint(checkpoint).await?;
117
118        let lessons_response = client.control.lessons(json!({"run_id": run_id, "limit": 20})).await?;
119        let lesson_id = lessons_response
120            .get("lessons")
121            .and_then(Value::as_array)
122            .and_then(|items| items.iter().find_map(|item| item.get("id").and_then(Value::as_str)))
123            .ok_or_else(|| boxed_error(format!("expected lesson id for outcome flow: {lessons_response}")))?
124            .to_string();
125
126        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
127        outcome.run_id = Some(run_id.clone());
128        outcome.signal = 0.75;
129        outcome.rationale = "Planner reused stored claim fact and resolved the missing-city branch.".to_string();
130        outcome.agent_id = Some("planner".to_string());
131        let outcome_response = client.record_outcome(outcome).await?;
132
133        let mut strategies = SurfaceStrategiesOptions::default();
134        strategies.run_id = Some(run_id.clone());
135        strategies.lesson_types = vec!["success".to_string(), "rule".to_string()];
136        strategies.max_strategies = 5;
137        let strategies_response = client.surface_strategies(strategies).await?;
138
139        let mut handoff = HandoffOptions::new(
140            "claim-1",
141            "planner",
142            "reviewer",
143            "Review whether the stored claimant city is sufficient for routing.",
144        );
145        handoff.run_id = Some(run_id.clone());
146        handoff.requested_action = "review".to_string();
147        handoff.metadata = Some(json!({"team": "claims"}));
148        let handoff_response = client.handoff(handoff).await?;
149        let handoff_id = handoff_response
150            .get("handoff_id")
151            .and_then(Value::as_str)
152            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
153            .to_string();
154
155        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
156        feedback.run_id = Some(run_id.clone());
157        feedback.comments = "Stored fact is sufficient; proceed without escalation.".to_string();
158        feedback.from_agent_id = Some("reviewer".to_string());
159        feedback.metadata = Some(json!({"team": "claims"}));
160        let feedback_response = client.feedback(feedback).await?;
161
162        let scratch_run = format!("{run_id}_forget");
163        let mut scratch = RememberOptions::new("Scratch run for forget helper coverage.");
164        scratch.run_id = Some(scratch_run.clone());
165        scratch.agent_id = Some("planner".to_string());
166        scratch.intent = Some("fact".to_string());
167        scratch.metadata = Some(json!({"suite": "all-helpers", "temporary": true}));
168        let scratch_response = client.remember(scratch).await?;
169
170        let forget_response = client
171            .forget(ForgetOptions::for_run(scratch_run.clone()))
172            .await?;
173
174        let mut forgotten = RecallOptions::new("What temporary scratch fact exists?");
175        forgotten.run_id = Some(scratch_run.clone());
176        forgotten.limit = 3;
177        let forgotten_response = client.recall(forgotten).await?;
178
179        require(remember_response.get("job_id").is_some() || remember_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("remember failed: {remember_response}"))?;
180        require(lesson_response.get("job_id").is_some() || lesson_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("lesson remember failed: {lesson_response}"))?;
181        require(recall_response.get("final_answer").is_some() || recall_response.get("evidence").is_some(), format!("recall failed: {recall_response}"))?;
182        require(context_response.get("sources").and_then(Value::as_array).is_some(), format!("context malformed: {context_response}"))?;
183        require(health_response.get("entry_counts").and_then(Value::as_object).is_some(), format!("memory_health malformed: {health_response}"))?;
184        require(diagnose_response.get("failure_lessons").and_then(Value::as_array).is_some(), format!("diagnose malformed: {diagnose_response}"))?;
185        require(reflect_response.get("lessons").and_then(Value::as_array).is_some(), format!("reflect malformed: {reflect_response}"))?;
186        require(register_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("register_agent failed: {register_response}"))?;
187        require(agents_response.get("agents").and_then(Value::as_array).map(|items| !items.is_empty()).unwrap_or(false), format!("list_agents failed: {agents_response}"))?;
188        require(archive_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("archive failed: {archive_response}"))?;
189        require(dereference_response.get("found").and_then(Value::as_bool).unwrap_or(false), format!("dereference failed: {dereference_response}"))?;
190        require(checkpoint_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
191        require(outcome_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("record_outcome failed: {outcome_response}"))?;
192        require(strategies_response.get("strategies").and_then(Value::as_array).is_some(), format!("surface_strategies malformed: {strategies_response}"))?;
193        require(handoff_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
194        require(feedback_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
195        require(scratch_response.get("job_id").is_some() || scratch_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("scratch remember failed: {scratch_response}"))?;
196        require(forget_response.get("success").and_then(Value::as_bool).unwrap_or(true), format!("forget failed: {forget_response}"))?;
197        let scratch_fact_visible = forgotten_response
198            .get("evidence")
199            .and_then(Value::as_array)
200            .map(|items| {
201                items.iter().any(|item| {
202                    item.get("run_id").and_then(Value::as_str) == Some(scratch_run.as_str())
203                        || item
204                            .get("content")
205                            .and_then(Value::as_str)
206                            .map(|content| {
207                                content
208                                    .to_ascii_lowercase()
209                                    .contains("scratch run for forget helper coverage")
210                            })
211                            .unwrap_or(false)
212                })
213            })
214            .unwrap_or(false);
215        require(!scratch_fact_visible, format!("scratch fact should be forgotten even if same-user lessons still surface: {forgotten_response}"))?;
216
217        let strategy_count = strategies_response
218            .get("strategies")
219            .and_then(Value::as_array)
220            .map(|items| items.len())
221            .unwrap_or(0);
222        let agent_count = agents_response
223            .get("agents")
224            .and_then(Value::as_array)
225            .map(|items| items.len())
226            .unwrap_or(0);
227        let lesson_count = lessons_response
228            .get("lessons")
229            .and_then(Value::as_array)
230            .map(|items| items.len())
231            .unwrap_or(0);
232
233        metrics = json!({
234            "run_id": run_id,
235            "agent_count": agent_count,
236            "strategy_count": strategy_count,
237            "reference_id": reference_id,
238            "lesson_count": lesson_count,
239            "forgotten_run": scratch_run,
240        });
241
242        Ok::<(), Box<dyn Error>>(())
243    }
244    .await;
245
246    if let Err(err) = scenario {
247        passed = false;
248        detail = err.to_string();
249    }
250
251    let cleanup_ok = cleanup_run(&client, &run_id).await;
252    if !cleanup_ok {
253        passed = false;
254        detail = format!("{detail} | cleanup failures");
255    }
256
257    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
258
259    if passed { Ok(()) } else { Err(boxed_error(detail)) }
260}
Source

pub async fn reflect(&self, options: ReflectOptions) -> Result<Value>

Examples found in repository?
examples/public/10_full_learning_loop_smoke.rs (line 85)
16async fn main() -> Result<(), Box<dyn Error>> {
17    let name = "public_10_full_learning_loop_smoke";
18    let started = Instant::now();
19    let client = create_client().await?;
20    let run_id = new_run_id("public_10_full_learning_loop_smoke");
21    client.set_run_id(Some(run_id.clone()));
22    client.set_transport(TransportMode::Http);
23
24    let mut passed = true;
25    let mut detail = "validated all helper flows".to_string();
26    let mut metrics = json!({});
27
28    let scenario = async {
29        let mut remember = RememberOptions::new("Policy limit is 5000 and claimant city is Leeds.");
30        remember.run_id = Some(run_id.clone());
31        remember.agent_id = Some("planner".to_string());
32        remember.intent = Some("fact".to_string());
33        remember.metadata = Some(json!({"suite": "all-helpers", "family": "claims"}));
34        remember.importance = Some("high".to_string());
35        remember.occurrence_time = Some(std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as i64 - 86400);
36        let remember_response = client.remember(remember).await?;
37
38        let mut lesson = RememberOptions::new("If city is missing from the latest step, check stored claim facts before escalating.");
39        lesson.run_id = Some(run_id.clone());
40        lesson.agent_id = Some("planner".to_string());
41        lesson.intent = Some("lesson".to_string());
42        lesson.lesson_type = Some("success".to_string());
43        lesson.lesson_scope = Some("session".to_string());
44        lesson.lesson_importance = Some("high".to_string());
45        let lesson_response = client.remember(lesson).await?;
46
47        let mut mental_model = RememberOptions::new(
48            "Claims case overview: Policy limit 5000 GBP, claimant city Leeds, \
49             missing-city branch resolved via stored claim facts. Lesson: check stored facts before escalating.",
50        );
51        mental_model.run_id = Some(run_id.clone());
52        mental_model.agent_id = Some("planner".to_string());
53        mental_model.intent = Some("mental_model".to_string());
54        mental_model.importance = Some("critical".to_string());
55        mental_model.metadata = Some(json!({"suite": "all-helpers", "entity": "claims-case", "consolidated": true}));
56        let mental_model_response = client.remember(mental_model).await?;
57
58        let mut recall = RecallOptions::new("What is the policy limit?");
59        recall.run_id = Some(run_id.clone());
60        recall.agent_id = Some("planner".to_string());
61        recall.limit = 5;
62        let recall_response = client.recall(recall).await?;
63
64        let mut context = GetContextOptions::default();
65        context.run_id = Some(run_id.clone());
66        context.query = Some("Prepare a short adjuster summary".to_string());
67        context.agent_id = Some("planner".to_string());
68        context.limit = Some(6);
69        context.max_token_budget = Some(700);
70        let context_response = client.get_context(context).await?;
71
72        let mut health = MemoryHealthOptions::default();
73        health.run_id = Some(run_id.clone());
74        health.limit = 50;
75        let health_response = client.memory_health(health).await?;
76
77        let mut diagnose = DiagnoseOptions::new("policy limit lookup returned empty");
78        diagnose.run_id = Some(run_id.clone());
79        diagnose.error_type = Some("retrieval".to_string());
80        diagnose.limit = 5;
81        let diagnose_response = client.diagnose(diagnose).await?;
82
83        let mut reflect = ReflectOptions::default();
84        reflect.run_id = Some(run_id.clone());
85        let reflect_response = client.reflect(reflect).await?;
86
87        let mut register = RegisterAgentOptions::new("planner");
88        register.run_id = Some(run_id.clone());
89        register.role = "planner".to_string();
90        register.read_scopes = vec!["fact".into(), "lesson".into(), "rule".into(), "mental_model".into(), "archive_block".into(), "handoff".into(), "feedback".into()];
91        register.write_scopes = vec!["fact".into(), "trace".into(), "lesson".into(), "observation".into(), "archive_block".into()];
92        register.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
93        let register_response = client.register_agent(register).await?;
94
95        let mut list_agents = ListAgentsOptions::default();
96        list_agents.run_id = Some(run_id.clone());
97        let agents_response = client.list_agents(list_agents).await?;
98
99        let mut archive = ArchiveOptions::new(
100            "Exact adjuster note: claimant confirmed city is Leeds during triage.",
101            "adjuster_note",
102        );
103        archive.run_id = Some(run_id.clone());
104        archive.agent_id = Some("planner".to_string());
105        archive.origin_agent_id = Some("planner".to_string());
106        archive.source_attempt_id = Some("attempt-1".to_string());
107        archive.source_tool = Some("phone_call".to_string());
108        archive.labels = vec!["claims".to_string(), "triage".to_string()];
109        archive.family = Some("claims-adjustment".to_string());
110        archive.metadata = Some(json!({"case": "all-helpers"}));
111        let archive_response = client.archive(archive).await?;
112        let reference_id = archive_response
113            .get("reference_id")
114            .and_then(Value::as_str)
115            .ok_or_else(|| boxed_error(format!("archive reference missing: {archive_response}")))?
116            .to_string();
117
118        let mut dereference = DereferenceOptions::new(reference_id.clone());
119        dereference.run_id = Some(run_id.clone());
120        dereference.agent_id = Some("planner".to_string());
121        let dereference_response = client.dereference(dereference).await?;
122
123        let mut checkpoint = CheckpointOptions::new("Planner captured claim facts before window compaction.");
124        checkpoint.run_id = Some(run_id.clone());
125        checkpoint.label = Some("pre-compaction".to_string());
126        checkpoint.metadata = Some(json!({"stage": "analysis"}));
127        checkpoint.agent_id = Some("planner".to_string());
128        let checkpoint_response = client.checkpoint(checkpoint).await?;
129
130        let lessons_response = client.control.lessons(json!({"run_id": run_id, "limit": 20})).await?;
131        let lesson_id = lessons_response
132            .get("lessons")
133            .and_then(Value::as_array)
134            .and_then(|items| items.iter().find_map(|item| item.get("id").and_then(Value::as_str)))
135            .ok_or_else(|| boxed_error(format!("expected lesson id for outcome flow: {lessons_response}")))?
136            .to_string();
137
138        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
139        outcome.run_id = Some(run_id.clone());
140        outcome.signal = 0.75;
141        outcome.rationale = "Planner reused stored claim fact and resolved the missing-city branch.".to_string();
142        outcome.agent_id = Some("planner".to_string());
143        let outcome_response = client.record_outcome(outcome).await?;
144
145        let mut strategies = SurfaceStrategiesOptions::default();
146        strategies.run_id = Some(run_id.clone());
147        strategies.lesson_types = vec!["success".to_string(), "rule".to_string()];
148        strategies.max_strategies = 5;
149        let strategies_response = client.surface_strategies(strategies).await?;
150
151        let mut handoff = HandoffOptions::new(
152            "claim-1",
153            "planner",
154            "reviewer",
155            "Review whether the stored claimant city is sufficient for routing.",
156        );
157        handoff.run_id = Some(run_id.clone());
158        handoff.requested_action = "review".to_string();
159        handoff.metadata = Some(json!({"team": "claims"}));
160        let handoff_response = client.handoff(handoff).await?;
161        let handoff_id = handoff_response
162            .get("handoff_id")
163            .and_then(Value::as_str)
164            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
165            .to_string();
166
167        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
168        feedback.run_id = Some(run_id.clone());
169        feedback.comments = "Stored fact is sufficient; proceed without escalation.".to_string();
170        feedback.from_agent_id = Some("reviewer".to_string());
171        feedback.metadata = Some(json!({"team": "claims"}));
172        let feedback_response = client.feedback(feedback).await?;
173
174        require(remember_response.get("job_id").is_some() || remember_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("remember failed: {remember_response}"))?;
175        require(mental_model_response.get("job_id").is_some() || mental_model_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("mental_model remember failed: {mental_model_response}"))?;
176        require(lesson_response.get("job_id").is_some() || lesson_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("lesson remember failed: {lesson_response}"))?;
177        require(recall_response.get("final_answer").is_some() || recall_response.get("evidence").is_some(), format!("recall failed: {recall_response}"))?;
178        require(context_response.get("sources").and_then(Value::as_array).is_some(), format!("context malformed: {context_response}"))?;
179        require(health_response.get("entry_counts").and_then(Value::as_object).is_some(), format!("memory_health malformed: {health_response}"))?;
180        require(diagnose_response.get("failure_lessons").and_then(Value::as_array).is_some(), format!("diagnose malformed: {diagnose_response}"))?;
181        require(reflect_response.get("lessons").and_then(Value::as_array).is_some(), format!("reflect malformed: {reflect_response}"))?;
182        require(register_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("register_agent failed: {register_response}"))?;
183        require(agents_response.get("agents").and_then(Value::as_array).map(|items| !items.is_empty()).unwrap_or(false), format!("list_agents failed: {agents_response}"))?;
184        require(archive_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("archive failed: {archive_response}"))?;
185        require(dereference_response.get("found").and_then(Value::as_bool).unwrap_or(false), format!("dereference failed: {dereference_response}"))?;
186        require(checkpoint_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
187        require(outcome_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("record_outcome failed: {outcome_response}"))?;
188        require(strategies_response.get("strategies").and_then(Value::as_array).is_some(), format!("surface_strategies malformed: {strategies_response}"))?;
189        require(handoff_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
190        require(feedback_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
191
192        let strategy_count = strategies_response
193            .get("strategies")
194            .and_then(Value::as_array)
195            .map(|items| items.len())
196            .unwrap_or(0);
197        let agent_count = agents_response
198            .get("agents")
199            .and_then(Value::as_array)
200            .map(|items| items.len())
201            .unwrap_or(0);
202        let lesson_count = lessons_response
203            .get("lessons")
204            .and_then(Value::as_array)
205            .map(|items| items.len())
206            .unwrap_or(0);
207
208        metrics = json!({
209            "run_id": run_id,
210            "agent_count": agent_count,
211            "strategy_count": strategy_count,
212            "reference_id": reference_id,
213            "lesson_count": lesson_count,
214        });
215
216        Ok::<(), Box<dyn Error>>(())
217    }
218    .await;
219
220    if let Err(err) = scenario {
221        passed = false;
222        detail = err.to_string();
223    }
224
225    let cleanup_ok = cleanup_run(&client, &run_id).await;
226    if !cleanup_ok {
227        passed = false;
228        detail = format!("{detail} | cleanup failures");
229    }
230
231    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
232
233    if passed { Ok(()) } else { Err(boxed_error(detail)) }
234}
More examples
Hide additional examples
examples/helper_all_helpers.rs (line 73)
16async fn main() -> Result<(), Box<dyn Error>> {
17    let name = "helper_all_helpers";
18    let started = Instant::now();
19    let client = create_client().await?;
20    let run_id = new_run_id("helper_all_helpers");
21    client.set_run_id(Some(run_id.clone()));
22    client.set_transport(TransportMode::Http);
23
24    let mut passed = true;
25    let mut detail = "validated all helper flows".to_string();
26    let mut metrics = json!({});
27
28    let scenario = async {
29        let mut remember = RememberOptions::new("Policy limit is 5000 and claimant city is Leeds.");
30        remember.run_id = Some(run_id.clone());
31        remember.agent_id = Some("planner".to_string());
32        remember.intent = Some("fact".to_string());
33        remember.metadata = Some(json!({"suite": "all-helpers", "family": "claims"}));
34        remember.importance = Some("high".to_string());
35        let remember_response = client.remember(remember).await?;
36
37        let mut lesson = RememberOptions::new("If city is missing from the latest step, check stored claim facts before escalating.");
38        lesson.run_id = Some(run_id.clone());
39        lesson.agent_id = Some("planner".to_string());
40        lesson.intent = Some("lesson".to_string());
41        lesson.lesson_type = Some("success".to_string());
42        lesson.lesson_scope = Some("session".to_string());
43        lesson.lesson_importance = Some("high".to_string());
44        let lesson_response = client.remember(lesson).await?;
45
46        let mut recall = RecallOptions::new("What is the policy limit?");
47        recall.run_id = Some(run_id.clone());
48        recall.agent_id = Some("planner".to_string());
49        recall.limit = 5;
50        let recall_response = client.recall(recall).await?;
51
52        let mut context = GetContextOptions::default();
53        context.run_id = Some(run_id.clone());
54        context.query = Some("Prepare a short adjuster summary".to_string());
55        context.agent_id = Some("planner".to_string());
56        context.limit = Some(6);
57        context.max_token_budget = Some(700);
58        let context_response = client.get_context(context).await?;
59
60        let mut health = MemoryHealthOptions::default();
61        health.run_id = Some(run_id.clone());
62        health.limit = 50;
63        let health_response = client.memory_health(health).await?;
64
65        let mut diagnose = DiagnoseOptions::new("policy limit lookup returned empty");
66        diagnose.run_id = Some(run_id.clone());
67        diagnose.error_type = Some("retrieval".to_string());
68        diagnose.limit = 5;
69        let diagnose_response = client.diagnose(diagnose).await?;
70
71        let mut reflect = ReflectOptions::default();
72        reflect.run_id = Some(run_id.clone());
73        let reflect_response = client.reflect(reflect).await?;
74
75        let mut register = RegisterAgentOptions::new("planner");
76        register.run_id = Some(run_id.clone());
77        register.role = "planner".to_string();
78        register.read_scopes = vec!["fact".into(), "lesson".into(), "rule".into(), "archive_block".into(), "handoff".into(), "feedback".into()];
79        register.write_scopes = vec!["fact".into(), "trace".into(), "lesson".into(), "observation".into(), "archive_block".into()];
80        register.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
81        let register_response = client.register_agent(register).await?;
82
83        let mut list_agents = ListAgentsOptions::default();
84        list_agents.run_id = Some(run_id.clone());
85        let agents_response = client.list_agents(list_agents).await?;
86
87        let mut archive = ArchiveOptions::new(
88            "Exact adjuster note: claimant confirmed city is Leeds during triage.",
89            "adjuster_note",
90        );
91        archive.run_id = Some(run_id.clone());
92        archive.agent_id = Some("planner".to_string());
93        archive.origin_agent_id = Some("planner".to_string());
94        archive.source_attempt_id = Some("attempt-1".to_string());
95        archive.source_tool = Some("phone_call".to_string());
96        archive.labels = vec!["claims".to_string(), "triage".to_string()];
97        archive.family = Some("claims-adjustment".to_string());
98        archive.metadata = Some(json!({"case": "all-helpers"}));
99        let archive_response = client.archive(archive).await?;
100        let reference_id = archive_response
101            .get("reference_id")
102            .and_then(Value::as_str)
103            .ok_or_else(|| boxed_error(format!("archive reference missing: {archive_response}")))?
104            .to_string();
105
106        let mut dereference = DereferenceOptions::new(reference_id.clone());
107        dereference.run_id = Some(run_id.clone());
108        dereference.agent_id = Some("planner".to_string());
109        let dereference_response = client.dereference(dereference).await?;
110
111        let mut checkpoint = CheckpointOptions::new("Planner captured claim facts before window compaction.");
112        checkpoint.run_id = Some(run_id.clone());
113        checkpoint.label = Some("pre-compaction".to_string());
114        checkpoint.metadata = Some(json!({"stage": "analysis"}));
115        checkpoint.agent_id = Some("planner".to_string());
116        let checkpoint_response = client.checkpoint(checkpoint).await?;
117
118        let lessons_response = client.control.lessons(json!({"run_id": run_id, "limit": 20})).await?;
119        let lesson_id = lessons_response
120            .get("lessons")
121            .and_then(Value::as_array)
122            .and_then(|items| items.iter().find_map(|item| item.get("id").and_then(Value::as_str)))
123            .ok_or_else(|| boxed_error(format!("expected lesson id for outcome flow: {lessons_response}")))?
124            .to_string();
125
126        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
127        outcome.run_id = Some(run_id.clone());
128        outcome.signal = 0.75;
129        outcome.rationale = "Planner reused stored claim fact and resolved the missing-city branch.".to_string();
130        outcome.agent_id = Some("planner".to_string());
131        let outcome_response = client.record_outcome(outcome).await?;
132
133        let mut strategies = SurfaceStrategiesOptions::default();
134        strategies.run_id = Some(run_id.clone());
135        strategies.lesson_types = vec!["success".to_string(), "rule".to_string()];
136        strategies.max_strategies = 5;
137        let strategies_response = client.surface_strategies(strategies).await?;
138
139        let mut handoff = HandoffOptions::new(
140            "claim-1",
141            "planner",
142            "reviewer",
143            "Review whether the stored claimant city is sufficient for routing.",
144        );
145        handoff.run_id = Some(run_id.clone());
146        handoff.requested_action = "review".to_string();
147        handoff.metadata = Some(json!({"team": "claims"}));
148        let handoff_response = client.handoff(handoff).await?;
149        let handoff_id = handoff_response
150            .get("handoff_id")
151            .and_then(Value::as_str)
152            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
153            .to_string();
154
155        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
156        feedback.run_id = Some(run_id.clone());
157        feedback.comments = "Stored fact is sufficient; proceed without escalation.".to_string();
158        feedback.from_agent_id = Some("reviewer".to_string());
159        feedback.metadata = Some(json!({"team": "claims"}));
160        let feedback_response = client.feedback(feedback).await?;
161
162        let scratch_run = format!("{run_id}_forget");
163        let mut scratch = RememberOptions::new("Scratch run for forget helper coverage.");
164        scratch.run_id = Some(scratch_run.clone());
165        scratch.agent_id = Some("planner".to_string());
166        scratch.intent = Some("fact".to_string());
167        scratch.metadata = Some(json!({"suite": "all-helpers", "temporary": true}));
168        let scratch_response = client.remember(scratch).await?;
169
170        let forget_response = client
171            .forget(ForgetOptions::for_run(scratch_run.clone()))
172            .await?;
173
174        let mut forgotten = RecallOptions::new("What temporary scratch fact exists?");
175        forgotten.run_id = Some(scratch_run.clone());
176        forgotten.limit = 3;
177        let forgotten_response = client.recall(forgotten).await?;
178
179        require(remember_response.get("job_id").is_some() || remember_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("remember failed: {remember_response}"))?;
180        require(lesson_response.get("job_id").is_some() || lesson_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("lesson remember failed: {lesson_response}"))?;
181        require(recall_response.get("final_answer").is_some() || recall_response.get("evidence").is_some(), format!("recall failed: {recall_response}"))?;
182        require(context_response.get("sources").and_then(Value::as_array).is_some(), format!("context malformed: {context_response}"))?;
183        require(health_response.get("entry_counts").and_then(Value::as_object).is_some(), format!("memory_health malformed: {health_response}"))?;
184        require(diagnose_response.get("failure_lessons").and_then(Value::as_array).is_some(), format!("diagnose malformed: {diagnose_response}"))?;
185        require(reflect_response.get("lessons").and_then(Value::as_array).is_some(), format!("reflect malformed: {reflect_response}"))?;
186        require(register_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("register_agent failed: {register_response}"))?;
187        require(agents_response.get("agents").and_then(Value::as_array).map(|items| !items.is_empty()).unwrap_or(false), format!("list_agents failed: {agents_response}"))?;
188        require(archive_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("archive failed: {archive_response}"))?;
189        require(dereference_response.get("found").and_then(Value::as_bool).unwrap_or(false), format!("dereference failed: {dereference_response}"))?;
190        require(checkpoint_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
191        require(outcome_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("record_outcome failed: {outcome_response}"))?;
192        require(strategies_response.get("strategies").and_then(Value::as_array).is_some(), format!("surface_strategies malformed: {strategies_response}"))?;
193        require(handoff_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
194        require(feedback_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
195        require(scratch_response.get("job_id").is_some() || scratch_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("scratch remember failed: {scratch_response}"))?;
196        require(forget_response.get("success").and_then(Value::as_bool).unwrap_or(true), format!("forget failed: {forget_response}"))?;
197        let scratch_fact_visible = forgotten_response
198            .get("evidence")
199            .and_then(Value::as_array)
200            .map(|items| {
201                items.iter().any(|item| {
202                    item.get("run_id").and_then(Value::as_str) == Some(scratch_run.as_str())
203                        || item
204                            .get("content")
205                            .and_then(Value::as_str)
206                            .map(|content| {
207                                content
208                                    .to_ascii_lowercase()
209                                    .contains("scratch run for forget helper coverage")
210                            })
211                            .unwrap_or(false)
212                })
213            })
214            .unwrap_or(false);
215        require(!scratch_fact_visible, format!("scratch fact should be forgotten even if same-user lessons still surface: {forgotten_response}"))?;
216
217        let strategy_count = strategies_response
218            .get("strategies")
219            .and_then(Value::as_array)
220            .map(|items| items.len())
221            .unwrap_or(0);
222        let agent_count = agents_response
223            .get("agents")
224            .and_then(Value::as_array)
225            .map(|items| items.len())
226            .unwrap_or(0);
227        let lesson_count = lessons_response
228            .get("lessons")
229            .and_then(Value::as_array)
230            .map(|items| items.len())
231            .unwrap_or(0);
232
233        metrics = json!({
234            "run_id": run_id,
235            "agent_count": agent_count,
236            "strategy_count": strategy_count,
237            "reference_id": reference_id,
238            "lesson_count": lesson_count,
239            "forgotten_run": scratch_run,
240        });
241
242        Ok::<(), Box<dyn Error>>(())
243    }
244    .await;
245
246    if let Err(err) = scenario {
247        passed = false;
248        detail = err.to_string();
249    }
250
251    let cleanup_ok = cleanup_run(&client, &run_id).await;
252    if !cleanup_ok {
253        passed = false;
254        detail = format!("{detail} | cleanup failures");
255    }
256
257    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
258
259    if passed { Ok(()) } else { Err(boxed_error(detail)) }
260}
Source

pub async fn forget(&self, options: ForgetOptions) -> Result<Value>

Examples found in repository?
examples/helper_all_helpers.rs (line 171)
16async fn main() -> Result<(), Box<dyn Error>> {
17    let name = "helper_all_helpers";
18    let started = Instant::now();
19    let client = create_client().await?;
20    let run_id = new_run_id("helper_all_helpers");
21    client.set_run_id(Some(run_id.clone()));
22    client.set_transport(TransportMode::Http);
23
24    let mut passed = true;
25    let mut detail = "validated all helper flows".to_string();
26    let mut metrics = json!({});
27
28    let scenario = async {
29        let mut remember = RememberOptions::new("Policy limit is 5000 and claimant city is Leeds.");
30        remember.run_id = Some(run_id.clone());
31        remember.agent_id = Some("planner".to_string());
32        remember.intent = Some("fact".to_string());
33        remember.metadata = Some(json!({"suite": "all-helpers", "family": "claims"}));
34        remember.importance = Some("high".to_string());
35        let remember_response = client.remember(remember).await?;
36
37        let mut lesson = RememberOptions::new("If city is missing from the latest step, check stored claim facts before escalating.");
38        lesson.run_id = Some(run_id.clone());
39        lesson.agent_id = Some("planner".to_string());
40        lesson.intent = Some("lesson".to_string());
41        lesson.lesson_type = Some("success".to_string());
42        lesson.lesson_scope = Some("session".to_string());
43        lesson.lesson_importance = Some("high".to_string());
44        let lesson_response = client.remember(lesson).await?;
45
46        let mut recall = RecallOptions::new("What is the policy limit?");
47        recall.run_id = Some(run_id.clone());
48        recall.agent_id = Some("planner".to_string());
49        recall.limit = 5;
50        let recall_response = client.recall(recall).await?;
51
52        let mut context = GetContextOptions::default();
53        context.run_id = Some(run_id.clone());
54        context.query = Some("Prepare a short adjuster summary".to_string());
55        context.agent_id = Some("planner".to_string());
56        context.limit = Some(6);
57        context.max_token_budget = Some(700);
58        let context_response = client.get_context(context).await?;
59
60        let mut health = MemoryHealthOptions::default();
61        health.run_id = Some(run_id.clone());
62        health.limit = 50;
63        let health_response = client.memory_health(health).await?;
64
65        let mut diagnose = DiagnoseOptions::new("policy limit lookup returned empty");
66        diagnose.run_id = Some(run_id.clone());
67        diagnose.error_type = Some("retrieval".to_string());
68        diagnose.limit = 5;
69        let diagnose_response = client.diagnose(diagnose).await?;
70
71        let mut reflect = ReflectOptions::default();
72        reflect.run_id = Some(run_id.clone());
73        let reflect_response = client.reflect(reflect).await?;
74
75        let mut register = RegisterAgentOptions::new("planner");
76        register.run_id = Some(run_id.clone());
77        register.role = "planner".to_string();
78        register.read_scopes = vec!["fact".into(), "lesson".into(), "rule".into(), "archive_block".into(), "handoff".into(), "feedback".into()];
79        register.write_scopes = vec!["fact".into(), "trace".into(), "lesson".into(), "observation".into(), "archive_block".into()];
80        register.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
81        let register_response = client.register_agent(register).await?;
82
83        let mut list_agents = ListAgentsOptions::default();
84        list_agents.run_id = Some(run_id.clone());
85        let agents_response = client.list_agents(list_agents).await?;
86
87        let mut archive = ArchiveOptions::new(
88            "Exact adjuster note: claimant confirmed city is Leeds during triage.",
89            "adjuster_note",
90        );
91        archive.run_id = Some(run_id.clone());
92        archive.agent_id = Some("planner".to_string());
93        archive.origin_agent_id = Some("planner".to_string());
94        archive.source_attempt_id = Some("attempt-1".to_string());
95        archive.source_tool = Some("phone_call".to_string());
96        archive.labels = vec!["claims".to_string(), "triage".to_string()];
97        archive.family = Some("claims-adjustment".to_string());
98        archive.metadata = Some(json!({"case": "all-helpers"}));
99        let archive_response = client.archive(archive).await?;
100        let reference_id = archive_response
101            .get("reference_id")
102            .and_then(Value::as_str)
103            .ok_or_else(|| boxed_error(format!("archive reference missing: {archive_response}")))?
104            .to_string();
105
106        let mut dereference = DereferenceOptions::new(reference_id.clone());
107        dereference.run_id = Some(run_id.clone());
108        dereference.agent_id = Some("planner".to_string());
109        let dereference_response = client.dereference(dereference).await?;
110
111        let mut checkpoint = CheckpointOptions::new("Planner captured claim facts before window compaction.");
112        checkpoint.run_id = Some(run_id.clone());
113        checkpoint.label = Some("pre-compaction".to_string());
114        checkpoint.metadata = Some(json!({"stage": "analysis"}));
115        checkpoint.agent_id = Some("planner".to_string());
116        let checkpoint_response = client.checkpoint(checkpoint).await?;
117
118        let lessons_response = client.control.lessons(json!({"run_id": run_id, "limit": 20})).await?;
119        let lesson_id = lessons_response
120            .get("lessons")
121            .and_then(Value::as_array)
122            .and_then(|items| items.iter().find_map(|item| item.get("id").and_then(Value::as_str)))
123            .ok_or_else(|| boxed_error(format!("expected lesson id for outcome flow: {lessons_response}")))?
124            .to_string();
125
126        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
127        outcome.run_id = Some(run_id.clone());
128        outcome.signal = 0.75;
129        outcome.rationale = "Planner reused stored claim fact and resolved the missing-city branch.".to_string();
130        outcome.agent_id = Some("planner".to_string());
131        let outcome_response = client.record_outcome(outcome).await?;
132
133        let mut strategies = SurfaceStrategiesOptions::default();
134        strategies.run_id = Some(run_id.clone());
135        strategies.lesson_types = vec!["success".to_string(), "rule".to_string()];
136        strategies.max_strategies = 5;
137        let strategies_response = client.surface_strategies(strategies).await?;
138
139        let mut handoff = HandoffOptions::new(
140            "claim-1",
141            "planner",
142            "reviewer",
143            "Review whether the stored claimant city is sufficient for routing.",
144        );
145        handoff.run_id = Some(run_id.clone());
146        handoff.requested_action = "review".to_string();
147        handoff.metadata = Some(json!({"team": "claims"}));
148        let handoff_response = client.handoff(handoff).await?;
149        let handoff_id = handoff_response
150            .get("handoff_id")
151            .and_then(Value::as_str)
152            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
153            .to_string();
154
155        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
156        feedback.run_id = Some(run_id.clone());
157        feedback.comments = "Stored fact is sufficient; proceed without escalation.".to_string();
158        feedback.from_agent_id = Some("reviewer".to_string());
159        feedback.metadata = Some(json!({"team": "claims"}));
160        let feedback_response = client.feedback(feedback).await?;
161
162        let scratch_run = format!("{run_id}_forget");
163        let mut scratch = RememberOptions::new("Scratch run for forget helper coverage.");
164        scratch.run_id = Some(scratch_run.clone());
165        scratch.agent_id = Some("planner".to_string());
166        scratch.intent = Some("fact".to_string());
167        scratch.metadata = Some(json!({"suite": "all-helpers", "temporary": true}));
168        let scratch_response = client.remember(scratch).await?;
169
170        let forget_response = client
171            .forget(ForgetOptions::for_run(scratch_run.clone()))
172            .await?;
173
174        let mut forgotten = RecallOptions::new("What temporary scratch fact exists?");
175        forgotten.run_id = Some(scratch_run.clone());
176        forgotten.limit = 3;
177        let forgotten_response = client.recall(forgotten).await?;
178
179        require(remember_response.get("job_id").is_some() || remember_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("remember failed: {remember_response}"))?;
180        require(lesson_response.get("job_id").is_some() || lesson_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("lesson remember failed: {lesson_response}"))?;
181        require(recall_response.get("final_answer").is_some() || recall_response.get("evidence").is_some(), format!("recall failed: {recall_response}"))?;
182        require(context_response.get("sources").and_then(Value::as_array).is_some(), format!("context malformed: {context_response}"))?;
183        require(health_response.get("entry_counts").and_then(Value::as_object).is_some(), format!("memory_health malformed: {health_response}"))?;
184        require(diagnose_response.get("failure_lessons").and_then(Value::as_array).is_some(), format!("diagnose malformed: {diagnose_response}"))?;
185        require(reflect_response.get("lessons").and_then(Value::as_array).is_some(), format!("reflect malformed: {reflect_response}"))?;
186        require(register_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("register_agent failed: {register_response}"))?;
187        require(agents_response.get("agents").and_then(Value::as_array).map(|items| !items.is_empty()).unwrap_or(false), format!("list_agents failed: {agents_response}"))?;
188        require(archive_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("archive failed: {archive_response}"))?;
189        require(dereference_response.get("found").and_then(Value::as_bool).unwrap_or(false), format!("dereference failed: {dereference_response}"))?;
190        require(checkpoint_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
191        require(outcome_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("record_outcome failed: {outcome_response}"))?;
192        require(strategies_response.get("strategies").and_then(Value::as_array).is_some(), format!("surface_strategies malformed: {strategies_response}"))?;
193        require(handoff_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
194        require(feedback_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
195        require(scratch_response.get("job_id").is_some() || scratch_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("scratch remember failed: {scratch_response}"))?;
196        require(forget_response.get("success").and_then(Value::as_bool).unwrap_or(true), format!("forget failed: {forget_response}"))?;
197        let scratch_fact_visible = forgotten_response
198            .get("evidence")
199            .and_then(Value::as_array)
200            .map(|items| {
201                items.iter().any(|item| {
202                    item.get("run_id").and_then(Value::as_str) == Some(scratch_run.as_str())
203                        || item
204                            .get("content")
205                            .and_then(Value::as_str)
206                            .map(|content| {
207                                content
208                                    .to_ascii_lowercase()
209                                    .contains("scratch run for forget helper coverage")
210                            })
211                            .unwrap_or(false)
212                })
213            })
214            .unwrap_or(false);
215        require(!scratch_fact_visible, format!("scratch fact should be forgotten even if same-user lessons still surface: {forgotten_response}"))?;
216
217        let strategy_count = strategies_response
218            .get("strategies")
219            .and_then(Value::as_array)
220            .map(|items| items.len())
221            .unwrap_or(0);
222        let agent_count = agents_response
223            .get("agents")
224            .and_then(Value::as_array)
225            .map(|items| items.len())
226            .unwrap_or(0);
227        let lesson_count = lessons_response
228            .get("lessons")
229            .and_then(Value::as_array)
230            .map(|items| items.len())
231            .unwrap_or(0);
232
233        metrics = json!({
234            "run_id": run_id,
235            "agent_count": agent_count,
236            "strategy_count": strategy_count,
237            "reference_id": reference_id,
238            "lesson_count": lesson_count,
239            "forgotten_run": scratch_run,
240        });
241
242        Ok::<(), Box<dyn Error>>(())
243    }
244    .await;
245
246    if let Err(err) = scenario {
247        passed = false;
248        detail = err.to_string();
249    }
250
251    let cleanup_ok = cleanup_run(&client, &run_id).await;
252    if !cleanup_ok {
253        passed = false;
254        detail = format!("{detail} | cleanup failures");
255    }
256
257    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
258
259    if passed { Ok(()) } else { Err(boxed_error(detail)) }
260}
Source

pub async fn checkpoint(&self, options: CheckpointOptions) -> Result<Value>

Examples found in repository?
examples/helper_mas_learning_loop.rs (line 53)
14async fn main() -> Result<(), Box<dyn Error>> {
15    let name = "helper_mas_learning_loop";
16    let started = Instant::now();
17    let client = create_client().await?;
18    let run_id = new_run_id("helper_mas_learning_loop");
19    client.set_run_id(Some(run_id.clone()));
20    client.set_transport(TransportMode::Http);
21
22    let mut passed = true;
23    let mut detail = "validated helper MAS checkpoint/outcome/strategies flow".to_string();
24    let mut metrics = json!({});
25
26    let scenario = async {
27        let mut register = RegisterAgentOptions::new("planner");
28        register.run_id = Some(run_id.clone());
29        register.role = "planner".to_string();
30        register.read_scopes = vec!["rule".to_string(), "lesson".to_string(), "fact".to_string()];
31        register.write_scopes = vec!["lesson".to_string(), "trace".to_string()];
32        register.shared_memory_lanes = vec!["knowledge".to_string(), "history".to_string()];
33        client.register_agent(register).await?;
34
35        let mut remember = RememberOptions::new(
36            "If a retry succeeds after token signer rotation, record it as a reusable recovery pattern.",
37        );
38        remember.run_id = Some(run_id.clone());
39        remember.agent_id = Some("planner".to_string());
40        remember.intent = Some("lesson".to_string());
41        remember.lesson_type = Some("success".to_string());
42        remember.lesson_scope = Some("session".to_string());
43        remember.lesson_importance = Some("high".to_string());
44        client.remember(remember).await?;
45
46        let mut checkpoint = CheckpointOptions::new(
47            "Planner isolated the recovery path to token signer rotation.",
48        );
49        checkpoint.run_id = Some(run_id.clone());
50        checkpoint.label = Some("pre-compaction-1".to_string());
51        checkpoint.metadata = Some(json!({ "stage": "analysis" }));
52        checkpoint.agent_id = Some("planner".to_string());
53        let checkpoint_response = client.checkpoint(checkpoint).await?;
54
55        let mut list_agents = ListAgentsOptions::default();
56        list_agents.run_id = Some(run_id.clone());
57        let agents = client.list_agents(list_agents).await?;
58
59        let lessons = client.control.lessons(json!({ "run_id": run_id, "limit": 10 })).await?;
60        let lesson_id = lessons
61            .get("lessons")
62            .and_then(|value| value.as_array())
63            .and_then(|items| items.first())
64            .and_then(|item| item.get("id"))
65            .and_then(|value| value.as_str())
66            .ok_or_else(|| boxed_error(format!("expected at least one lesson to record outcome against: {lessons}")))?
67            .to_string();
68
69        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
70        outcome.run_id = Some(run_id.clone());
71        outcome.signal = 0.75;
72        outcome.rationale = "Recovery succeeded after following the stored lesson.".to_string();
73        outcome.agent_id = Some("planner".to_string());
74        let outcome_response = client.record_outcome(outcome).await?;
75
76        let mut strategies = SurfaceStrategiesOptions::default();
77        strategies.run_id = Some(run_id.clone());
78        strategies.lesson_types = vec!["success".to_string(), "failure".to_string()];
79        strategies.max_strategies = 5;
80        let strategy_response = client.surface_strategies(strategies).await?;
81
82        require(
83            checkpoint_response
84                .get("success")
85                .and_then(|value| value.as_bool())
86                .unwrap_or(false),
87            format!("checkpoint failed: {checkpoint_response}"),
88        )?;
89        let agent_count = agents
90            .get("agents")
91            .and_then(|value| value.as_array())
92            .map(|items| items.len())
93            .unwrap_or(0);
94        require(agent_count == 1, format!("agent registration missing: {agents}"))?;
95        require(
96            outcome_response
97                .get("success")
98                .and_then(|value| value.as_bool())
99                .unwrap_or(false),
100            format!("record_outcome failed: {outcome_response}"),
101        )?;
102        let strategy_count = strategy_response
103            .get("strategies")
104            .and_then(|value| value.as_array())
105            .map(|items| items.len())
106            .unwrap_or(0);
107
108        metrics = json!({
109            "run_id": run_id,
110            "checkpoint_id": checkpoint_response.get("checkpoint_id").cloned().unwrap_or(serde_json::Value::Null),
111            "agent_count": agent_count,
112            "strategy_count": strategy_count,
113        });
114
115        Ok::<(), Box<dyn Error>>(())
116    }
117    .await;
118
119    if let Err(err) = scenario {
120        passed = false;
121        detail = err.to_string();
122    }
123
124    let cleanup_ok = cleanup_run(&client, &run_id).await;
125    if !cleanup_ok {
126        passed = false;
127        detail = format!("{detail} | cleanup failures");
128    }
129
130    print_summary(
131        name,
132        passed,
133        &detail,
134        &metrics,
135        started.elapsed().as_secs_f64(),
136        cleanup_ok,
137    );
138
139    if passed {
140        Ok(())
141    } else {
142        Err(boxed_error(detail))
143    }
144}
More examples
Hide additional examples
examples/public/03_checkpoint_reflect_outcome.rs (line 53)
14async fn main() -> Result<(), Box<dyn Error>> {
15    let name = "public_03_checkpoint_reflect_outcome";
16    let started = Instant::now();
17    let client = create_client().await?;
18    let run_id = new_run_id("public_03_checkpoint_reflect_outcome");
19    client.set_run_id(Some(run_id.clone()));
20    client.set_transport(TransportMode::Http);
21
22    let mut passed = true;
23    let mut detail = "validated helper MAS checkpoint/outcome/strategies flow".to_string();
24    let mut metrics = json!({});
25
26    let scenario = async {
27        let mut register = RegisterAgentOptions::new("planner");
28        register.run_id = Some(run_id.clone());
29        register.role = "planner".to_string();
30        register.read_scopes = vec!["rule".to_string(), "lesson".to_string(), "fact".to_string()];
31        register.write_scopes = vec!["lesson".to_string(), "trace".to_string()];
32        register.shared_memory_lanes = vec!["knowledge".to_string(), "history".to_string()];
33        client.register_agent(register).await?;
34
35        let mut remember = RememberOptions::new(
36            "If a retry succeeds after token signer rotation, record it as a reusable recovery pattern.",
37        );
38        remember.run_id = Some(run_id.clone());
39        remember.agent_id = Some("planner".to_string());
40        remember.intent = Some("lesson".to_string());
41        remember.lesson_type = Some("success".to_string());
42        remember.lesson_scope = Some("session".to_string());
43        remember.lesson_importance = Some("high".to_string());
44        client.remember(remember).await?;
45
46        let mut checkpoint = CheckpointOptions::new(
47            "Planner isolated the recovery path to token signer rotation.",
48        );
49        checkpoint.run_id = Some(run_id.clone());
50        checkpoint.label = Some("pre-compaction-1".to_string());
51        checkpoint.metadata = Some(json!({ "stage": "analysis" }));
52        checkpoint.agent_id = Some("planner".to_string());
53        let checkpoint_response = client.checkpoint(checkpoint).await?;
54
55        let mut list_agents = ListAgentsOptions::default();
56        list_agents.run_id = Some(run_id.clone());
57        let agents = client.list_agents(list_agents).await?;
58
59        let lessons = client.control.lessons(json!({ "run_id": run_id, "limit": 10 })).await?;
60        let lesson_id = lessons
61            .get("lessons")
62            .and_then(|value| value.as_array())
63            .and_then(|items| items.first())
64            .and_then(|item| item.get("id"))
65            .and_then(|value| value.as_str())
66            .ok_or_else(|| boxed_error(format!("expected at least one lesson to record outcome against: {lessons}")))?
67            .to_string();
68
69        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
70        outcome.run_id = Some(run_id.clone());
71        outcome.signal = 0.75;
72        outcome.rationale = "Recovery succeeded after following the stored lesson.".to_string();
73        outcome.agent_id = Some("planner".to_string());
74        let outcome_response = client.record_outcome(outcome).await?;
75
76        let mut strategies = SurfaceStrategiesOptions::default();
77        strategies.run_id = Some(run_id.clone());
78        strategies.lesson_types = vec!["success".to_string(), "failure".to_string()];
79        strategies.max_strategies = 5;
80        let strategy_response = client.surface_strategies(strategies).await?;
81
82        require(
83            checkpoint_response
84                .get("success")
85                .and_then(|value| value.as_bool())
86                .unwrap_or(false),
87            format!("checkpoint failed: {checkpoint_response}"),
88        )?;
89        let agent_count = agents
90            .get("agents")
91            .and_then(|value| value.as_array())
92            .map(|items| items.len())
93            .unwrap_or(0);
94        require(agent_count == 1, format!("agent registration missing: {agents}"))?;
95        require(
96            outcome_response
97                .get("success")
98                .and_then(|value| value.as_bool())
99                .unwrap_or(false),
100            format!("record_outcome failed: {outcome_response}"),
101        )?;
102        let strategy_count = strategy_response
103            .get("strategies")
104            .and_then(|value| value.as_array())
105            .map(|items| items.len())
106            .unwrap_or(0);
107
108        metrics = json!({
109            "run_id": run_id,
110            "checkpoint_id": checkpoint_response.get("checkpoint_id").cloned().unwrap_or(serde_json::Value::Null),
111            "agent_count": agent_count,
112            "strategy_count": strategy_count,
113        });
114
115        Ok::<(), Box<dyn Error>>(())
116    }
117    .await;
118
119    if let Err(err) = scenario {
120        passed = false;
121        detail = err.to_string();
122    }
123
124    let cleanup_ok = cleanup_run(&client, &run_id).await;
125    if !cleanup_ok {
126        passed = false;
127        detail = format!("{detail} | cleanup failures");
128    }
129
130    print_summary(
131        name,
132        passed,
133        &detail,
134        &metrics,
135        started.elapsed().as_secs_f64(),
136        cleanup_ok,
137    );
138
139    if passed {
140        Ok(())
141    } else {
142        Err(boxed_error(detail))
143    }
144}
examples/public/08_multi_agent_claims_or_support_flow.rs (line 61)
11async fn main() -> Result<(), Box<dyn Error>> {
12    let name = "public_08_multi_agent_claims_or_support_flow";
13    let started = Instant::now();
14    let client = create_client().await?;
15    let run_id = new_run_id("public_claims_flow");
16    client.set_run_id(Some(run_id.clone()));
17    client.set_transport(TransportMode::Http);
18
19    let mut passed = true;
20    let mut detail = "validated multi-agent claims/support flow".to_string();
21    let mut metrics = json!({});
22
23    let scenario = async {
24        for (agent_id, role, read_scopes, write_scopes) in [
25            ("intake", "intake", vec!["fact", "archive_block"], vec!["fact", "archive_block", "trace"]),
26            ("coverage", "coverage", vec!["fact", "rule", "archive_block", "handoff", "feedback"], vec!["fact", "trace", "lesson"]),
27            ("reviewer", "reviewer", vec!["fact", "archive_block", "handoff", "feedback", "rule"], vec!["feedback", "rule"]),
28        ] {
29            let mut agent = RegisterAgentOptions::new(agent_id);
30            agent.run_id = Some(run_id.clone());
31            agent.role = role.to_string();
32            agent.read_scopes = read_scopes.into_iter().map(String::from).collect();
33            agent.write_scopes = write_scopes.into_iter().map(String::from).collect();
34            agent.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
35            client.register_agent(agent).await?;
36        }
37
38        let mut fact = RememberOptions::new("Policy P-8842 covers windshield damage with a 250 GBP deductible.");
39        fact.run_id = Some(run_id.clone());
40        fact.agent_id = Some("intake".into());
41        fact.intent = Some("fact".into());
42        fact.metadata = Some(json!({"claim_id": "CLM-8842", "source": "intake-form"}));
43        client.remember(fact).await?;
44
45        let mut archive = ArchiveOptions::new("Exact adjuster note: customer confirmed the damage happened on the motorway and no third party was involved.", "adjuster_note");
46        archive.run_id = Some(run_id.clone());
47        archive.agent_id = Some("intake".into());
48        archive.origin_agent_id = Some("intake".into());
49        archive.source_attempt_id = Some("attempt-1".into());
50        archive.source_tool = Some("claim-review".into());
51        archive.labels = vec!["claims".into(), "coverage".into()];
52        archive.family = Some("windshield".into());
53        let archived = client.archive(archive).await?;
54        let reference_id = archived.get("reference_id").and_then(|v| v.as_str()).ok_or_else(|| boxed_error(format!("archive reference missing: {archived}")))?.to_string();
55
56        let mut checkpoint = CheckpointOptions::new("Coverage verified deductible and adjuster note before escalation.");
57        checkpoint.run_id = Some(run_id.clone());
58        checkpoint.label = Some("pre-review".into());
59        checkpoint.agent_id = Some("coverage".into());
60        checkpoint.metadata = Some(json!({"claim_id": "CLM-8842"}));
61        let checkpoint_response = client.checkpoint(checkpoint).await?;
62
63        let mut handoff = HandoffOptions::new("claim-8842", "coverage", "reviewer", "Review whether the adjuster note is enough to approve the claim.");
64        handoff.run_id = Some(run_id.clone());
65        handoff.requested_action = "review".into();
66        handoff.metadata = Some(json!({"claim_id": "CLM-8842"}));
67        let handoff_response = client.handoff(handoff).await?;
68        let handoff_id = handoff_response.get("handoff_id").and_then(|v| v.as_str()).ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?.to_string();
69
70        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
71        feedback.run_id = Some(run_id.clone());
72        feedback.from_agent_id = Some("reviewer".into());
73        feedback.comments = "Deductible and adjuster note are sufficient for routing.".into();
74        feedback.metadata = Some(json!({"claim_id": "CLM-8842"}));
75        let feedback_response = client.feedback(feedback).await?;
76
77        let mut context_opts = GetContextOptions::default();
78        context_opts.run_id = Some(run_id.clone());
79        context_opts.query = Some("Prepare the final claims routing summary.".into());
80        context_opts.agent_id = Some("coverage".into());
81        context_opts.sections = vec!["archive".into(), "facts".into(), "handoffs".into(), "feedback".into()];
82        context_opts.mode = Some("sections".into());
83        let context = client.get_context(context_opts).await?;
84
85        let mut dereference = DereferenceOptions::new(reference_id.clone());
86        dereference.run_id = Some(run_id.clone());
87        dereference.agent_id = Some("coverage".into());
88        let exact = client.dereference(dereference).await?;
89
90        let mut recall = RecallOptions::new("What deductible applies and what did the adjuster confirm?");
91        recall.run_id = Some(run_id.clone());
92        recall.agent_id = Some("coverage".into());
93        recall.entry_types = vec!["fact".into(), "archive_block".into(), "feedback".into()];
94        let recall_response = client.recall(recall).await?;
95
96        require(checkpoint_response.get("success").and_then(|v| v.as_bool()).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
97        require(handoff_response.get("success").and_then(|v| v.as_bool()).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
98        require(feedback_response.get("success").and_then(|v| v.as_bool()).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
99        require(exact.get("found").and_then(|v| v.as_bool()).unwrap_or(false), format!("dereference failed: {exact}"))?;
100        let context_text = context.get("context_block").and_then(|v| v.as_str()).unwrap_or("").to_lowercase();
101        let recall_text = recall_response.get("final_answer").and_then(|v| v.as_str()).unwrap_or("").to_lowercase();
102        let has_archive_source = context
103            .get("sources")
104            .and_then(|v| v.as_array())
105            .map(|sources| {
106                sources.iter().any(|source| {
107                    source
108                        .get("entry_type")
109                        .and_then(|v| v.as_str())
110                        == Some("archive_block")
111                })
112            })
113            .unwrap_or(false);
114        let exact_refs_surfaced = context
115            .get("exact_references_surfaced")
116            .and_then(|v| v.as_u64())
117            .unwrap_or(0);
118        require(
119            context_text.contains("adjuster note")
120                || context_text.contains("motorway")
121                || has_archive_source
122                || exact_refs_surfaced > 0,
123            format!("expected explicit or telemetry-backed exact reuse in context: {context}"),
124        )?;
125        require(recall_text.contains("250") && (recall_text.contains("motorway") || recall_text.contains("third party")), format!("expected recall to include fact + archive content: {recall_response}"))?;
126
127        metrics = json!({
128            "run_id": run_id,
129            "handoff_id": handoff_id,
130            "reference_id": reference_id,
131            "feedback_id": feedback_response.get("feedback_id").cloned().unwrap_or(serde_json::Value::Null),
132        });
133        Ok::<(), Box<dyn Error>>(())
134    }
135    .await;
136
137    if let Err(err) = scenario {
138        passed = false;
139        detail = err.to_string();
140    }
141
142    let cleanup_ok = cleanup_run(&client, &run_id).await;
143    if !cleanup_ok {
144        passed = false;
145        detail = format!("{detail} | cleanup failures");
146    }
147
148    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
149    if passed { Ok(()) } else { Err(boxed_error(detail)) }
150}
examples/public/10_full_learning_loop_smoke.rs (line 128)
16async fn main() -> Result<(), Box<dyn Error>> {
17    let name = "public_10_full_learning_loop_smoke";
18    let started = Instant::now();
19    let client = create_client().await?;
20    let run_id = new_run_id("public_10_full_learning_loop_smoke");
21    client.set_run_id(Some(run_id.clone()));
22    client.set_transport(TransportMode::Http);
23
24    let mut passed = true;
25    let mut detail = "validated all helper flows".to_string();
26    let mut metrics = json!({});
27
28    let scenario = async {
29        let mut remember = RememberOptions::new("Policy limit is 5000 and claimant city is Leeds.");
30        remember.run_id = Some(run_id.clone());
31        remember.agent_id = Some("planner".to_string());
32        remember.intent = Some("fact".to_string());
33        remember.metadata = Some(json!({"suite": "all-helpers", "family": "claims"}));
34        remember.importance = Some("high".to_string());
35        remember.occurrence_time = Some(std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as i64 - 86400);
36        let remember_response = client.remember(remember).await?;
37
38        let mut lesson = RememberOptions::new("If city is missing from the latest step, check stored claim facts before escalating.");
39        lesson.run_id = Some(run_id.clone());
40        lesson.agent_id = Some("planner".to_string());
41        lesson.intent = Some("lesson".to_string());
42        lesson.lesson_type = Some("success".to_string());
43        lesson.lesson_scope = Some("session".to_string());
44        lesson.lesson_importance = Some("high".to_string());
45        let lesson_response = client.remember(lesson).await?;
46
47        let mut mental_model = RememberOptions::new(
48            "Claims case overview: Policy limit 5000 GBP, claimant city Leeds, \
49             missing-city branch resolved via stored claim facts. Lesson: check stored facts before escalating.",
50        );
51        mental_model.run_id = Some(run_id.clone());
52        mental_model.agent_id = Some("planner".to_string());
53        mental_model.intent = Some("mental_model".to_string());
54        mental_model.importance = Some("critical".to_string());
55        mental_model.metadata = Some(json!({"suite": "all-helpers", "entity": "claims-case", "consolidated": true}));
56        let mental_model_response = client.remember(mental_model).await?;
57
58        let mut recall = RecallOptions::new("What is the policy limit?");
59        recall.run_id = Some(run_id.clone());
60        recall.agent_id = Some("planner".to_string());
61        recall.limit = 5;
62        let recall_response = client.recall(recall).await?;
63
64        let mut context = GetContextOptions::default();
65        context.run_id = Some(run_id.clone());
66        context.query = Some("Prepare a short adjuster summary".to_string());
67        context.agent_id = Some("planner".to_string());
68        context.limit = Some(6);
69        context.max_token_budget = Some(700);
70        let context_response = client.get_context(context).await?;
71
72        let mut health = MemoryHealthOptions::default();
73        health.run_id = Some(run_id.clone());
74        health.limit = 50;
75        let health_response = client.memory_health(health).await?;
76
77        let mut diagnose = DiagnoseOptions::new("policy limit lookup returned empty");
78        diagnose.run_id = Some(run_id.clone());
79        diagnose.error_type = Some("retrieval".to_string());
80        diagnose.limit = 5;
81        let diagnose_response = client.diagnose(diagnose).await?;
82
83        let mut reflect = ReflectOptions::default();
84        reflect.run_id = Some(run_id.clone());
85        let reflect_response = client.reflect(reflect).await?;
86
87        let mut register = RegisterAgentOptions::new("planner");
88        register.run_id = Some(run_id.clone());
89        register.role = "planner".to_string();
90        register.read_scopes = vec!["fact".into(), "lesson".into(), "rule".into(), "mental_model".into(), "archive_block".into(), "handoff".into(), "feedback".into()];
91        register.write_scopes = vec!["fact".into(), "trace".into(), "lesson".into(), "observation".into(), "archive_block".into()];
92        register.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
93        let register_response = client.register_agent(register).await?;
94
95        let mut list_agents = ListAgentsOptions::default();
96        list_agents.run_id = Some(run_id.clone());
97        let agents_response = client.list_agents(list_agents).await?;
98
99        let mut archive = ArchiveOptions::new(
100            "Exact adjuster note: claimant confirmed city is Leeds during triage.",
101            "adjuster_note",
102        );
103        archive.run_id = Some(run_id.clone());
104        archive.agent_id = Some("planner".to_string());
105        archive.origin_agent_id = Some("planner".to_string());
106        archive.source_attempt_id = Some("attempt-1".to_string());
107        archive.source_tool = Some("phone_call".to_string());
108        archive.labels = vec!["claims".to_string(), "triage".to_string()];
109        archive.family = Some("claims-adjustment".to_string());
110        archive.metadata = Some(json!({"case": "all-helpers"}));
111        let archive_response = client.archive(archive).await?;
112        let reference_id = archive_response
113            .get("reference_id")
114            .and_then(Value::as_str)
115            .ok_or_else(|| boxed_error(format!("archive reference missing: {archive_response}")))?
116            .to_string();
117
118        let mut dereference = DereferenceOptions::new(reference_id.clone());
119        dereference.run_id = Some(run_id.clone());
120        dereference.agent_id = Some("planner".to_string());
121        let dereference_response = client.dereference(dereference).await?;
122
123        let mut checkpoint = CheckpointOptions::new("Planner captured claim facts before window compaction.");
124        checkpoint.run_id = Some(run_id.clone());
125        checkpoint.label = Some("pre-compaction".to_string());
126        checkpoint.metadata = Some(json!({"stage": "analysis"}));
127        checkpoint.agent_id = Some("planner".to_string());
128        let checkpoint_response = client.checkpoint(checkpoint).await?;
129
130        let lessons_response = client.control.lessons(json!({"run_id": run_id, "limit": 20})).await?;
131        let lesson_id = lessons_response
132            .get("lessons")
133            .and_then(Value::as_array)
134            .and_then(|items| items.iter().find_map(|item| item.get("id").and_then(Value::as_str)))
135            .ok_or_else(|| boxed_error(format!("expected lesson id for outcome flow: {lessons_response}")))?
136            .to_string();
137
138        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
139        outcome.run_id = Some(run_id.clone());
140        outcome.signal = 0.75;
141        outcome.rationale = "Planner reused stored claim fact and resolved the missing-city branch.".to_string();
142        outcome.agent_id = Some("planner".to_string());
143        let outcome_response = client.record_outcome(outcome).await?;
144
145        let mut strategies = SurfaceStrategiesOptions::default();
146        strategies.run_id = Some(run_id.clone());
147        strategies.lesson_types = vec!["success".to_string(), "rule".to_string()];
148        strategies.max_strategies = 5;
149        let strategies_response = client.surface_strategies(strategies).await?;
150
151        let mut handoff = HandoffOptions::new(
152            "claim-1",
153            "planner",
154            "reviewer",
155            "Review whether the stored claimant city is sufficient for routing.",
156        );
157        handoff.run_id = Some(run_id.clone());
158        handoff.requested_action = "review".to_string();
159        handoff.metadata = Some(json!({"team": "claims"}));
160        let handoff_response = client.handoff(handoff).await?;
161        let handoff_id = handoff_response
162            .get("handoff_id")
163            .and_then(Value::as_str)
164            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
165            .to_string();
166
167        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
168        feedback.run_id = Some(run_id.clone());
169        feedback.comments = "Stored fact is sufficient; proceed without escalation.".to_string();
170        feedback.from_agent_id = Some("reviewer".to_string());
171        feedback.metadata = Some(json!({"team": "claims"}));
172        let feedback_response = client.feedback(feedback).await?;
173
174        require(remember_response.get("job_id").is_some() || remember_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("remember failed: {remember_response}"))?;
175        require(mental_model_response.get("job_id").is_some() || mental_model_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("mental_model remember failed: {mental_model_response}"))?;
176        require(lesson_response.get("job_id").is_some() || lesson_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("lesson remember failed: {lesson_response}"))?;
177        require(recall_response.get("final_answer").is_some() || recall_response.get("evidence").is_some(), format!("recall failed: {recall_response}"))?;
178        require(context_response.get("sources").and_then(Value::as_array).is_some(), format!("context malformed: {context_response}"))?;
179        require(health_response.get("entry_counts").and_then(Value::as_object).is_some(), format!("memory_health malformed: {health_response}"))?;
180        require(diagnose_response.get("failure_lessons").and_then(Value::as_array).is_some(), format!("diagnose malformed: {diagnose_response}"))?;
181        require(reflect_response.get("lessons").and_then(Value::as_array).is_some(), format!("reflect malformed: {reflect_response}"))?;
182        require(register_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("register_agent failed: {register_response}"))?;
183        require(agents_response.get("agents").and_then(Value::as_array).map(|items| !items.is_empty()).unwrap_or(false), format!("list_agents failed: {agents_response}"))?;
184        require(archive_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("archive failed: {archive_response}"))?;
185        require(dereference_response.get("found").and_then(Value::as_bool).unwrap_or(false), format!("dereference failed: {dereference_response}"))?;
186        require(checkpoint_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
187        require(outcome_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("record_outcome failed: {outcome_response}"))?;
188        require(strategies_response.get("strategies").and_then(Value::as_array).is_some(), format!("surface_strategies malformed: {strategies_response}"))?;
189        require(handoff_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
190        require(feedback_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
191
192        let strategy_count = strategies_response
193            .get("strategies")
194            .and_then(Value::as_array)
195            .map(|items| items.len())
196            .unwrap_or(0);
197        let agent_count = agents_response
198            .get("agents")
199            .and_then(Value::as_array)
200            .map(|items| items.len())
201            .unwrap_or(0);
202        let lesson_count = lessons_response
203            .get("lessons")
204            .and_then(Value::as_array)
205            .map(|items| items.len())
206            .unwrap_or(0);
207
208        metrics = json!({
209            "run_id": run_id,
210            "agent_count": agent_count,
211            "strategy_count": strategy_count,
212            "reference_id": reference_id,
213            "lesson_count": lesson_count,
214        });
215
216        Ok::<(), Box<dyn Error>>(())
217    }
218    .await;
219
220    if let Err(err) = scenario {
221        passed = false;
222        detail = err.to_string();
223    }
224
225    let cleanup_ok = cleanup_run(&client, &run_id).await;
226    if !cleanup_ok {
227        passed = false;
228        detail = format!("{detail} | cleanup failures");
229    }
230
231    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
232
233    if passed { Ok(()) } else { Err(boxed_error(detail)) }
234}
examples/helper_all_helpers.rs (line 116)
16async fn main() -> Result<(), Box<dyn Error>> {
17    let name = "helper_all_helpers";
18    let started = Instant::now();
19    let client = create_client().await?;
20    let run_id = new_run_id("helper_all_helpers");
21    client.set_run_id(Some(run_id.clone()));
22    client.set_transport(TransportMode::Http);
23
24    let mut passed = true;
25    let mut detail = "validated all helper flows".to_string();
26    let mut metrics = json!({});
27
28    let scenario = async {
29        let mut remember = RememberOptions::new("Policy limit is 5000 and claimant city is Leeds.");
30        remember.run_id = Some(run_id.clone());
31        remember.agent_id = Some("planner".to_string());
32        remember.intent = Some("fact".to_string());
33        remember.metadata = Some(json!({"suite": "all-helpers", "family": "claims"}));
34        remember.importance = Some("high".to_string());
35        let remember_response = client.remember(remember).await?;
36
37        let mut lesson = RememberOptions::new("If city is missing from the latest step, check stored claim facts before escalating.");
38        lesson.run_id = Some(run_id.clone());
39        lesson.agent_id = Some("planner".to_string());
40        lesson.intent = Some("lesson".to_string());
41        lesson.lesson_type = Some("success".to_string());
42        lesson.lesson_scope = Some("session".to_string());
43        lesson.lesson_importance = Some("high".to_string());
44        let lesson_response = client.remember(lesson).await?;
45
46        let mut recall = RecallOptions::new("What is the policy limit?");
47        recall.run_id = Some(run_id.clone());
48        recall.agent_id = Some("planner".to_string());
49        recall.limit = 5;
50        let recall_response = client.recall(recall).await?;
51
52        let mut context = GetContextOptions::default();
53        context.run_id = Some(run_id.clone());
54        context.query = Some("Prepare a short adjuster summary".to_string());
55        context.agent_id = Some("planner".to_string());
56        context.limit = Some(6);
57        context.max_token_budget = Some(700);
58        let context_response = client.get_context(context).await?;
59
60        let mut health = MemoryHealthOptions::default();
61        health.run_id = Some(run_id.clone());
62        health.limit = 50;
63        let health_response = client.memory_health(health).await?;
64
65        let mut diagnose = DiagnoseOptions::new("policy limit lookup returned empty");
66        diagnose.run_id = Some(run_id.clone());
67        diagnose.error_type = Some("retrieval".to_string());
68        diagnose.limit = 5;
69        let diagnose_response = client.diagnose(diagnose).await?;
70
71        let mut reflect = ReflectOptions::default();
72        reflect.run_id = Some(run_id.clone());
73        let reflect_response = client.reflect(reflect).await?;
74
75        let mut register = RegisterAgentOptions::new("planner");
76        register.run_id = Some(run_id.clone());
77        register.role = "planner".to_string();
78        register.read_scopes = vec!["fact".into(), "lesson".into(), "rule".into(), "archive_block".into(), "handoff".into(), "feedback".into()];
79        register.write_scopes = vec!["fact".into(), "trace".into(), "lesson".into(), "observation".into(), "archive_block".into()];
80        register.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
81        let register_response = client.register_agent(register).await?;
82
83        let mut list_agents = ListAgentsOptions::default();
84        list_agents.run_id = Some(run_id.clone());
85        let agents_response = client.list_agents(list_agents).await?;
86
87        let mut archive = ArchiveOptions::new(
88            "Exact adjuster note: claimant confirmed city is Leeds during triage.",
89            "adjuster_note",
90        );
91        archive.run_id = Some(run_id.clone());
92        archive.agent_id = Some("planner".to_string());
93        archive.origin_agent_id = Some("planner".to_string());
94        archive.source_attempt_id = Some("attempt-1".to_string());
95        archive.source_tool = Some("phone_call".to_string());
96        archive.labels = vec!["claims".to_string(), "triage".to_string()];
97        archive.family = Some("claims-adjustment".to_string());
98        archive.metadata = Some(json!({"case": "all-helpers"}));
99        let archive_response = client.archive(archive).await?;
100        let reference_id = archive_response
101            .get("reference_id")
102            .and_then(Value::as_str)
103            .ok_or_else(|| boxed_error(format!("archive reference missing: {archive_response}")))?
104            .to_string();
105
106        let mut dereference = DereferenceOptions::new(reference_id.clone());
107        dereference.run_id = Some(run_id.clone());
108        dereference.agent_id = Some("planner".to_string());
109        let dereference_response = client.dereference(dereference).await?;
110
111        let mut checkpoint = CheckpointOptions::new("Planner captured claim facts before window compaction.");
112        checkpoint.run_id = Some(run_id.clone());
113        checkpoint.label = Some("pre-compaction".to_string());
114        checkpoint.metadata = Some(json!({"stage": "analysis"}));
115        checkpoint.agent_id = Some("planner".to_string());
116        let checkpoint_response = client.checkpoint(checkpoint).await?;
117
118        let lessons_response = client.control.lessons(json!({"run_id": run_id, "limit": 20})).await?;
119        let lesson_id = lessons_response
120            .get("lessons")
121            .and_then(Value::as_array)
122            .and_then(|items| items.iter().find_map(|item| item.get("id").and_then(Value::as_str)))
123            .ok_or_else(|| boxed_error(format!("expected lesson id for outcome flow: {lessons_response}")))?
124            .to_string();
125
126        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
127        outcome.run_id = Some(run_id.clone());
128        outcome.signal = 0.75;
129        outcome.rationale = "Planner reused stored claim fact and resolved the missing-city branch.".to_string();
130        outcome.agent_id = Some("planner".to_string());
131        let outcome_response = client.record_outcome(outcome).await?;
132
133        let mut strategies = SurfaceStrategiesOptions::default();
134        strategies.run_id = Some(run_id.clone());
135        strategies.lesson_types = vec!["success".to_string(), "rule".to_string()];
136        strategies.max_strategies = 5;
137        let strategies_response = client.surface_strategies(strategies).await?;
138
139        let mut handoff = HandoffOptions::new(
140            "claim-1",
141            "planner",
142            "reviewer",
143            "Review whether the stored claimant city is sufficient for routing.",
144        );
145        handoff.run_id = Some(run_id.clone());
146        handoff.requested_action = "review".to_string();
147        handoff.metadata = Some(json!({"team": "claims"}));
148        let handoff_response = client.handoff(handoff).await?;
149        let handoff_id = handoff_response
150            .get("handoff_id")
151            .and_then(Value::as_str)
152            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
153            .to_string();
154
155        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
156        feedback.run_id = Some(run_id.clone());
157        feedback.comments = "Stored fact is sufficient; proceed without escalation.".to_string();
158        feedback.from_agent_id = Some("reviewer".to_string());
159        feedback.metadata = Some(json!({"team": "claims"}));
160        let feedback_response = client.feedback(feedback).await?;
161
162        let scratch_run = format!("{run_id}_forget");
163        let mut scratch = RememberOptions::new("Scratch run for forget helper coverage.");
164        scratch.run_id = Some(scratch_run.clone());
165        scratch.agent_id = Some("planner".to_string());
166        scratch.intent = Some("fact".to_string());
167        scratch.metadata = Some(json!({"suite": "all-helpers", "temporary": true}));
168        let scratch_response = client.remember(scratch).await?;
169
170        let forget_response = client
171            .forget(ForgetOptions::for_run(scratch_run.clone()))
172            .await?;
173
174        let mut forgotten = RecallOptions::new("What temporary scratch fact exists?");
175        forgotten.run_id = Some(scratch_run.clone());
176        forgotten.limit = 3;
177        let forgotten_response = client.recall(forgotten).await?;
178
179        require(remember_response.get("job_id").is_some() || remember_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("remember failed: {remember_response}"))?;
180        require(lesson_response.get("job_id").is_some() || lesson_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("lesson remember failed: {lesson_response}"))?;
181        require(recall_response.get("final_answer").is_some() || recall_response.get("evidence").is_some(), format!("recall failed: {recall_response}"))?;
182        require(context_response.get("sources").and_then(Value::as_array).is_some(), format!("context malformed: {context_response}"))?;
183        require(health_response.get("entry_counts").and_then(Value::as_object).is_some(), format!("memory_health malformed: {health_response}"))?;
184        require(diagnose_response.get("failure_lessons").and_then(Value::as_array).is_some(), format!("diagnose malformed: {diagnose_response}"))?;
185        require(reflect_response.get("lessons").and_then(Value::as_array).is_some(), format!("reflect malformed: {reflect_response}"))?;
186        require(register_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("register_agent failed: {register_response}"))?;
187        require(agents_response.get("agents").and_then(Value::as_array).map(|items| !items.is_empty()).unwrap_or(false), format!("list_agents failed: {agents_response}"))?;
188        require(archive_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("archive failed: {archive_response}"))?;
189        require(dereference_response.get("found").and_then(Value::as_bool).unwrap_or(false), format!("dereference failed: {dereference_response}"))?;
190        require(checkpoint_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
191        require(outcome_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("record_outcome failed: {outcome_response}"))?;
192        require(strategies_response.get("strategies").and_then(Value::as_array).is_some(), format!("surface_strategies malformed: {strategies_response}"))?;
193        require(handoff_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
194        require(feedback_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
195        require(scratch_response.get("job_id").is_some() || scratch_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("scratch remember failed: {scratch_response}"))?;
196        require(forget_response.get("success").and_then(Value::as_bool).unwrap_or(true), format!("forget failed: {forget_response}"))?;
197        let scratch_fact_visible = forgotten_response
198            .get("evidence")
199            .and_then(Value::as_array)
200            .map(|items| {
201                items.iter().any(|item| {
202                    item.get("run_id").and_then(Value::as_str) == Some(scratch_run.as_str())
203                        || item
204                            .get("content")
205                            .and_then(Value::as_str)
206                            .map(|content| {
207                                content
208                                    .to_ascii_lowercase()
209                                    .contains("scratch run for forget helper coverage")
210                            })
211                            .unwrap_or(false)
212                })
213            })
214            .unwrap_or(false);
215        require(!scratch_fact_visible, format!("scratch fact should be forgotten even if same-user lessons still surface: {forgotten_response}"))?;
216
217        let strategy_count = strategies_response
218            .get("strategies")
219            .and_then(Value::as_array)
220            .map(|items| items.len())
221            .unwrap_or(0);
222        let agent_count = agents_response
223            .get("agents")
224            .and_then(Value::as_array)
225            .map(|items| items.len())
226            .unwrap_or(0);
227        let lesson_count = lessons_response
228            .get("lessons")
229            .and_then(Value::as_array)
230            .map(|items| items.len())
231            .unwrap_or(0);
232
233        metrics = json!({
234            "run_id": run_id,
235            "agent_count": agent_count,
236            "strategy_count": strategy_count,
237            "reference_id": reference_id,
238            "lesson_count": lesson_count,
239            "forgotten_run": scratch_run,
240        });
241
242        Ok::<(), Box<dyn Error>>(())
243    }
244    .await;
245
246    if let Err(err) = scenario {
247        passed = false;
248        detail = err.to_string();
249    }
250
251    let cleanup_ok = cleanup_run(&client, &run_id).await;
252    if !cleanup_ok {
253        passed = false;
254        detail = format!("{detail} | cleanup failures");
255    }
256
257    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
258
259    if passed { Ok(()) } else { Err(boxed_error(detail)) }
260}
Source

pub async fn register_agent( &self, options: RegisterAgentOptions, ) -> Result<Value>

Examples found in repository?
examples/helper_handoff_feedback.rs (line 29)
13async fn main() -> Result<(), Box<dyn Error>> {
14    let name = "helper_handoff_feedback";
15    let started = Instant::now();
16    let client = create_client().await?;
17    let run_id = new_run_id("helper_handoff_feedback");
18    client.set_run_id(Some(run_id.clone()));
19    client.set_transport(TransportMode::Http);
20
21    let mut passed = true;
22    let mut detail = "validated helper handoff + feedback flow".to_string();
23    let mut metrics = json!({});
24
25    let scenario = async {
26        let mut planner = RegisterAgentOptions::new("planner");
27        planner.run_id = Some(run_id.clone());
28        planner.role = "planner".to_string();
29        client.register_agent(planner).await?;
30
31        let mut reviewer = RegisterAgentOptions::new("reviewer");
32        reviewer.run_id = Some(run_id.clone());
33        reviewer.role = "reviewer".to_string();
34        client.register_agent(reviewer).await?;
35
36        let mut handoff = HandoffOptions::new(
37            "task-1",
38            "planner",
39            "reviewer",
40            "Review the retry policy patch before rollout.",
41        );
42        handoff.run_id = Some(run_id.clone());
43        handoff.requested_action = "review".to_string();
44        handoff.metadata = Some(json!({ "source": "rust-helper-example" }));
45        let handoff_response = client.handoff(handoff).await?;
46        let handoff_id = handoff_response
47            .get("handoff_id")
48            .and_then(|value| value.as_str())
49            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
50            .to_string();
51
52        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
53        feedback.run_id = Some(run_id.clone());
54        feedback.comments = "Patch looks safe for rollout.".to_string();
55        feedback.from_agent_id = Some("reviewer".to_string());
56        feedback.metadata = Some(json!({ "source": "rust-helper-example" }));
57        let feedback_response = client.feedback(feedback).await?;
58
59        let mut context = GetContextOptions::default();
60        context.run_id = Some(run_id.clone());
61        context.query = Some("What coordination artifacts were recorded for this review handoff?".to_string());
62        context.mode = Some("sections".to_string());
63        context.sections = vec!["handoffs".to_string(), "feedback".to_string()];
64        let context_response = client.get_context(context).await?;
65
66        require(
67            handoff_response
68                .get("success")
69                .and_then(|value| value.as_bool())
70                .unwrap_or(false),
71            format!("handoff failed: {handoff_response}"),
72        )?;
73        require(
74            feedback_response
75                .get("success")
76                .and_then(|value| value.as_bool())
77                .unwrap_or(false),
78            format!("feedback failed: {feedback_response}"),
79        )?;
80        let section_count = context_response
81            .get("section_summaries")
82            .and_then(|value| value.as_array())
83            .map(|items| items.len())
84            .unwrap_or(0);
85
86        metrics = json!({
87            "run_id": run_id,
88            "handoff_id": handoff_id,
89            "feedback_id": feedback_response.get("feedback_id").cloned().unwrap_or(serde_json::Value::Null),
90            "section_count": section_count,
91        });
92
93        Ok::<(), Box<dyn Error>>(())
94    }
95    .await;
96
97    if let Err(err) = scenario {
98        passed = false;
99        detail = err.to_string();
100    }
101
102    let cleanup_ok = cleanup_run(&client, &run_id).await;
103    if !cleanup_ok {
104        passed = false;
105        detail = format!("{detail} | cleanup failures");
106    }
107
108    print_summary(
109        name,
110        passed,
111        &detail,
112        &metrics,
113        started.elapsed().as_secs_f64(),
114        cleanup_ok,
115    );
116
117    if passed {
118        Ok(())
119    } else {
120        Err(boxed_error(detail))
121    }
122}
More examples
Hide additional examples
examples/public/06_handoff_feedback.rs (line 29)
13async fn main() -> Result<(), Box<dyn Error>> {
14    let name = "public_06_handoff_feedback";
15    let started = Instant::now();
16    let client = create_client().await?;
17    let run_id = new_run_id("public_06_handoff_feedback");
18    client.set_run_id(Some(run_id.clone()));
19    client.set_transport(TransportMode::Http);
20
21    let mut passed = true;
22    let mut detail = "validated helper handoff + feedback flow".to_string();
23    let mut metrics = json!({});
24
25    let scenario = async {
26        let mut planner = RegisterAgentOptions::new("planner");
27        planner.run_id = Some(run_id.clone());
28        planner.role = "planner".to_string();
29        client.register_agent(planner).await?;
30
31        let mut reviewer = RegisterAgentOptions::new("reviewer");
32        reviewer.run_id = Some(run_id.clone());
33        reviewer.role = "reviewer".to_string();
34        client.register_agent(reviewer).await?;
35
36        let mut handoff = HandoffOptions::new(
37            "task-1",
38            "planner",
39            "reviewer",
40            "Review the retry policy patch before rollout.",
41        );
42        handoff.run_id = Some(run_id.clone());
43        handoff.requested_action = "review".to_string();
44        handoff.metadata = Some(json!({ "source": "rust-helper-example" }));
45        let handoff_response = client.handoff(handoff).await?;
46        let handoff_id = handoff_response
47            .get("handoff_id")
48            .and_then(|value| value.as_str())
49            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
50            .to_string();
51
52        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
53        feedback.run_id = Some(run_id.clone());
54        feedback.comments = "Patch looks safe for rollout.".to_string();
55        feedback.from_agent_id = Some("reviewer".to_string());
56        feedback.metadata = Some(json!({ "source": "rust-helper-example" }));
57        let feedback_response = client.feedback(feedback).await?;
58
59        let mut context = GetContextOptions::default();
60        context.run_id = Some(run_id.clone());
61        context.query = Some("What coordination artifacts were recorded for this review handoff?".to_string());
62        context.mode = Some("sections".to_string());
63        context.sections = vec!["handoffs".to_string(), "feedback".to_string()];
64        let context_response = client.get_context(context).await?;
65
66        require(
67            handoff_response
68                .get("success")
69                .and_then(|value| value.as_bool())
70                .unwrap_or(false),
71            format!("handoff failed: {handoff_response}"),
72        )?;
73        require(
74            feedback_response
75                .get("success")
76                .and_then(|value| value.as_bool())
77                .unwrap_or(false),
78            format!("feedback failed: {feedback_response}"),
79        )?;
80        let section_count = context_response
81            .get("section_summaries")
82            .and_then(|value| value.as_array())
83            .map(|items| items.len())
84            .unwrap_or(0);
85
86        metrics = json!({
87            "run_id": run_id,
88            "handoff_id": handoff_id,
89            "feedback_id": feedback_response.get("feedback_id").cloned().unwrap_or(serde_json::Value::Null),
90            "section_count": section_count,
91        });
92
93        Ok::<(), Box<dyn Error>>(())
94    }
95    .await;
96
97    if let Err(err) = scenario {
98        passed = false;
99        detail = err.to_string();
100    }
101
102    let cleanup_ok = cleanup_run(&client, &run_id).await;
103    if !cleanup_ok {
104        passed = false;
105        detail = format!("{detail} | cleanup failures");
106    }
107
108    print_summary(
109        name,
110        passed,
111        &detail,
112        &metrics,
113        started.elapsed().as_secs_f64(),
114        cleanup_ok,
115    );
116
117    if passed {
118        Ok(())
119    } else {
120        Err(boxed_error(detail))
121    }
122}
examples/helper_mas_learning_loop.rs (line 33)
14async fn main() -> Result<(), Box<dyn Error>> {
15    let name = "helper_mas_learning_loop";
16    let started = Instant::now();
17    let client = create_client().await?;
18    let run_id = new_run_id("helper_mas_learning_loop");
19    client.set_run_id(Some(run_id.clone()));
20    client.set_transport(TransportMode::Http);
21
22    let mut passed = true;
23    let mut detail = "validated helper MAS checkpoint/outcome/strategies flow".to_string();
24    let mut metrics = json!({});
25
26    let scenario = async {
27        let mut register = RegisterAgentOptions::new("planner");
28        register.run_id = Some(run_id.clone());
29        register.role = "planner".to_string();
30        register.read_scopes = vec!["rule".to_string(), "lesson".to_string(), "fact".to_string()];
31        register.write_scopes = vec!["lesson".to_string(), "trace".to_string()];
32        register.shared_memory_lanes = vec!["knowledge".to_string(), "history".to_string()];
33        client.register_agent(register).await?;
34
35        let mut remember = RememberOptions::new(
36            "If a retry succeeds after token signer rotation, record it as a reusable recovery pattern.",
37        );
38        remember.run_id = Some(run_id.clone());
39        remember.agent_id = Some("planner".to_string());
40        remember.intent = Some("lesson".to_string());
41        remember.lesson_type = Some("success".to_string());
42        remember.lesson_scope = Some("session".to_string());
43        remember.lesson_importance = Some("high".to_string());
44        client.remember(remember).await?;
45
46        let mut checkpoint = CheckpointOptions::new(
47            "Planner isolated the recovery path to token signer rotation.",
48        );
49        checkpoint.run_id = Some(run_id.clone());
50        checkpoint.label = Some("pre-compaction-1".to_string());
51        checkpoint.metadata = Some(json!({ "stage": "analysis" }));
52        checkpoint.agent_id = Some("planner".to_string());
53        let checkpoint_response = client.checkpoint(checkpoint).await?;
54
55        let mut list_agents = ListAgentsOptions::default();
56        list_agents.run_id = Some(run_id.clone());
57        let agents = client.list_agents(list_agents).await?;
58
59        let lessons = client.control.lessons(json!({ "run_id": run_id, "limit": 10 })).await?;
60        let lesson_id = lessons
61            .get("lessons")
62            .and_then(|value| value.as_array())
63            .and_then(|items| items.first())
64            .and_then(|item| item.get("id"))
65            .and_then(|value| value.as_str())
66            .ok_or_else(|| boxed_error(format!("expected at least one lesson to record outcome against: {lessons}")))?
67            .to_string();
68
69        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
70        outcome.run_id = Some(run_id.clone());
71        outcome.signal = 0.75;
72        outcome.rationale = "Recovery succeeded after following the stored lesson.".to_string();
73        outcome.agent_id = Some("planner".to_string());
74        let outcome_response = client.record_outcome(outcome).await?;
75
76        let mut strategies = SurfaceStrategiesOptions::default();
77        strategies.run_id = Some(run_id.clone());
78        strategies.lesson_types = vec!["success".to_string(), "failure".to_string()];
79        strategies.max_strategies = 5;
80        let strategy_response = client.surface_strategies(strategies).await?;
81
82        require(
83            checkpoint_response
84                .get("success")
85                .and_then(|value| value.as_bool())
86                .unwrap_or(false),
87            format!("checkpoint failed: {checkpoint_response}"),
88        )?;
89        let agent_count = agents
90            .get("agents")
91            .and_then(|value| value.as_array())
92            .map(|items| items.len())
93            .unwrap_or(0);
94        require(agent_count == 1, format!("agent registration missing: {agents}"))?;
95        require(
96            outcome_response
97                .get("success")
98                .and_then(|value| value.as_bool())
99                .unwrap_or(false),
100            format!("record_outcome failed: {outcome_response}"),
101        )?;
102        let strategy_count = strategy_response
103            .get("strategies")
104            .and_then(|value| value.as_array())
105            .map(|items| items.len())
106            .unwrap_or(0);
107
108        metrics = json!({
109            "run_id": run_id,
110            "checkpoint_id": checkpoint_response.get("checkpoint_id").cloned().unwrap_or(serde_json::Value::Null),
111            "agent_count": agent_count,
112            "strategy_count": strategy_count,
113        });
114
115        Ok::<(), Box<dyn Error>>(())
116    }
117    .await;
118
119    if let Err(err) = scenario {
120        passed = false;
121        detail = err.to_string();
122    }
123
124    let cleanup_ok = cleanup_run(&client, &run_id).await;
125    if !cleanup_ok {
126        passed = false;
127        detail = format!("{detail} | cleanup failures");
128    }
129
130    print_summary(
131        name,
132        passed,
133        &detail,
134        &metrics,
135        started.elapsed().as_secs_f64(),
136        cleanup_ok,
137    );
138
139    if passed {
140        Ok(())
141    } else {
142        Err(boxed_error(detail))
143    }
144}
examples/public/03_checkpoint_reflect_outcome.rs (line 33)
14async fn main() -> Result<(), Box<dyn Error>> {
15    let name = "public_03_checkpoint_reflect_outcome";
16    let started = Instant::now();
17    let client = create_client().await?;
18    let run_id = new_run_id("public_03_checkpoint_reflect_outcome");
19    client.set_run_id(Some(run_id.clone()));
20    client.set_transport(TransportMode::Http);
21
22    let mut passed = true;
23    let mut detail = "validated helper MAS checkpoint/outcome/strategies flow".to_string();
24    let mut metrics = json!({});
25
26    let scenario = async {
27        let mut register = RegisterAgentOptions::new("planner");
28        register.run_id = Some(run_id.clone());
29        register.role = "planner".to_string();
30        register.read_scopes = vec!["rule".to_string(), "lesson".to_string(), "fact".to_string()];
31        register.write_scopes = vec!["lesson".to_string(), "trace".to_string()];
32        register.shared_memory_lanes = vec!["knowledge".to_string(), "history".to_string()];
33        client.register_agent(register).await?;
34
35        let mut remember = RememberOptions::new(
36            "If a retry succeeds after token signer rotation, record it as a reusable recovery pattern.",
37        );
38        remember.run_id = Some(run_id.clone());
39        remember.agent_id = Some("planner".to_string());
40        remember.intent = Some("lesson".to_string());
41        remember.lesson_type = Some("success".to_string());
42        remember.lesson_scope = Some("session".to_string());
43        remember.lesson_importance = Some("high".to_string());
44        client.remember(remember).await?;
45
46        let mut checkpoint = CheckpointOptions::new(
47            "Planner isolated the recovery path to token signer rotation.",
48        );
49        checkpoint.run_id = Some(run_id.clone());
50        checkpoint.label = Some("pre-compaction-1".to_string());
51        checkpoint.metadata = Some(json!({ "stage": "analysis" }));
52        checkpoint.agent_id = Some("planner".to_string());
53        let checkpoint_response = client.checkpoint(checkpoint).await?;
54
55        let mut list_agents = ListAgentsOptions::default();
56        list_agents.run_id = Some(run_id.clone());
57        let agents = client.list_agents(list_agents).await?;
58
59        let lessons = client.control.lessons(json!({ "run_id": run_id, "limit": 10 })).await?;
60        let lesson_id = lessons
61            .get("lessons")
62            .and_then(|value| value.as_array())
63            .and_then(|items| items.first())
64            .and_then(|item| item.get("id"))
65            .and_then(|value| value.as_str())
66            .ok_or_else(|| boxed_error(format!("expected at least one lesson to record outcome against: {lessons}")))?
67            .to_string();
68
69        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
70        outcome.run_id = Some(run_id.clone());
71        outcome.signal = 0.75;
72        outcome.rationale = "Recovery succeeded after following the stored lesson.".to_string();
73        outcome.agent_id = Some("planner".to_string());
74        let outcome_response = client.record_outcome(outcome).await?;
75
76        let mut strategies = SurfaceStrategiesOptions::default();
77        strategies.run_id = Some(run_id.clone());
78        strategies.lesson_types = vec!["success".to_string(), "failure".to_string()];
79        strategies.max_strategies = 5;
80        let strategy_response = client.surface_strategies(strategies).await?;
81
82        require(
83            checkpoint_response
84                .get("success")
85                .and_then(|value| value.as_bool())
86                .unwrap_or(false),
87            format!("checkpoint failed: {checkpoint_response}"),
88        )?;
89        let agent_count = agents
90            .get("agents")
91            .and_then(|value| value.as_array())
92            .map(|items| items.len())
93            .unwrap_or(0);
94        require(agent_count == 1, format!("agent registration missing: {agents}"))?;
95        require(
96            outcome_response
97                .get("success")
98                .and_then(|value| value.as_bool())
99                .unwrap_or(false),
100            format!("record_outcome failed: {outcome_response}"),
101        )?;
102        let strategy_count = strategy_response
103            .get("strategies")
104            .and_then(|value| value.as_array())
105            .map(|items| items.len())
106            .unwrap_or(0);
107
108        metrics = json!({
109            "run_id": run_id,
110            "checkpoint_id": checkpoint_response.get("checkpoint_id").cloned().unwrap_or(serde_json::Value::Null),
111            "agent_count": agent_count,
112            "strategy_count": strategy_count,
113        });
114
115        Ok::<(), Box<dyn Error>>(())
116    }
117    .await;
118
119    if let Err(err) = scenario {
120        passed = false;
121        detail = err.to_string();
122    }
123
124    let cleanup_ok = cleanup_run(&client, &run_id).await;
125    if !cleanup_ok {
126        passed = false;
127        detail = format!("{detail} | cleanup failures");
128    }
129
130    print_summary(
131        name,
132        passed,
133        &detail,
134        &metrics,
135        started.elapsed().as_secs_f64(),
136        cleanup_ok,
137    );
138
139    if passed {
140        Ok(())
141    } else {
142        Err(boxed_error(detail))
143    }
144}
examples/public/05_agent_registration_and_scoped_access.rs (line 30)
11async fn main() -> Result<(), Box<dyn Error>> {
12    let name = "public_05_agent_registration_and_scoped_access";
13    let started = Instant::now();
14    let client = create_client().await?;
15    let run_id = new_run_id("public_agent_scopes");
16    client.set_run_id(Some(run_id.clone()));
17    client.set_transport(TransportMode::Http);
18
19    let mut passed = true;
20    let mut detail = "validated agent registration and scoped access".to_string();
21    let mut metrics = json!({});
22
23    let scenario = async {
24        let mut planner = RegisterAgentOptions::new("planner");
25        planner.run_id = Some(run_id.clone());
26        planner.role = "planner".to_string();
27        planner.read_scopes = vec!["fact".into(), "lesson".into()];
28        planner.write_scopes = vec!["fact".into(), "lesson".into()];
29        planner.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
30        client.register_agent(planner).await?;
31
32        let mut reviewer = RegisterAgentOptions::new("reviewer");
33        reviewer.run_id = Some(run_id.clone());
34        reviewer.role = "reviewer".to_string();
35        reviewer.read_scopes = vec!["rule".into(), "trace".into()];
36        reviewer.write_scopes = vec!["rule".into(), "trace".into()];
37        reviewer.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
38        client.register_agent(reviewer).await?;
39
40        let mut planner_fact = RememberOptions::new("Claim requires police report only when payout exceeds 3000 GBP.");
41        planner_fact.run_id = Some(run_id.clone());
42        planner_fact.agent_id = Some("planner".into());
43        planner_fact.intent = Some("fact".into());
44        planner_fact.metadata = Some(json!({"source": "planner"}));
45        let planner_write = client.remember(planner_fact).await?;
46
47        let mut reviewer_rule = RememberOptions::new("Escalate to compliance if a police report is missing after payout approval.");
48        reviewer_rule.run_id = Some(run_id.clone());
49        reviewer_rule.agent_id = Some("reviewer".into());
50        reviewer_rule.intent = Some("rule".into());
51        reviewer_rule.metadata = Some(json!({"source": "reviewer"}));
52        let reviewer_write = client.remember(reviewer_rule).await?;
53
54        let mut planner_context_opts = GetContextOptions::default();
55        planner_context_opts.run_id = Some(run_id.clone());
56        planner_context_opts.query = Some("What should planner know before triage?".into());
57        planner_context_opts.agent_id = Some("planner".into());
58        planner_context_opts.entry_types = vec!["fact".into(), "lesson".into(), "rule".into()];
59        planner_context_opts.mode = Some("sections".into());
60        planner_context_opts.sections = vec!["facts".into(), "rules".into()];
61        let planner_context = client.get_context(planner_context_opts).await?;
62
63        let mut reviewer_context_opts = GetContextOptions::default();
64        reviewer_context_opts.run_id = Some(run_id.clone());
65        reviewer_context_opts.query = Some("What should reviewer know before approval?".into());
66        reviewer_context_opts.agent_id = Some("reviewer".into());
67        reviewer_context_opts.entry_types = vec!["fact".into(), "lesson".into(), "rule".into(), "trace".into()];
68        reviewer_context_opts.mode = Some("sections".into());
69        reviewer_context_opts.sections = vec!["facts".into(), "rules".into()];
70        let reviewer_context = client.get_context(reviewer_context_opts).await?;
71
72        let mut list_agents = ListAgentsOptions::default();
73        list_agents.run_id = Some(run_id.clone());
74        let agents = client.list_agents(list_agents).await?;
75
76        require(planner_write.get("accepted").and_then(|v| v.as_bool()).unwrap_or(false) || planner_write.get("job_id").is_some(), format!("planner remember failed: {planner_write}"))?;
77        require(reviewer_write.get("accepted").and_then(|v| v.as_bool()).unwrap_or(false) || reviewer_write.get("job_id").is_some(), format!("reviewer remember failed: {reviewer_write}"))?;
78        let agent_count = agents.get("agents").and_then(|v| v.as_array()).map(|items| items.len()).unwrap_or(0);
79        require(agent_count == 2, format!("agent registration failed: {agents}"))?;
80
81        let planner_types: Vec<&str> = planner_context.get("sources").and_then(|v| v.as_array()).into_iter().flatten().filter_map(|source| source.get("entry_type").and_then(|v| v.as_str())).collect();
82        let reviewer_types: Vec<&str> = reviewer_context.get("sources").and_then(|v| v.as_array()).into_iter().flatten().filter_map(|source| source.get("entry_type").and_then(|v| v.as_str())).collect();
83        require(planner_types.iter().any(|t| *t == "fact"), format!("planner should see facts: {planner_context}"))?;
84        require(!planner_types.iter().any(|t| *t == "rule"), format!("planner should not see reviewer rule scope: {planner_context}"))?;
85        require(reviewer_types.iter().any(|t| *t == "rule"), format!("reviewer should see rules: {reviewer_context}"))?;
86
87        metrics = json!({
88            "run_id": run_id,
89            "agent_count": agent_count,
90            "planner_source_types": planner_types,
91            "reviewer_source_types": reviewer_types,
92        });
93        Ok::<(), Box<dyn Error>>(())
94    }
95    .await;
96
97    if let Err(err) = scenario {
98        passed = false;
99        detail = err.to_string();
100    }
101
102    let cleanup_ok = cleanup_run(&client, &run_id).await;
103    if !cleanup_ok {
104        passed = false;
105        detail = format!("{detail} | cleanup failures");
106    }
107
108    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
109    if passed { Ok(()) } else { Err(boxed_error(detail)) }
110}
examples/public/08_multi_agent_claims_or_support_flow.rs (line 35)
11async fn main() -> Result<(), Box<dyn Error>> {
12    let name = "public_08_multi_agent_claims_or_support_flow";
13    let started = Instant::now();
14    let client = create_client().await?;
15    let run_id = new_run_id("public_claims_flow");
16    client.set_run_id(Some(run_id.clone()));
17    client.set_transport(TransportMode::Http);
18
19    let mut passed = true;
20    let mut detail = "validated multi-agent claims/support flow".to_string();
21    let mut metrics = json!({});
22
23    let scenario = async {
24        for (agent_id, role, read_scopes, write_scopes) in [
25            ("intake", "intake", vec!["fact", "archive_block"], vec!["fact", "archive_block", "trace"]),
26            ("coverage", "coverage", vec!["fact", "rule", "archive_block", "handoff", "feedback"], vec!["fact", "trace", "lesson"]),
27            ("reviewer", "reviewer", vec!["fact", "archive_block", "handoff", "feedback", "rule"], vec!["feedback", "rule"]),
28        ] {
29            let mut agent = RegisterAgentOptions::new(agent_id);
30            agent.run_id = Some(run_id.clone());
31            agent.role = role.to_string();
32            agent.read_scopes = read_scopes.into_iter().map(String::from).collect();
33            agent.write_scopes = write_scopes.into_iter().map(String::from).collect();
34            agent.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
35            client.register_agent(agent).await?;
36        }
37
38        let mut fact = RememberOptions::new("Policy P-8842 covers windshield damage with a 250 GBP deductible.");
39        fact.run_id = Some(run_id.clone());
40        fact.agent_id = Some("intake".into());
41        fact.intent = Some("fact".into());
42        fact.metadata = Some(json!({"claim_id": "CLM-8842", "source": "intake-form"}));
43        client.remember(fact).await?;
44
45        let mut archive = ArchiveOptions::new("Exact adjuster note: customer confirmed the damage happened on the motorway and no third party was involved.", "adjuster_note");
46        archive.run_id = Some(run_id.clone());
47        archive.agent_id = Some("intake".into());
48        archive.origin_agent_id = Some("intake".into());
49        archive.source_attempt_id = Some("attempt-1".into());
50        archive.source_tool = Some("claim-review".into());
51        archive.labels = vec!["claims".into(), "coverage".into()];
52        archive.family = Some("windshield".into());
53        let archived = client.archive(archive).await?;
54        let reference_id = archived.get("reference_id").and_then(|v| v.as_str()).ok_or_else(|| boxed_error(format!("archive reference missing: {archived}")))?.to_string();
55
56        let mut checkpoint = CheckpointOptions::new("Coverage verified deductible and adjuster note before escalation.");
57        checkpoint.run_id = Some(run_id.clone());
58        checkpoint.label = Some("pre-review".into());
59        checkpoint.agent_id = Some("coverage".into());
60        checkpoint.metadata = Some(json!({"claim_id": "CLM-8842"}));
61        let checkpoint_response = client.checkpoint(checkpoint).await?;
62
63        let mut handoff = HandoffOptions::new("claim-8842", "coverage", "reviewer", "Review whether the adjuster note is enough to approve the claim.");
64        handoff.run_id = Some(run_id.clone());
65        handoff.requested_action = "review".into();
66        handoff.metadata = Some(json!({"claim_id": "CLM-8842"}));
67        let handoff_response = client.handoff(handoff).await?;
68        let handoff_id = handoff_response.get("handoff_id").and_then(|v| v.as_str()).ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?.to_string();
69
70        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
71        feedback.run_id = Some(run_id.clone());
72        feedback.from_agent_id = Some("reviewer".into());
73        feedback.comments = "Deductible and adjuster note are sufficient for routing.".into();
74        feedback.metadata = Some(json!({"claim_id": "CLM-8842"}));
75        let feedback_response = client.feedback(feedback).await?;
76
77        let mut context_opts = GetContextOptions::default();
78        context_opts.run_id = Some(run_id.clone());
79        context_opts.query = Some("Prepare the final claims routing summary.".into());
80        context_opts.agent_id = Some("coverage".into());
81        context_opts.sections = vec!["archive".into(), "facts".into(), "handoffs".into(), "feedback".into()];
82        context_opts.mode = Some("sections".into());
83        let context = client.get_context(context_opts).await?;
84
85        let mut dereference = DereferenceOptions::new(reference_id.clone());
86        dereference.run_id = Some(run_id.clone());
87        dereference.agent_id = Some("coverage".into());
88        let exact = client.dereference(dereference).await?;
89
90        let mut recall = RecallOptions::new("What deductible applies and what did the adjuster confirm?");
91        recall.run_id = Some(run_id.clone());
92        recall.agent_id = Some("coverage".into());
93        recall.entry_types = vec!["fact".into(), "archive_block".into(), "feedback".into()];
94        let recall_response = client.recall(recall).await?;
95
96        require(checkpoint_response.get("success").and_then(|v| v.as_bool()).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
97        require(handoff_response.get("success").and_then(|v| v.as_bool()).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
98        require(feedback_response.get("success").and_then(|v| v.as_bool()).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
99        require(exact.get("found").and_then(|v| v.as_bool()).unwrap_or(false), format!("dereference failed: {exact}"))?;
100        let context_text = context.get("context_block").and_then(|v| v.as_str()).unwrap_or("").to_lowercase();
101        let recall_text = recall_response.get("final_answer").and_then(|v| v.as_str()).unwrap_or("").to_lowercase();
102        let has_archive_source = context
103            .get("sources")
104            .and_then(|v| v.as_array())
105            .map(|sources| {
106                sources.iter().any(|source| {
107                    source
108                        .get("entry_type")
109                        .and_then(|v| v.as_str())
110                        == Some("archive_block")
111                })
112            })
113            .unwrap_or(false);
114        let exact_refs_surfaced = context
115            .get("exact_references_surfaced")
116            .and_then(|v| v.as_u64())
117            .unwrap_or(0);
118        require(
119            context_text.contains("adjuster note")
120                || context_text.contains("motorway")
121                || has_archive_source
122                || exact_refs_surfaced > 0,
123            format!("expected explicit or telemetry-backed exact reuse in context: {context}"),
124        )?;
125        require(recall_text.contains("250") && (recall_text.contains("motorway") || recall_text.contains("third party")), format!("expected recall to include fact + archive content: {recall_response}"))?;
126
127        metrics = json!({
128            "run_id": run_id,
129            "handoff_id": handoff_id,
130            "reference_id": reference_id,
131            "feedback_id": feedback_response.get("feedback_id").cloned().unwrap_or(serde_json::Value::Null),
132        });
133        Ok::<(), Box<dyn Error>>(())
134    }
135    .await;
136
137    if let Err(err) = scenario {
138        passed = false;
139        detail = err.to_string();
140    }
141
142    let cleanup_ok = cleanup_run(&client, &run_id).await;
143    if !cleanup_ok {
144        passed = false;
145        detail = format!("{detail} | cleanup failures");
146    }
147
148    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
149    if passed { Ok(()) } else { Err(boxed_error(detail)) }
150}
Source

pub async fn list_agents(&self, options: ListAgentsOptions) -> Result<Value>

Examples found in repository?
examples/helper_mas_learning_loop.rs (line 57)
14async fn main() -> Result<(), Box<dyn Error>> {
15    let name = "helper_mas_learning_loop";
16    let started = Instant::now();
17    let client = create_client().await?;
18    let run_id = new_run_id("helper_mas_learning_loop");
19    client.set_run_id(Some(run_id.clone()));
20    client.set_transport(TransportMode::Http);
21
22    let mut passed = true;
23    let mut detail = "validated helper MAS checkpoint/outcome/strategies flow".to_string();
24    let mut metrics = json!({});
25
26    let scenario = async {
27        let mut register = RegisterAgentOptions::new("planner");
28        register.run_id = Some(run_id.clone());
29        register.role = "planner".to_string();
30        register.read_scopes = vec!["rule".to_string(), "lesson".to_string(), "fact".to_string()];
31        register.write_scopes = vec!["lesson".to_string(), "trace".to_string()];
32        register.shared_memory_lanes = vec!["knowledge".to_string(), "history".to_string()];
33        client.register_agent(register).await?;
34
35        let mut remember = RememberOptions::new(
36            "If a retry succeeds after token signer rotation, record it as a reusable recovery pattern.",
37        );
38        remember.run_id = Some(run_id.clone());
39        remember.agent_id = Some("planner".to_string());
40        remember.intent = Some("lesson".to_string());
41        remember.lesson_type = Some("success".to_string());
42        remember.lesson_scope = Some("session".to_string());
43        remember.lesson_importance = Some("high".to_string());
44        client.remember(remember).await?;
45
46        let mut checkpoint = CheckpointOptions::new(
47            "Planner isolated the recovery path to token signer rotation.",
48        );
49        checkpoint.run_id = Some(run_id.clone());
50        checkpoint.label = Some("pre-compaction-1".to_string());
51        checkpoint.metadata = Some(json!({ "stage": "analysis" }));
52        checkpoint.agent_id = Some("planner".to_string());
53        let checkpoint_response = client.checkpoint(checkpoint).await?;
54
55        let mut list_agents = ListAgentsOptions::default();
56        list_agents.run_id = Some(run_id.clone());
57        let agents = client.list_agents(list_agents).await?;
58
59        let lessons = client.control.lessons(json!({ "run_id": run_id, "limit": 10 })).await?;
60        let lesson_id = lessons
61            .get("lessons")
62            .and_then(|value| value.as_array())
63            .and_then(|items| items.first())
64            .and_then(|item| item.get("id"))
65            .and_then(|value| value.as_str())
66            .ok_or_else(|| boxed_error(format!("expected at least one lesson to record outcome against: {lessons}")))?
67            .to_string();
68
69        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
70        outcome.run_id = Some(run_id.clone());
71        outcome.signal = 0.75;
72        outcome.rationale = "Recovery succeeded after following the stored lesson.".to_string();
73        outcome.agent_id = Some("planner".to_string());
74        let outcome_response = client.record_outcome(outcome).await?;
75
76        let mut strategies = SurfaceStrategiesOptions::default();
77        strategies.run_id = Some(run_id.clone());
78        strategies.lesson_types = vec!["success".to_string(), "failure".to_string()];
79        strategies.max_strategies = 5;
80        let strategy_response = client.surface_strategies(strategies).await?;
81
82        require(
83            checkpoint_response
84                .get("success")
85                .and_then(|value| value.as_bool())
86                .unwrap_or(false),
87            format!("checkpoint failed: {checkpoint_response}"),
88        )?;
89        let agent_count = agents
90            .get("agents")
91            .and_then(|value| value.as_array())
92            .map(|items| items.len())
93            .unwrap_or(0);
94        require(agent_count == 1, format!("agent registration missing: {agents}"))?;
95        require(
96            outcome_response
97                .get("success")
98                .and_then(|value| value.as_bool())
99                .unwrap_or(false),
100            format!("record_outcome failed: {outcome_response}"),
101        )?;
102        let strategy_count = strategy_response
103            .get("strategies")
104            .and_then(|value| value.as_array())
105            .map(|items| items.len())
106            .unwrap_or(0);
107
108        metrics = json!({
109            "run_id": run_id,
110            "checkpoint_id": checkpoint_response.get("checkpoint_id").cloned().unwrap_or(serde_json::Value::Null),
111            "agent_count": agent_count,
112            "strategy_count": strategy_count,
113        });
114
115        Ok::<(), Box<dyn Error>>(())
116    }
117    .await;
118
119    if let Err(err) = scenario {
120        passed = false;
121        detail = err.to_string();
122    }
123
124    let cleanup_ok = cleanup_run(&client, &run_id).await;
125    if !cleanup_ok {
126        passed = false;
127        detail = format!("{detail} | cleanup failures");
128    }
129
130    print_summary(
131        name,
132        passed,
133        &detail,
134        &metrics,
135        started.elapsed().as_secs_f64(),
136        cleanup_ok,
137    );
138
139    if passed {
140        Ok(())
141    } else {
142        Err(boxed_error(detail))
143    }
144}
More examples
Hide additional examples
examples/public/03_checkpoint_reflect_outcome.rs (line 57)
14async fn main() -> Result<(), Box<dyn Error>> {
15    let name = "public_03_checkpoint_reflect_outcome";
16    let started = Instant::now();
17    let client = create_client().await?;
18    let run_id = new_run_id("public_03_checkpoint_reflect_outcome");
19    client.set_run_id(Some(run_id.clone()));
20    client.set_transport(TransportMode::Http);
21
22    let mut passed = true;
23    let mut detail = "validated helper MAS checkpoint/outcome/strategies flow".to_string();
24    let mut metrics = json!({});
25
26    let scenario = async {
27        let mut register = RegisterAgentOptions::new("planner");
28        register.run_id = Some(run_id.clone());
29        register.role = "planner".to_string();
30        register.read_scopes = vec!["rule".to_string(), "lesson".to_string(), "fact".to_string()];
31        register.write_scopes = vec!["lesson".to_string(), "trace".to_string()];
32        register.shared_memory_lanes = vec!["knowledge".to_string(), "history".to_string()];
33        client.register_agent(register).await?;
34
35        let mut remember = RememberOptions::new(
36            "If a retry succeeds after token signer rotation, record it as a reusable recovery pattern.",
37        );
38        remember.run_id = Some(run_id.clone());
39        remember.agent_id = Some("planner".to_string());
40        remember.intent = Some("lesson".to_string());
41        remember.lesson_type = Some("success".to_string());
42        remember.lesson_scope = Some("session".to_string());
43        remember.lesson_importance = Some("high".to_string());
44        client.remember(remember).await?;
45
46        let mut checkpoint = CheckpointOptions::new(
47            "Planner isolated the recovery path to token signer rotation.",
48        );
49        checkpoint.run_id = Some(run_id.clone());
50        checkpoint.label = Some("pre-compaction-1".to_string());
51        checkpoint.metadata = Some(json!({ "stage": "analysis" }));
52        checkpoint.agent_id = Some("planner".to_string());
53        let checkpoint_response = client.checkpoint(checkpoint).await?;
54
55        let mut list_agents = ListAgentsOptions::default();
56        list_agents.run_id = Some(run_id.clone());
57        let agents = client.list_agents(list_agents).await?;
58
59        let lessons = client.control.lessons(json!({ "run_id": run_id, "limit": 10 })).await?;
60        let lesson_id = lessons
61            .get("lessons")
62            .and_then(|value| value.as_array())
63            .and_then(|items| items.first())
64            .and_then(|item| item.get("id"))
65            .and_then(|value| value.as_str())
66            .ok_or_else(|| boxed_error(format!("expected at least one lesson to record outcome against: {lessons}")))?
67            .to_string();
68
69        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
70        outcome.run_id = Some(run_id.clone());
71        outcome.signal = 0.75;
72        outcome.rationale = "Recovery succeeded after following the stored lesson.".to_string();
73        outcome.agent_id = Some("planner".to_string());
74        let outcome_response = client.record_outcome(outcome).await?;
75
76        let mut strategies = SurfaceStrategiesOptions::default();
77        strategies.run_id = Some(run_id.clone());
78        strategies.lesson_types = vec!["success".to_string(), "failure".to_string()];
79        strategies.max_strategies = 5;
80        let strategy_response = client.surface_strategies(strategies).await?;
81
82        require(
83            checkpoint_response
84                .get("success")
85                .and_then(|value| value.as_bool())
86                .unwrap_or(false),
87            format!("checkpoint failed: {checkpoint_response}"),
88        )?;
89        let agent_count = agents
90            .get("agents")
91            .and_then(|value| value.as_array())
92            .map(|items| items.len())
93            .unwrap_or(0);
94        require(agent_count == 1, format!("agent registration missing: {agents}"))?;
95        require(
96            outcome_response
97                .get("success")
98                .and_then(|value| value.as_bool())
99                .unwrap_or(false),
100            format!("record_outcome failed: {outcome_response}"),
101        )?;
102        let strategy_count = strategy_response
103            .get("strategies")
104            .and_then(|value| value.as_array())
105            .map(|items| items.len())
106            .unwrap_or(0);
107
108        metrics = json!({
109            "run_id": run_id,
110            "checkpoint_id": checkpoint_response.get("checkpoint_id").cloned().unwrap_or(serde_json::Value::Null),
111            "agent_count": agent_count,
112            "strategy_count": strategy_count,
113        });
114
115        Ok::<(), Box<dyn Error>>(())
116    }
117    .await;
118
119    if let Err(err) = scenario {
120        passed = false;
121        detail = err.to_string();
122    }
123
124    let cleanup_ok = cleanup_run(&client, &run_id).await;
125    if !cleanup_ok {
126        passed = false;
127        detail = format!("{detail} | cleanup failures");
128    }
129
130    print_summary(
131        name,
132        passed,
133        &detail,
134        &metrics,
135        started.elapsed().as_secs_f64(),
136        cleanup_ok,
137    );
138
139    if passed {
140        Ok(())
141    } else {
142        Err(boxed_error(detail))
143    }
144}
examples/public/05_agent_registration_and_scoped_access.rs (line 74)
11async fn main() -> Result<(), Box<dyn Error>> {
12    let name = "public_05_agent_registration_and_scoped_access";
13    let started = Instant::now();
14    let client = create_client().await?;
15    let run_id = new_run_id("public_agent_scopes");
16    client.set_run_id(Some(run_id.clone()));
17    client.set_transport(TransportMode::Http);
18
19    let mut passed = true;
20    let mut detail = "validated agent registration and scoped access".to_string();
21    let mut metrics = json!({});
22
23    let scenario = async {
24        let mut planner = RegisterAgentOptions::new("planner");
25        planner.run_id = Some(run_id.clone());
26        planner.role = "planner".to_string();
27        planner.read_scopes = vec!["fact".into(), "lesson".into()];
28        planner.write_scopes = vec!["fact".into(), "lesson".into()];
29        planner.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
30        client.register_agent(planner).await?;
31
32        let mut reviewer = RegisterAgentOptions::new("reviewer");
33        reviewer.run_id = Some(run_id.clone());
34        reviewer.role = "reviewer".to_string();
35        reviewer.read_scopes = vec!["rule".into(), "trace".into()];
36        reviewer.write_scopes = vec!["rule".into(), "trace".into()];
37        reviewer.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
38        client.register_agent(reviewer).await?;
39
40        let mut planner_fact = RememberOptions::new("Claim requires police report only when payout exceeds 3000 GBP.");
41        planner_fact.run_id = Some(run_id.clone());
42        planner_fact.agent_id = Some("planner".into());
43        planner_fact.intent = Some("fact".into());
44        planner_fact.metadata = Some(json!({"source": "planner"}));
45        let planner_write = client.remember(planner_fact).await?;
46
47        let mut reviewer_rule = RememberOptions::new("Escalate to compliance if a police report is missing after payout approval.");
48        reviewer_rule.run_id = Some(run_id.clone());
49        reviewer_rule.agent_id = Some("reviewer".into());
50        reviewer_rule.intent = Some("rule".into());
51        reviewer_rule.metadata = Some(json!({"source": "reviewer"}));
52        let reviewer_write = client.remember(reviewer_rule).await?;
53
54        let mut planner_context_opts = GetContextOptions::default();
55        planner_context_opts.run_id = Some(run_id.clone());
56        planner_context_opts.query = Some("What should planner know before triage?".into());
57        planner_context_opts.agent_id = Some("planner".into());
58        planner_context_opts.entry_types = vec!["fact".into(), "lesson".into(), "rule".into()];
59        planner_context_opts.mode = Some("sections".into());
60        planner_context_opts.sections = vec!["facts".into(), "rules".into()];
61        let planner_context = client.get_context(planner_context_opts).await?;
62
63        let mut reviewer_context_opts = GetContextOptions::default();
64        reviewer_context_opts.run_id = Some(run_id.clone());
65        reviewer_context_opts.query = Some("What should reviewer know before approval?".into());
66        reviewer_context_opts.agent_id = Some("reviewer".into());
67        reviewer_context_opts.entry_types = vec!["fact".into(), "lesson".into(), "rule".into(), "trace".into()];
68        reviewer_context_opts.mode = Some("sections".into());
69        reviewer_context_opts.sections = vec!["facts".into(), "rules".into()];
70        let reviewer_context = client.get_context(reviewer_context_opts).await?;
71
72        let mut list_agents = ListAgentsOptions::default();
73        list_agents.run_id = Some(run_id.clone());
74        let agents = client.list_agents(list_agents).await?;
75
76        require(planner_write.get("accepted").and_then(|v| v.as_bool()).unwrap_or(false) || planner_write.get("job_id").is_some(), format!("planner remember failed: {planner_write}"))?;
77        require(reviewer_write.get("accepted").and_then(|v| v.as_bool()).unwrap_or(false) || reviewer_write.get("job_id").is_some(), format!("reviewer remember failed: {reviewer_write}"))?;
78        let agent_count = agents.get("agents").and_then(|v| v.as_array()).map(|items| items.len()).unwrap_or(0);
79        require(agent_count == 2, format!("agent registration failed: {agents}"))?;
80
81        let planner_types: Vec<&str> = planner_context.get("sources").and_then(|v| v.as_array()).into_iter().flatten().filter_map(|source| source.get("entry_type").and_then(|v| v.as_str())).collect();
82        let reviewer_types: Vec<&str> = reviewer_context.get("sources").and_then(|v| v.as_array()).into_iter().flatten().filter_map(|source| source.get("entry_type").and_then(|v| v.as_str())).collect();
83        require(planner_types.iter().any(|t| *t == "fact"), format!("planner should see facts: {planner_context}"))?;
84        require(!planner_types.iter().any(|t| *t == "rule"), format!("planner should not see reviewer rule scope: {planner_context}"))?;
85        require(reviewer_types.iter().any(|t| *t == "rule"), format!("reviewer should see rules: {reviewer_context}"))?;
86
87        metrics = json!({
88            "run_id": run_id,
89            "agent_count": agent_count,
90            "planner_source_types": planner_types,
91            "reviewer_source_types": reviewer_types,
92        });
93        Ok::<(), Box<dyn Error>>(())
94    }
95    .await;
96
97    if let Err(err) = scenario {
98        passed = false;
99        detail = err.to_string();
100    }
101
102    let cleanup_ok = cleanup_run(&client, &run_id).await;
103    if !cleanup_ok {
104        passed = false;
105        detail = format!("{detail} | cleanup failures");
106    }
107
108    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
109    if passed { Ok(()) } else { Err(boxed_error(detail)) }
110}
examples/public/10_full_learning_loop_smoke.rs (line 97)
16async fn main() -> Result<(), Box<dyn Error>> {
17    let name = "public_10_full_learning_loop_smoke";
18    let started = Instant::now();
19    let client = create_client().await?;
20    let run_id = new_run_id("public_10_full_learning_loop_smoke");
21    client.set_run_id(Some(run_id.clone()));
22    client.set_transport(TransportMode::Http);
23
24    let mut passed = true;
25    let mut detail = "validated all helper flows".to_string();
26    let mut metrics = json!({});
27
28    let scenario = async {
29        let mut remember = RememberOptions::new("Policy limit is 5000 and claimant city is Leeds.");
30        remember.run_id = Some(run_id.clone());
31        remember.agent_id = Some("planner".to_string());
32        remember.intent = Some("fact".to_string());
33        remember.metadata = Some(json!({"suite": "all-helpers", "family": "claims"}));
34        remember.importance = Some("high".to_string());
35        remember.occurrence_time = Some(std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as i64 - 86400);
36        let remember_response = client.remember(remember).await?;
37
38        let mut lesson = RememberOptions::new("If city is missing from the latest step, check stored claim facts before escalating.");
39        lesson.run_id = Some(run_id.clone());
40        lesson.agent_id = Some("planner".to_string());
41        lesson.intent = Some("lesson".to_string());
42        lesson.lesson_type = Some("success".to_string());
43        lesson.lesson_scope = Some("session".to_string());
44        lesson.lesson_importance = Some("high".to_string());
45        let lesson_response = client.remember(lesson).await?;
46
47        let mut mental_model = RememberOptions::new(
48            "Claims case overview: Policy limit 5000 GBP, claimant city Leeds, \
49             missing-city branch resolved via stored claim facts. Lesson: check stored facts before escalating.",
50        );
51        mental_model.run_id = Some(run_id.clone());
52        mental_model.agent_id = Some("planner".to_string());
53        mental_model.intent = Some("mental_model".to_string());
54        mental_model.importance = Some("critical".to_string());
55        mental_model.metadata = Some(json!({"suite": "all-helpers", "entity": "claims-case", "consolidated": true}));
56        let mental_model_response = client.remember(mental_model).await?;
57
58        let mut recall = RecallOptions::new("What is the policy limit?");
59        recall.run_id = Some(run_id.clone());
60        recall.agent_id = Some("planner".to_string());
61        recall.limit = 5;
62        let recall_response = client.recall(recall).await?;
63
64        let mut context = GetContextOptions::default();
65        context.run_id = Some(run_id.clone());
66        context.query = Some("Prepare a short adjuster summary".to_string());
67        context.agent_id = Some("planner".to_string());
68        context.limit = Some(6);
69        context.max_token_budget = Some(700);
70        let context_response = client.get_context(context).await?;
71
72        let mut health = MemoryHealthOptions::default();
73        health.run_id = Some(run_id.clone());
74        health.limit = 50;
75        let health_response = client.memory_health(health).await?;
76
77        let mut diagnose = DiagnoseOptions::new("policy limit lookup returned empty");
78        diagnose.run_id = Some(run_id.clone());
79        diagnose.error_type = Some("retrieval".to_string());
80        diagnose.limit = 5;
81        let diagnose_response = client.diagnose(diagnose).await?;
82
83        let mut reflect = ReflectOptions::default();
84        reflect.run_id = Some(run_id.clone());
85        let reflect_response = client.reflect(reflect).await?;
86
87        let mut register = RegisterAgentOptions::new("planner");
88        register.run_id = Some(run_id.clone());
89        register.role = "planner".to_string();
90        register.read_scopes = vec!["fact".into(), "lesson".into(), "rule".into(), "mental_model".into(), "archive_block".into(), "handoff".into(), "feedback".into()];
91        register.write_scopes = vec!["fact".into(), "trace".into(), "lesson".into(), "observation".into(), "archive_block".into()];
92        register.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
93        let register_response = client.register_agent(register).await?;
94
95        let mut list_agents = ListAgentsOptions::default();
96        list_agents.run_id = Some(run_id.clone());
97        let agents_response = client.list_agents(list_agents).await?;
98
99        let mut archive = ArchiveOptions::new(
100            "Exact adjuster note: claimant confirmed city is Leeds during triage.",
101            "adjuster_note",
102        );
103        archive.run_id = Some(run_id.clone());
104        archive.agent_id = Some("planner".to_string());
105        archive.origin_agent_id = Some("planner".to_string());
106        archive.source_attempt_id = Some("attempt-1".to_string());
107        archive.source_tool = Some("phone_call".to_string());
108        archive.labels = vec!["claims".to_string(), "triage".to_string()];
109        archive.family = Some("claims-adjustment".to_string());
110        archive.metadata = Some(json!({"case": "all-helpers"}));
111        let archive_response = client.archive(archive).await?;
112        let reference_id = archive_response
113            .get("reference_id")
114            .and_then(Value::as_str)
115            .ok_or_else(|| boxed_error(format!("archive reference missing: {archive_response}")))?
116            .to_string();
117
118        let mut dereference = DereferenceOptions::new(reference_id.clone());
119        dereference.run_id = Some(run_id.clone());
120        dereference.agent_id = Some("planner".to_string());
121        let dereference_response = client.dereference(dereference).await?;
122
123        let mut checkpoint = CheckpointOptions::new("Planner captured claim facts before window compaction.");
124        checkpoint.run_id = Some(run_id.clone());
125        checkpoint.label = Some("pre-compaction".to_string());
126        checkpoint.metadata = Some(json!({"stage": "analysis"}));
127        checkpoint.agent_id = Some("planner".to_string());
128        let checkpoint_response = client.checkpoint(checkpoint).await?;
129
130        let lessons_response = client.control.lessons(json!({"run_id": run_id, "limit": 20})).await?;
131        let lesson_id = lessons_response
132            .get("lessons")
133            .and_then(Value::as_array)
134            .and_then(|items| items.iter().find_map(|item| item.get("id").and_then(Value::as_str)))
135            .ok_or_else(|| boxed_error(format!("expected lesson id for outcome flow: {lessons_response}")))?
136            .to_string();
137
138        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
139        outcome.run_id = Some(run_id.clone());
140        outcome.signal = 0.75;
141        outcome.rationale = "Planner reused stored claim fact and resolved the missing-city branch.".to_string();
142        outcome.agent_id = Some("planner".to_string());
143        let outcome_response = client.record_outcome(outcome).await?;
144
145        let mut strategies = SurfaceStrategiesOptions::default();
146        strategies.run_id = Some(run_id.clone());
147        strategies.lesson_types = vec!["success".to_string(), "rule".to_string()];
148        strategies.max_strategies = 5;
149        let strategies_response = client.surface_strategies(strategies).await?;
150
151        let mut handoff = HandoffOptions::new(
152            "claim-1",
153            "planner",
154            "reviewer",
155            "Review whether the stored claimant city is sufficient for routing.",
156        );
157        handoff.run_id = Some(run_id.clone());
158        handoff.requested_action = "review".to_string();
159        handoff.metadata = Some(json!({"team": "claims"}));
160        let handoff_response = client.handoff(handoff).await?;
161        let handoff_id = handoff_response
162            .get("handoff_id")
163            .and_then(Value::as_str)
164            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
165            .to_string();
166
167        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
168        feedback.run_id = Some(run_id.clone());
169        feedback.comments = "Stored fact is sufficient; proceed without escalation.".to_string();
170        feedback.from_agent_id = Some("reviewer".to_string());
171        feedback.metadata = Some(json!({"team": "claims"}));
172        let feedback_response = client.feedback(feedback).await?;
173
174        require(remember_response.get("job_id").is_some() || remember_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("remember failed: {remember_response}"))?;
175        require(mental_model_response.get("job_id").is_some() || mental_model_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("mental_model remember failed: {mental_model_response}"))?;
176        require(lesson_response.get("job_id").is_some() || lesson_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("lesson remember failed: {lesson_response}"))?;
177        require(recall_response.get("final_answer").is_some() || recall_response.get("evidence").is_some(), format!("recall failed: {recall_response}"))?;
178        require(context_response.get("sources").and_then(Value::as_array).is_some(), format!("context malformed: {context_response}"))?;
179        require(health_response.get("entry_counts").and_then(Value::as_object).is_some(), format!("memory_health malformed: {health_response}"))?;
180        require(diagnose_response.get("failure_lessons").and_then(Value::as_array).is_some(), format!("diagnose malformed: {diagnose_response}"))?;
181        require(reflect_response.get("lessons").and_then(Value::as_array).is_some(), format!("reflect malformed: {reflect_response}"))?;
182        require(register_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("register_agent failed: {register_response}"))?;
183        require(agents_response.get("agents").and_then(Value::as_array).map(|items| !items.is_empty()).unwrap_or(false), format!("list_agents failed: {agents_response}"))?;
184        require(archive_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("archive failed: {archive_response}"))?;
185        require(dereference_response.get("found").and_then(Value::as_bool).unwrap_or(false), format!("dereference failed: {dereference_response}"))?;
186        require(checkpoint_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
187        require(outcome_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("record_outcome failed: {outcome_response}"))?;
188        require(strategies_response.get("strategies").and_then(Value::as_array).is_some(), format!("surface_strategies malformed: {strategies_response}"))?;
189        require(handoff_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
190        require(feedback_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
191
192        let strategy_count = strategies_response
193            .get("strategies")
194            .and_then(Value::as_array)
195            .map(|items| items.len())
196            .unwrap_or(0);
197        let agent_count = agents_response
198            .get("agents")
199            .and_then(Value::as_array)
200            .map(|items| items.len())
201            .unwrap_or(0);
202        let lesson_count = lessons_response
203            .get("lessons")
204            .and_then(Value::as_array)
205            .map(|items| items.len())
206            .unwrap_or(0);
207
208        metrics = json!({
209            "run_id": run_id,
210            "agent_count": agent_count,
211            "strategy_count": strategy_count,
212            "reference_id": reference_id,
213            "lesson_count": lesson_count,
214        });
215
216        Ok::<(), Box<dyn Error>>(())
217    }
218    .await;
219
220    if let Err(err) = scenario {
221        passed = false;
222        detail = err.to_string();
223    }
224
225    let cleanup_ok = cleanup_run(&client, &run_id).await;
226    if !cleanup_ok {
227        passed = false;
228        detail = format!("{detail} | cleanup failures");
229    }
230
231    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
232
233    if passed { Ok(()) } else { Err(boxed_error(detail)) }
234}
examples/helper_all_helpers.rs (line 85)
16async fn main() -> Result<(), Box<dyn Error>> {
17    let name = "helper_all_helpers";
18    let started = Instant::now();
19    let client = create_client().await?;
20    let run_id = new_run_id("helper_all_helpers");
21    client.set_run_id(Some(run_id.clone()));
22    client.set_transport(TransportMode::Http);
23
24    let mut passed = true;
25    let mut detail = "validated all helper flows".to_string();
26    let mut metrics = json!({});
27
28    let scenario = async {
29        let mut remember = RememberOptions::new("Policy limit is 5000 and claimant city is Leeds.");
30        remember.run_id = Some(run_id.clone());
31        remember.agent_id = Some("planner".to_string());
32        remember.intent = Some("fact".to_string());
33        remember.metadata = Some(json!({"suite": "all-helpers", "family": "claims"}));
34        remember.importance = Some("high".to_string());
35        let remember_response = client.remember(remember).await?;
36
37        let mut lesson = RememberOptions::new("If city is missing from the latest step, check stored claim facts before escalating.");
38        lesson.run_id = Some(run_id.clone());
39        lesson.agent_id = Some("planner".to_string());
40        lesson.intent = Some("lesson".to_string());
41        lesson.lesson_type = Some("success".to_string());
42        lesson.lesson_scope = Some("session".to_string());
43        lesson.lesson_importance = Some("high".to_string());
44        let lesson_response = client.remember(lesson).await?;
45
46        let mut recall = RecallOptions::new("What is the policy limit?");
47        recall.run_id = Some(run_id.clone());
48        recall.agent_id = Some("planner".to_string());
49        recall.limit = 5;
50        let recall_response = client.recall(recall).await?;
51
52        let mut context = GetContextOptions::default();
53        context.run_id = Some(run_id.clone());
54        context.query = Some("Prepare a short adjuster summary".to_string());
55        context.agent_id = Some("planner".to_string());
56        context.limit = Some(6);
57        context.max_token_budget = Some(700);
58        let context_response = client.get_context(context).await?;
59
60        let mut health = MemoryHealthOptions::default();
61        health.run_id = Some(run_id.clone());
62        health.limit = 50;
63        let health_response = client.memory_health(health).await?;
64
65        let mut diagnose = DiagnoseOptions::new("policy limit lookup returned empty");
66        diagnose.run_id = Some(run_id.clone());
67        diagnose.error_type = Some("retrieval".to_string());
68        diagnose.limit = 5;
69        let diagnose_response = client.diagnose(diagnose).await?;
70
71        let mut reflect = ReflectOptions::default();
72        reflect.run_id = Some(run_id.clone());
73        let reflect_response = client.reflect(reflect).await?;
74
75        let mut register = RegisterAgentOptions::new("planner");
76        register.run_id = Some(run_id.clone());
77        register.role = "planner".to_string();
78        register.read_scopes = vec!["fact".into(), "lesson".into(), "rule".into(), "archive_block".into(), "handoff".into(), "feedback".into()];
79        register.write_scopes = vec!["fact".into(), "trace".into(), "lesson".into(), "observation".into(), "archive_block".into()];
80        register.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
81        let register_response = client.register_agent(register).await?;
82
83        let mut list_agents = ListAgentsOptions::default();
84        list_agents.run_id = Some(run_id.clone());
85        let agents_response = client.list_agents(list_agents).await?;
86
87        let mut archive = ArchiveOptions::new(
88            "Exact adjuster note: claimant confirmed city is Leeds during triage.",
89            "adjuster_note",
90        );
91        archive.run_id = Some(run_id.clone());
92        archive.agent_id = Some("planner".to_string());
93        archive.origin_agent_id = Some("planner".to_string());
94        archive.source_attempt_id = Some("attempt-1".to_string());
95        archive.source_tool = Some("phone_call".to_string());
96        archive.labels = vec!["claims".to_string(), "triage".to_string()];
97        archive.family = Some("claims-adjustment".to_string());
98        archive.metadata = Some(json!({"case": "all-helpers"}));
99        let archive_response = client.archive(archive).await?;
100        let reference_id = archive_response
101            .get("reference_id")
102            .and_then(Value::as_str)
103            .ok_or_else(|| boxed_error(format!("archive reference missing: {archive_response}")))?
104            .to_string();
105
106        let mut dereference = DereferenceOptions::new(reference_id.clone());
107        dereference.run_id = Some(run_id.clone());
108        dereference.agent_id = Some("planner".to_string());
109        let dereference_response = client.dereference(dereference).await?;
110
111        let mut checkpoint = CheckpointOptions::new("Planner captured claim facts before window compaction.");
112        checkpoint.run_id = Some(run_id.clone());
113        checkpoint.label = Some("pre-compaction".to_string());
114        checkpoint.metadata = Some(json!({"stage": "analysis"}));
115        checkpoint.agent_id = Some("planner".to_string());
116        let checkpoint_response = client.checkpoint(checkpoint).await?;
117
118        let lessons_response = client.control.lessons(json!({"run_id": run_id, "limit": 20})).await?;
119        let lesson_id = lessons_response
120            .get("lessons")
121            .and_then(Value::as_array)
122            .and_then(|items| items.iter().find_map(|item| item.get("id").and_then(Value::as_str)))
123            .ok_or_else(|| boxed_error(format!("expected lesson id for outcome flow: {lessons_response}")))?
124            .to_string();
125
126        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
127        outcome.run_id = Some(run_id.clone());
128        outcome.signal = 0.75;
129        outcome.rationale = "Planner reused stored claim fact and resolved the missing-city branch.".to_string();
130        outcome.agent_id = Some("planner".to_string());
131        let outcome_response = client.record_outcome(outcome).await?;
132
133        let mut strategies = SurfaceStrategiesOptions::default();
134        strategies.run_id = Some(run_id.clone());
135        strategies.lesson_types = vec!["success".to_string(), "rule".to_string()];
136        strategies.max_strategies = 5;
137        let strategies_response = client.surface_strategies(strategies).await?;
138
139        let mut handoff = HandoffOptions::new(
140            "claim-1",
141            "planner",
142            "reviewer",
143            "Review whether the stored claimant city is sufficient for routing.",
144        );
145        handoff.run_id = Some(run_id.clone());
146        handoff.requested_action = "review".to_string();
147        handoff.metadata = Some(json!({"team": "claims"}));
148        let handoff_response = client.handoff(handoff).await?;
149        let handoff_id = handoff_response
150            .get("handoff_id")
151            .and_then(Value::as_str)
152            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
153            .to_string();
154
155        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
156        feedback.run_id = Some(run_id.clone());
157        feedback.comments = "Stored fact is sufficient; proceed without escalation.".to_string();
158        feedback.from_agent_id = Some("reviewer".to_string());
159        feedback.metadata = Some(json!({"team": "claims"}));
160        let feedback_response = client.feedback(feedback).await?;
161
162        let scratch_run = format!("{run_id}_forget");
163        let mut scratch = RememberOptions::new("Scratch run for forget helper coverage.");
164        scratch.run_id = Some(scratch_run.clone());
165        scratch.agent_id = Some("planner".to_string());
166        scratch.intent = Some("fact".to_string());
167        scratch.metadata = Some(json!({"suite": "all-helpers", "temporary": true}));
168        let scratch_response = client.remember(scratch).await?;
169
170        let forget_response = client
171            .forget(ForgetOptions::for_run(scratch_run.clone()))
172            .await?;
173
174        let mut forgotten = RecallOptions::new("What temporary scratch fact exists?");
175        forgotten.run_id = Some(scratch_run.clone());
176        forgotten.limit = 3;
177        let forgotten_response = client.recall(forgotten).await?;
178
179        require(remember_response.get("job_id").is_some() || remember_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("remember failed: {remember_response}"))?;
180        require(lesson_response.get("job_id").is_some() || lesson_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("lesson remember failed: {lesson_response}"))?;
181        require(recall_response.get("final_answer").is_some() || recall_response.get("evidence").is_some(), format!("recall failed: {recall_response}"))?;
182        require(context_response.get("sources").and_then(Value::as_array).is_some(), format!("context malformed: {context_response}"))?;
183        require(health_response.get("entry_counts").and_then(Value::as_object).is_some(), format!("memory_health malformed: {health_response}"))?;
184        require(diagnose_response.get("failure_lessons").and_then(Value::as_array).is_some(), format!("diagnose malformed: {diagnose_response}"))?;
185        require(reflect_response.get("lessons").and_then(Value::as_array).is_some(), format!("reflect malformed: {reflect_response}"))?;
186        require(register_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("register_agent failed: {register_response}"))?;
187        require(agents_response.get("agents").and_then(Value::as_array).map(|items| !items.is_empty()).unwrap_or(false), format!("list_agents failed: {agents_response}"))?;
188        require(archive_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("archive failed: {archive_response}"))?;
189        require(dereference_response.get("found").and_then(Value::as_bool).unwrap_or(false), format!("dereference failed: {dereference_response}"))?;
190        require(checkpoint_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
191        require(outcome_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("record_outcome failed: {outcome_response}"))?;
192        require(strategies_response.get("strategies").and_then(Value::as_array).is_some(), format!("surface_strategies malformed: {strategies_response}"))?;
193        require(handoff_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
194        require(feedback_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
195        require(scratch_response.get("job_id").is_some() || scratch_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("scratch remember failed: {scratch_response}"))?;
196        require(forget_response.get("success").and_then(Value::as_bool).unwrap_or(true), format!("forget failed: {forget_response}"))?;
197        let scratch_fact_visible = forgotten_response
198            .get("evidence")
199            .and_then(Value::as_array)
200            .map(|items| {
201                items.iter().any(|item| {
202                    item.get("run_id").and_then(Value::as_str) == Some(scratch_run.as_str())
203                        || item
204                            .get("content")
205                            .and_then(Value::as_str)
206                            .map(|content| {
207                                content
208                                    .to_ascii_lowercase()
209                                    .contains("scratch run for forget helper coverage")
210                            })
211                            .unwrap_or(false)
212                })
213            })
214            .unwrap_or(false);
215        require(!scratch_fact_visible, format!("scratch fact should be forgotten even if same-user lessons still surface: {forgotten_response}"))?;
216
217        let strategy_count = strategies_response
218            .get("strategies")
219            .and_then(Value::as_array)
220            .map(|items| items.len())
221            .unwrap_or(0);
222        let agent_count = agents_response
223            .get("agents")
224            .and_then(Value::as_array)
225            .map(|items| items.len())
226            .unwrap_or(0);
227        let lesson_count = lessons_response
228            .get("lessons")
229            .and_then(Value::as_array)
230            .map(|items| items.len())
231            .unwrap_or(0);
232
233        metrics = json!({
234            "run_id": run_id,
235            "agent_count": agent_count,
236            "strategy_count": strategy_count,
237            "reference_id": reference_id,
238            "lesson_count": lesson_count,
239            "forgotten_run": scratch_run,
240        });
241
242        Ok::<(), Box<dyn Error>>(())
243    }
244    .await;
245
246    if let Err(err) = scenario {
247        passed = false;
248        detail = err.to_string();
249    }
250
251    let cleanup_ok = cleanup_run(&client, &run_id).await;
252    if !cleanup_ok {
253        passed = false;
254        detail = format!("{detail} | cleanup failures");
255    }
256
257    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
258
259    if passed { Ok(()) } else { Err(boxed_error(detail)) }
260}
Source

pub async fn record_outcome( &self, options: RecordOutcomeOptions, ) -> Result<Value>

Examples found in repository?
examples/helper_mas_learning_loop.rs (line 74)
14async fn main() -> Result<(), Box<dyn Error>> {
15    let name = "helper_mas_learning_loop";
16    let started = Instant::now();
17    let client = create_client().await?;
18    let run_id = new_run_id("helper_mas_learning_loop");
19    client.set_run_id(Some(run_id.clone()));
20    client.set_transport(TransportMode::Http);
21
22    let mut passed = true;
23    let mut detail = "validated helper MAS checkpoint/outcome/strategies flow".to_string();
24    let mut metrics = json!({});
25
26    let scenario = async {
27        let mut register = RegisterAgentOptions::new("planner");
28        register.run_id = Some(run_id.clone());
29        register.role = "planner".to_string();
30        register.read_scopes = vec!["rule".to_string(), "lesson".to_string(), "fact".to_string()];
31        register.write_scopes = vec!["lesson".to_string(), "trace".to_string()];
32        register.shared_memory_lanes = vec!["knowledge".to_string(), "history".to_string()];
33        client.register_agent(register).await?;
34
35        let mut remember = RememberOptions::new(
36            "If a retry succeeds after token signer rotation, record it as a reusable recovery pattern.",
37        );
38        remember.run_id = Some(run_id.clone());
39        remember.agent_id = Some("planner".to_string());
40        remember.intent = Some("lesson".to_string());
41        remember.lesson_type = Some("success".to_string());
42        remember.lesson_scope = Some("session".to_string());
43        remember.lesson_importance = Some("high".to_string());
44        client.remember(remember).await?;
45
46        let mut checkpoint = CheckpointOptions::new(
47            "Planner isolated the recovery path to token signer rotation.",
48        );
49        checkpoint.run_id = Some(run_id.clone());
50        checkpoint.label = Some("pre-compaction-1".to_string());
51        checkpoint.metadata = Some(json!({ "stage": "analysis" }));
52        checkpoint.agent_id = Some("planner".to_string());
53        let checkpoint_response = client.checkpoint(checkpoint).await?;
54
55        let mut list_agents = ListAgentsOptions::default();
56        list_agents.run_id = Some(run_id.clone());
57        let agents = client.list_agents(list_agents).await?;
58
59        let lessons = client.control.lessons(json!({ "run_id": run_id, "limit": 10 })).await?;
60        let lesson_id = lessons
61            .get("lessons")
62            .and_then(|value| value.as_array())
63            .and_then(|items| items.first())
64            .and_then(|item| item.get("id"))
65            .and_then(|value| value.as_str())
66            .ok_or_else(|| boxed_error(format!("expected at least one lesson to record outcome against: {lessons}")))?
67            .to_string();
68
69        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
70        outcome.run_id = Some(run_id.clone());
71        outcome.signal = 0.75;
72        outcome.rationale = "Recovery succeeded after following the stored lesson.".to_string();
73        outcome.agent_id = Some("planner".to_string());
74        let outcome_response = client.record_outcome(outcome).await?;
75
76        let mut strategies = SurfaceStrategiesOptions::default();
77        strategies.run_id = Some(run_id.clone());
78        strategies.lesson_types = vec!["success".to_string(), "failure".to_string()];
79        strategies.max_strategies = 5;
80        let strategy_response = client.surface_strategies(strategies).await?;
81
82        require(
83            checkpoint_response
84                .get("success")
85                .and_then(|value| value.as_bool())
86                .unwrap_or(false),
87            format!("checkpoint failed: {checkpoint_response}"),
88        )?;
89        let agent_count = agents
90            .get("agents")
91            .and_then(|value| value.as_array())
92            .map(|items| items.len())
93            .unwrap_or(0);
94        require(agent_count == 1, format!("agent registration missing: {agents}"))?;
95        require(
96            outcome_response
97                .get("success")
98                .and_then(|value| value.as_bool())
99                .unwrap_or(false),
100            format!("record_outcome failed: {outcome_response}"),
101        )?;
102        let strategy_count = strategy_response
103            .get("strategies")
104            .and_then(|value| value.as_array())
105            .map(|items| items.len())
106            .unwrap_or(0);
107
108        metrics = json!({
109            "run_id": run_id,
110            "checkpoint_id": checkpoint_response.get("checkpoint_id").cloned().unwrap_or(serde_json::Value::Null),
111            "agent_count": agent_count,
112            "strategy_count": strategy_count,
113        });
114
115        Ok::<(), Box<dyn Error>>(())
116    }
117    .await;
118
119    if let Err(err) = scenario {
120        passed = false;
121        detail = err.to_string();
122    }
123
124    let cleanup_ok = cleanup_run(&client, &run_id).await;
125    if !cleanup_ok {
126        passed = false;
127        detail = format!("{detail} | cleanup failures");
128    }
129
130    print_summary(
131        name,
132        passed,
133        &detail,
134        &metrics,
135        started.elapsed().as_secs_f64(),
136        cleanup_ok,
137    );
138
139    if passed {
140        Ok(())
141    } else {
142        Err(boxed_error(detail))
143    }
144}
More examples
Hide additional examples
examples/public/03_checkpoint_reflect_outcome.rs (line 74)
14async fn main() -> Result<(), Box<dyn Error>> {
15    let name = "public_03_checkpoint_reflect_outcome";
16    let started = Instant::now();
17    let client = create_client().await?;
18    let run_id = new_run_id("public_03_checkpoint_reflect_outcome");
19    client.set_run_id(Some(run_id.clone()));
20    client.set_transport(TransportMode::Http);
21
22    let mut passed = true;
23    let mut detail = "validated helper MAS checkpoint/outcome/strategies flow".to_string();
24    let mut metrics = json!({});
25
26    let scenario = async {
27        let mut register = RegisterAgentOptions::new("planner");
28        register.run_id = Some(run_id.clone());
29        register.role = "planner".to_string();
30        register.read_scopes = vec!["rule".to_string(), "lesson".to_string(), "fact".to_string()];
31        register.write_scopes = vec!["lesson".to_string(), "trace".to_string()];
32        register.shared_memory_lanes = vec!["knowledge".to_string(), "history".to_string()];
33        client.register_agent(register).await?;
34
35        let mut remember = RememberOptions::new(
36            "If a retry succeeds after token signer rotation, record it as a reusable recovery pattern.",
37        );
38        remember.run_id = Some(run_id.clone());
39        remember.agent_id = Some("planner".to_string());
40        remember.intent = Some("lesson".to_string());
41        remember.lesson_type = Some("success".to_string());
42        remember.lesson_scope = Some("session".to_string());
43        remember.lesson_importance = Some("high".to_string());
44        client.remember(remember).await?;
45
46        let mut checkpoint = CheckpointOptions::new(
47            "Planner isolated the recovery path to token signer rotation.",
48        );
49        checkpoint.run_id = Some(run_id.clone());
50        checkpoint.label = Some("pre-compaction-1".to_string());
51        checkpoint.metadata = Some(json!({ "stage": "analysis" }));
52        checkpoint.agent_id = Some("planner".to_string());
53        let checkpoint_response = client.checkpoint(checkpoint).await?;
54
55        let mut list_agents = ListAgentsOptions::default();
56        list_agents.run_id = Some(run_id.clone());
57        let agents = client.list_agents(list_agents).await?;
58
59        let lessons = client.control.lessons(json!({ "run_id": run_id, "limit": 10 })).await?;
60        let lesson_id = lessons
61            .get("lessons")
62            .and_then(|value| value.as_array())
63            .and_then(|items| items.first())
64            .and_then(|item| item.get("id"))
65            .and_then(|value| value.as_str())
66            .ok_or_else(|| boxed_error(format!("expected at least one lesson to record outcome against: {lessons}")))?
67            .to_string();
68
69        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
70        outcome.run_id = Some(run_id.clone());
71        outcome.signal = 0.75;
72        outcome.rationale = "Recovery succeeded after following the stored lesson.".to_string();
73        outcome.agent_id = Some("planner".to_string());
74        let outcome_response = client.record_outcome(outcome).await?;
75
76        let mut strategies = SurfaceStrategiesOptions::default();
77        strategies.run_id = Some(run_id.clone());
78        strategies.lesson_types = vec!["success".to_string(), "failure".to_string()];
79        strategies.max_strategies = 5;
80        let strategy_response = client.surface_strategies(strategies).await?;
81
82        require(
83            checkpoint_response
84                .get("success")
85                .and_then(|value| value.as_bool())
86                .unwrap_or(false),
87            format!("checkpoint failed: {checkpoint_response}"),
88        )?;
89        let agent_count = agents
90            .get("agents")
91            .and_then(|value| value.as_array())
92            .map(|items| items.len())
93            .unwrap_or(0);
94        require(agent_count == 1, format!("agent registration missing: {agents}"))?;
95        require(
96            outcome_response
97                .get("success")
98                .and_then(|value| value.as_bool())
99                .unwrap_or(false),
100            format!("record_outcome failed: {outcome_response}"),
101        )?;
102        let strategy_count = strategy_response
103            .get("strategies")
104            .and_then(|value| value.as_array())
105            .map(|items| items.len())
106            .unwrap_or(0);
107
108        metrics = json!({
109            "run_id": run_id,
110            "checkpoint_id": checkpoint_response.get("checkpoint_id").cloned().unwrap_or(serde_json::Value::Null),
111            "agent_count": agent_count,
112            "strategy_count": strategy_count,
113        });
114
115        Ok::<(), Box<dyn Error>>(())
116    }
117    .await;
118
119    if let Err(err) = scenario {
120        passed = false;
121        detail = err.to_string();
122    }
123
124    let cleanup_ok = cleanup_run(&client, &run_id).await;
125    if !cleanup_ok {
126        passed = false;
127        detail = format!("{detail} | cleanup failures");
128    }
129
130    print_summary(
131        name,
132        passed,
133        &detail,
134        &metrics,
135        started.elapsed().as_secs_f64(),
136        cleanup_ok,
137    );
138
139    if passed {
140        Ok(())
141    } else {
142        Err(boxed_error(detail))
143    }
144}
examples/public/10_full_learning_loop_smoke.rs (line 143)
16async fn main() -> Result<(), Box<dyn Error>> {
17    let name = "public_10_full_learning_loop_smoke";
18    let started = Instant::now();
19    let client = create_client().await?;
20    let run_id = new_run_id("public_10_full_learning_loop_smoke");
21    client.set_run_id(Some(run_id.clone()));
22    client.set_transport(TransportMode::Http);
23
24    let mut passed = true;
25    let mut detail = "validated all helper flows".to_string();
26    let mut metrics = json!({});
27
28    let scenario = async {
29        let mut remember = RememberOptions::new("Policy limit is 5000 and claimant city is Leeds.");
30        remember.run_id = Some(run_id.clone());
31        remember.agent_id = Some("planner".to_string());
32        remember.intent = Some("fact".to_string());
33        remember.metadata = Some(json!({"suite": "all-helpers", "family": "claims"}));
34        remember.importance = Some("high".to_string());
35        remember.occurrence_time = Some(std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as i64 - 86400);
36        let remember_response = client.remember(remember).await?;
37
38        let mut lesson = RememberOptions::new("If city is missing from the latest step, check stored claim facts before escalating.");
39        lesson.run_id = Some(run_id.clone());
40        lesson.agent_id = Some("planner".to_string());
41        lesson.intent = Some("lesson".to_string());
42        lesson.lesson_type = Some("success".to_string());
43        lesson.lesson_scope = Some("session".to_string());
44        lesson.lesson_importance = Some("high".to_string());
45        let lesson_response = client.remember(lesson).await?;
46
47        let mut mental_model = RememberOptions::new(
48            "Claims case overview: Policy limit 5000 GBP, claimant city Leeds, \
49             missing-city branch resolved via stored claim facts. Lesson: check stored facts before escalating.",
50        );
51        mental_model.run_id = Some(run_id.clone());
52        mental_model.agent_id = Some("planner".to_string());
53        mental_model.intent = Some("mental_model".to_string());
54        mental_model.importance = Some("critical".to_string());
55        mental_model.metadata = Some(json!({"suite": "all-helpers", "entity": "claims-case", "consolidated": true}));
56        let mental_model_response = client.remember(mental_model).await?;
57
58        let mut recall = RecallOptions::new("What is the policy limit?");
59        recall.run_id = Some(run_id.clone());
60        recall.agent_id = Some("planner".to_string());
61        recall.limit = 5;
62        let recall_response = client.recall(recall).await?;
63
64        let mut context = GetContextOptions::default();
65        context.run_id = Some(run_id.clone());
66        context.query = Some("Prepare a short adjuster summary".to_string());
67        context.agent_id = Some("planner".to_string());
68        context.limit = Some(6);
69        context.max_token_budget = Some(700);
70        let context_response = client.get_context(context).await?;
71
72        let mut health = MemoryHealthOptions::default();
73        health.run_id = Some(run_id.clone());
74        health.limit = 50;
75        let health_response = client.memory_health(health).await?;
76
77        let mut diagnose = DiagnoseOptions::new("policy limit lookup returned empty");
78        diagnose.run_id = Some(run_id.clone());
79        diagnose.error_type = Some("retrieval".to_string());
80        diagnose.limit = 5;
81        let diagnose_response = client.diagnose(diagnose).await?;
82
83        let mut reflect = ReflectOptions::default();
84        reflect.run_id = Some(run_id.clone());
85        let reflect_response = client.reflect(reflect).await?;
86
87        let mut register = RegisterAgentOptions::new("planner");
88        register.run_id = Some(run_id.clone());
89        register.role = "planner".to_string();
90        register.read_scopes = vec!["fact".into(), "lesson".into(), "rule".into(), "mental_model".into(), "archive_block".into(), "handoff".into(), "feedback".into()];
91        register.write_scopes = vec!["fact".into(), "trace".into(), "lesson".into(), "observation".into(), "archive_block".into()];
92        register.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
93        let register_response = client.register_agent(register).await?;
94
95        let mut list_agents = ListAgentsOptions::default();
96        list_agents.run_id = Some(run_id.clone());
97        let agents_response = client.list_agents(list_agents).await?;
98
99        let mut archive = ArchiveOptions::new(
100            "Exact adjuster note: claimant confirmed city is Leeds during triage.",
101            "adjuster_note",
102        );
103        archive.run_id = Some(run_id.clone());
104        archive.agent_id = Some("planner".to_string());
105        archive.origin_agent_id = Some("planner".to_string());
106        archive.source_attempt_id = Some("attempt-1".to_string());
107        archive.source_tool = Some("phone_call".to_string());
108        archive.labels = vec!["claims".to_string(), "triage".to_string()];
109        archive.family = Some("claims-adjustment".to_string());
110        archive.metadata = Some(json!({"case": "all-helpers"}));
111        let archive_response = client.archive(archive).await?;
112        let reference_id = archive_response
113            .get("reference_id")
114            .and_then(Value::as_str)
115            .ok_or_else(|| boxed_error(format!("archive reference missing: {archive_response}")))?
116            .to_string();
117
118        let mut dereference = DereferenceOptions::new(reference_id.clone());
119        dereference.run_id = Some(run_id.clone());
120        dereference.agent_id = Some("planner".to_string());
121        let dereference_response = client.dereference(dereference).await?;
122
123        let mut checkpoint = CheckpointOptions::new("Planner captured claim facts before window compaction.");
124        checkpoint.run_id = Some(run_id.clone());
125        checkpoint.label = Some("pre-compaction".to_string());
126        checkpoint.metadata = Some(json!({"stage": "analysis"}));
127        checkpoint.agent_id = Some("planner".to_string());
128        let checkpoint_response = client.checkpoint(checkpoint).await?;
129
130        let lessons_response = client.control.lessons(json!({"run_id": run_id, "limit": 20})).await?;
131        let lesson_id = lessons_response
132            .get("lessons")
133            .and_then(Value::as_array)
134            .and_then(|items| items.iter().find_map(|item| item.get("id").and_then(Value::as_str)))
135            .ok_or_else(|| boxed_error(format!("expected lesson id for outcome flow: {lessons_response}")))?
136            .to_string();
137
138        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
139        outcome.run_id = Some(run_id.clone());
140        outcome.signal = 0.75;
141        outcome.rationale = "Planner reused stored claim fact and resolved the missing-city branch.".to_string();
142        outcome.agent_id = Some("planner".to_string());
143        let outcome_response = client.record_outcome(outcome).await?;
144
145        let mut strategies = SurfaceStrategiesOptions::default();
146        strategies.run_id = Some(run_id.clone());
147        strategies.lesson_types = vec!["success".to_string(), "rule".to_string()];
148        strategies.max_strategies = 5;
149        let strategies_response = client.surface_strategies(strategies).await?;
150
151        let mut handoff = HandoffOptions::new(
152            "claim-1",
153            "planner",
154            "reviewer",
155            "Review whether the stored claimant city is sufficient for routing.",
156        );
157        handoff.run_id = Some(run_id.clone());
158        handoff.requested_action = "review".to_string();
159        handoff.metadata = Some(json!({"team": "claims"}));
160        let handoff_response = client.handoff(handoff).await?;
161        let handoff_id = handoff_response
162            .get("handoff_id")
163            .and_then(Value::as_str)
164            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
165            .to_string();
166
167        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
168        feedback.run_id = Some(run_id.clone());
169        feedback.comments = "Stored fact is sufficient; proceed without escalation.".to_string();
170        feedback.from_agent_id = Some("reviewer".to_string());
171        feedback.metadata = Some(json!({"team": "claims"}));
172        let feedback_response = client.feedback(feedback).await?;
173
174        require(remember_response.get("job_id").is_some() || remember_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("remember failed: {remember_response}"))?;
175        require(mental_model_response.get("job_id").is_some() || mental_model_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("mental_model remember failed: {mental_model_response}"))?;
176        require(lesson_response.get("job_id").is_some() || lesson_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("lesson remember failed: {lesson_response}"))?;
177        require(recall_response.get("final_answer").is_some() || recall_response.get("evidence").is_some(), format!("recall failed: {recall_response}"))?;
178        require(context_response.get("sources").and_then(Value::as_array).is_some(), format!("context malformed: {context_response}"))?;
179        require(health_response.get("entry_counts").and_then(Value::as_object).is_some(), format!("memory_health malformed: {health_response}"))?;
180        require(diagnose_response.get("failure_lessons").and_then(Value::as_array).is_some(), format!("diagnose malformed: {diagnose_response}"))?;
181        require(reflect_response.get("lessons").and_then(Value::as_array).is_some(), format!("reflect malformed: {reflect_response}"))?;
182        require(register_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("register_agent failed: {register_response}"))?;
183        require(agents_response.get("agents").and_then(Value::as_array).map(|items| !items.is_empty()).unwrap_or(false), format!("list_agents failed: {agents_response}"))?;
184        require(archive_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("archive failed: {archive_response}"))?;
185        require(dereference_response.get("found").and_then(Value::as_bool).unwrap_or(false), format!("dereference failed: {dereference_response}"))?;
186        require(checkpoint_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
187        require(outcome_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("record_outcome failed: {outcome_response}"))?;
188        require(strategies_response.get("strategies").and_then(Value::as_array).is_some(), format!("surface_strategies malformed: {strategies_response}"))?;
189        require(handoff_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
190        require(feedback_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
191
192        let strategy_count = strategies_response
193            .get("strategies")
194            .and_then(Value::as_array)
195            .map(|items| items.len())
196            .unwrap_or(0);
197        let agent_count = agents_response
198            .get("agents")
199            .and_then(Value::as_array)
200            .map(|items| items.len())
201            .unwrap_or(0);
202        let lesson_count = lessons_response
203            .get("lessons")
204            .and_then(Value::as_array)
205            .map(|items| items.len())
206            .unwrap_or(0);
207
208        metrics = json!({
209            "run_id": run_id,
210            "agent_count": agent_count,
211            "strategy_count": strategy_count,
212            "reference_id": reference_id,
213            "lesson_count": lesson_count,
214        });
215
216        Ok::<(), Box<dyn Error>>(())
217    }
218    .await;
219
220    if let Err(err) = scenario {
221        passed = false;
222        detail = err.to_string();
223    }
224
225    let cleanup_ok = cleanup_run(&client, &run_id).await;
226    if !cleanup_ok {
227        passed = false;
228        detail = format!("{detail} | cleanup failures");
229    }
230
231    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
232
233    if passed { Ok(()) } else { Err(boxed_error(detail)) }
234}
examples/helper_all_helpers.rs (line 131)
16async fn main() -> Result<(), Box<dyn Error>> {
17    let name = "helper_all_helpers";
18    let started = Instant::now();
19    let client = create_client().await?;
20    let run_id = new_run_id("helper_all_helpers");
21    client.set_run_id(Some(run_id.clone()));
22    client.set_transport(TransportMode::Http);
23
24    let mut passed = true;
25    let mut detail = "validated all helper flows".to_string();
26    let mut metrics = json!({});
27
28    let scenario = async {
29        let mut remember = RememberOptions::new("Policy limit is 5000 and claimant city is Leeds.");
30        remember.run_id = Some(run_id.clone());
31        remember.agent_id = Some("planner".to_string());
32        remember.intent = Some("fact".to_string());
33        remember.metadata = Some(json!({"suite": "all-helpers", "family": "claims"}));
34        remember.importance = Some("high".to_string());
35        let remember_response = client.remember(remember).await?;
36
37        let mut lesson = RememberOptions::new("If city is missing from the latest step, check stored claim facts before escalating.");
38        lesson.run_id = Some(run_id.clone());
39        lesson.agent_id = Some("planner".to_string());
40        lesson.intent = Some("lesson".to_string());
41        lesson.lesson_type = Some("success".to_string());
42        lesson.lesson_scope = Some("session".to_string());
43        lesson.lesson_importance = Some("high".to_string());
44        let lesson_response = client.remember(lesson).await?;
45
46        let mut recall = RecallOptions::new("What is the policy limit?");
47        recall.run_id = Some(run_id.clone());
48        recall.agent_id = Some("planner".to_string());
49        recall.limit = 5;
50        let recall_response = client.recall(recall).await?;
51
52        let mut context = GetContextOptions::default();
53        context.run_id = Some(run_id.clone());
54        context.query = Some("Prepare a short adjuster summary".to_string());
55        context.agent_id = Some("planner".to_string());
56        context.limit = Some(6);
57        context.max_token_budget = Some(700);
58        let context_response = client.get_context(context).await?;
59
60        let mut health = MemoryHealthOptions::default();
61        health.run_id = Some(run_id.clone());
62        health.limit = 50;
63        let health_response = client.memory_health(health).await?;
64
65        let mut diagnose = DiagnoseOptions::new("policy limit lookup returned empty");
66        diagnose.run_id = Some(run_id.clone());
67        diagnose.error_type = Some("retrieval".to_string());
68        diagnose.limit = 5;
69        let diagnose_response = client.diagnose(diagnose).await?;
70
71        let mut reflect = ReflectOptions::default();
72        reflect.run_id = Some(run_id.clone());
73        let reflect_response = client.reflect(reflect).await?;
74
75        let mut register = RegisterAgentOptions::new("planner");
76        register.run_id = Some(run_id.clone());
77        register.role = "planner".to_string();
78        register.read_scopes = vec!["fact".into(), "lesson".into(), "rule".into(), "archive_block".into(), "handoff".into(), "feedback".into()];
79        register.write_scopes = vec!["fact".into(), "trace".into(), "lesson".into(), "observation".into(), "archive_block".into()];
80        register.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
81        let register_response = client.register_agent(register).await?;
82
83        let mut list_agents = ListAgentsOptions::default();
84        list_agents.run_id = Some(run_id.clone());
85        let agents_response = client.list_agents(list_agents).await?;
86
87        let mut archive = ArchiveOptions::new(
88            "Exact adjuster note: claimant confirmed city is Leeds during triage.",
89            "adjuster_note",
90        );
91        archive.run_id = Some(run_id.clone());
92        archive.agent_id = Some("planner".to_string());
93        archive.origin_agent_id = Some("planner".to_string());
94        archive.source_attempt_id = Some("attempt-1".to_string());
95        archive.source_tool = Some("phone_call".to_string());
96        archive.labels = vec!["claims".to_string(), "triage".to_string()];
97        archive.family = Some("claims-adjustment".to_string());
98        archive.metadata = Some(json!({"case": "all-helpers"}));
99        let archive_response = client.archive(archive).await?;
100        let reference_id = archive_response
101            .get("reference_id")
102            .and_then(Value::as_str)
103            .ok_or_else(|| boxed_error(format!("archive reference missing: {archive_response}")))?
104            .to_string();
105
106        let mut dereference = DereferenceOptions::new(reference_id.clone());
107        dereference.run_id = Some(run_id.clone());
108        dereference.agent_id = Some("planner".to_string());
109        let dereference_response = client.dereference(dereference).await?;
110
111        let mut checkpoint = CheckpointOptions::new("Planner captured claim facts before window compaction.");
112        checkpoint.run_id = Some(run_id.clone());
113        checkpoint.label = Some("pre-compaction".to_string());
114        checkpoint.metadata = Some(json!({"stage": "analysis"}));
115        checkpoint.agent_id = Some("planner".to_string());
116        let checkpoint_response = client.checkpoint(checkpoint).await?;
117
118        let lessons_response = client.control.lessons(json!({"run_id": run_id, "limit": 20})).await?;
119        let lesson_id = lessons_response
120            .get("lessons")
121            .and_then(Value::as_array)
122            .and_then(|items| items.iter().find_map(|item| item.get("id").and_then(Value::as_str)))
123            .ok_or_else(|| boxed_error(format!("expected lesson id for outcome flow: {lessons_response}")))?
124            .to_string();
125
126        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
127        outcome.run_id = Some(run_id.clone());
128        outcome.signal = 0.75;
129        outcome.rationale = "Planner reused stored claim fact and resolved the missing-city branch.".to_string();
130        outcome.agent_id = Some("planner".to_string());
131        let outcome_response = client.record_outcome(outcome).await?;
132
133        let mut strategies = SurfaceStrategiesOptions::default();
134        strategies.run_id = Some(run_id.clone());
135        strategies.lesson_types = vec!["success".to_string(), "rule".to_string()];
136        strategies.max_strategies = 5;
137        let strategies_response = client.surface_strategies(strategies).await?;
138
139        let mut handoff = HandoffOptions::new(
140            "claim-1",
141            "planner",
142            "reviewer",
143            "Review whether the stored claimant city is sufficient for routing.",
144        );
145        handoff.run_id = Some(run_id.clone());
146        handoff.requested_action = "review".to_string();
147        handoff.metadata = Some(json!({"team": "claims"}));
148        let handoff_response = client.handoff(handoff).await?;
149        let handoff_id = handoff_response
150            .get("handoff_id")
151            .and_then(Value::as_str)
152            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
153            .to_string();
154
155        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
156        feedback.run_id = Some(run_id.clone());
157        feedback.comments = "Stored fact is sufficient; proceed without escalation.".to_string();
158        feedback.from_agent_id = Some("reviewer".to_string());
159        feedback.metadata = Some(json!({"team": "claims"}));
160        let feedback_response = client.feedback(feedback).await?;
161
162        let scratch_run = format!("{run_id}_forget");
163        let mut scratch = RememberOptions::new("Scratch run for forget helper coverage.");
164        scratch.run_id = Some(scratch_run.clone());
165        scratch.agent_id = Some("planner".to_string());
166        scratch.intent = Some("fact".to_string());
167        scratch.metadata = Some(json!({"suite": "all-helpers", "temporary": true}));
168        let scratch_response = client.remember(scratch).await?;
169
170        let forget_response = client
171            .forget(ForgetOptions::for_run(scratch_run.clone()))
172            .await?;
173
174        let mut forgotten = RecallOptions::new("What temporary scratch fact exists?");
175        forgotten.run_id = Some(scratch_run.clone());
176        forgotten.limit = 3;
177        let forgotten_response = client.recall(forgotten).await?;
178
179        require(remember_response.get("job_id").is_some() || remember_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("remember failed: {remember_response}"))?;
180        require(lesson_response.get("job_id").is_some() || lesson_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("lesson remember failed: {lesson_response}"))?;
181        require(recall_response.get("final_answer").is_some() || recall_response.get("evidence").is_some(), format!("recall failed: {recall_response}"))?;
182        require(context_response.get("sources").and_then(Value::as_array).is_some(), format!("context malformed: {context_response}"))?;
183        require(health_response.get("entry_counts").and_then(Value::as_object).is_some(), format!("memory_health malformed: {health_response}"))?;
184        require(diagnose_response.get("failure_lessons").and_then(Value::as_array).is_some(), format!("diagnose malformed: {diagnose_response}"))?;
185        require(reflect_response.get("lessons").and_then(Value::as_array).is_some(), format!("reflect malformed: {reflect_response}"))?;
186        require(register_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("register_agent failed: {register_response}"))?;
187        require(agents_response.get("agents").and_then(Value::as_array).map(|items| !items.is_empty()).unwrap_or(false), format!("list_agents failed: {agents_response}"))?;
188        require(archive_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("archive failed: {archive_response}"))?;
189        require(dereference_response.get("found").and_then(Value::as_bool).unwrap_or(false), format!("dereference failed: {dereference_response}"))?;
190        require(checkpoint_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
191        require(outcome_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("record_outcome failed: {outcome_response}"))?;
192        require(strategies_response.get("strategies").and_then(Value::as_array).is_some(), format!("surface_strategies malformed: {strategies_response}"))?;
193        require(handoff_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
194        require(feedback_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
195        require(scratch_response.get("job_id").is_some() || scratch_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("scratch remember failed: {scratch_response}"))?;
196        require(forget_response.get("success").and_then(Value::as_bool).unwrap_or(true), format!("forget failed: {forget_response}"))?;
197        let scratch_fact_visible = forgotten_response
198            .get("evidence")
199            .and_then(Value::as_array)
200            .map(|items| {
201                items.iter().any(|item| {
202                    item.get("run_id").and_then(Value::as_str) == Some(scratch_run.as_str())
203                        || item
204                            .get("content")
205                            .and_then(Value::as_str)
206                            .map(|content| {
207                                content
208                                    .to_ascii_lowercase()
209                                    .contains("scratch run for forget helper coverage")
210                            })
211                            .unwrap_or(false)
212                })
213            })
214            .unwrap_or(false);
215        require(!scratch_fact_visible, format!("scratch fact should be forgotten even if same-user lessons still surface: {forgotten_response}"))?;
216
217        let strategy_count = strategies_response
218            .get("strategies")
219            .and_then(Value::as_array)
220            .map(|items| items.len())
221            .unwrap_or(0);
222        let agent_count = agents_response
223            .get("agents")
224            .and_then(Value::as_array)
225            .map(|items| items.len())
226            .unwrap_or(0);
227        let lesson_count = lessons_response
228            .get("lessons")
229            .and_then(Value::as_array)
230            .map(|items| items.len())
231            .unwrap_or(0);
232
233        metrics = json!({
234            "run_id": run_id,
235            "agent_count": agent_count,
236            "strategy_count": strategy_count,
237            "reference_id": reference_id,
238            "lesson_count": lesson_count,
239            "forgotten_run": scratch_run,
240        });
241
242        Ok::<(), Box<dyn Error>>(())
243    }
244    .await;
245
246    if let Err(err) = scenario {
247        passed = false;
248        detail = err.to_string();
249    }
250
251    let cleanup_ok = cleanup_run(&client, &run_id).await;
252    if !cleanup_ok {
253        passed = false;
254        detail = format!("{detail} | cleanup failures");
255    }
256
257    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
258
259    if passed { Ok(()) } else { Err(boxed_error(detail)) }
260}
Source

pub async fn record_step_outcome( &self, options: RecordStepOutcomeOptions, ) -> Result<Value>

Source

pub async fn surface_strategies( &self, options: SurfaceStrategiesOptions, ) -> Result<Value>

Examples found in repository?
examples/helper_mas_learning_loop.rs (line 80)
14async fn main() -> Result<(), Box<dyn Error>> {
15    let name = "helper_mas_learning_loop";
16    let started = Instant::now();
17    let client = create_client().await?;
18    let run_id = new_run_id("helper_mas_learning_loop");
19    client.set_run_id(Some(run_id.clone()));
20    client.set_transport(TransportMode::Http);
21
22    let mut passed = true;
23    let mut detail = "validated helper MAS checkpoint/outcome/strategies flow".to_string();
24    let mut metrics = json!({});
25
26    let scenario = async {
27        let mut register = RegisterAgentOptions::new("planner");
28        register.run_id = Some(run_id.clone());
29        register.role = "planner".to_string();
30        register.read_scopes = vec!["rule".to_string(), "lesson".to_string(), "fact".to_string()];
31        register.write_scopes = vec!["lesson".to_string(), "trace".to_string()];
32        register.shared_memory_lanes = vec!["knowledge".to_string(), "history".to_string()];
33        client.register_agent(register).await?;
34
35        let mut remember = RememberOptions::new(
36            "If a retry succeeds after token signer rotation, record it as a reusable recovery pattern.",
37        );
38        remember.run_id = Some(run_id.clone());
39        remember.agent_id = Some("planner".to_string());
40        remember.intent = Some("lesson".to_string());
41        remember.lesson_type = Some("success".to_string());
42        remember.lesson_scope = Some("session".to_string());
43        remember.lesson_importance = Some("high".to_string());
44        client.remember(remember).await?;
45
46        let mut checkpoint = CheckpointOptions::new(
47            "Planner isolated the recovery path to token signer rotation.",
48        );
49        checkpoint.run_id = Some(run_id.clone());
50        checkpoint.label = Some("pre-compaction-1".to_string());
51        checkpoint.metadata = Some(json!({ "stage": "analysis" }));
52        checkpoint.agent_id = Some("planner".to_string());
53        let checkpoint_response = client.checkpoint(checkpoint).await?;
54
55        let mut list_agents = ListAgentsOptions::default();
56        list_agents.run_id = Some(run_id.clone());
57        let agents = client.list_agents(list_agents).await?;
58
59        let lessons = client.control.lessons(json!({ "run_id": run_id, "limit": 10 })).await?;
60        let lesson_id = lessons
61            .get("lessons")
62            .and_then(|value| value.as_array())
63            .and_then(|items| items.first())
64            .and_then(|item| item.get("id"))
65            .and_then(|value| value.as_str())
66            .ok_or_else(|| boxed_error(format!("expected at least one lesson to record outcome against: {lessons}")))?
67            .to_string();
68
69        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
70        outcome.run_id = Some(run_id.clone());
71        outcome.signal = 0.75;
72        outcome.rationale = "Recovery succeeded after following the stored lesson.".to_string();
73        outcome.agent_id = Some("planner".to_string());
74        let outcome_response = client.record_outcome(outcome).await?;
75
76        let mut strategies = SurfaceStrategiesOptions::default();
77        strategies.run_id = Some(run_id.clone());
78        strategies.lesson_types = vec!["success".to_string(), "failure".to_string()];
79        strategies.max_strategies = 5;
80        let strategy_response = client.surface_strategies(strategies).await?;
81
82        require(
83            checkpoint_response
84                .get("success")
85                .and_then(|value| value.as_bool())
86                .unwrap_or(false),
87            format!("checkpoint failed: {checkpoint_response}"),
88        )?;
89        let agent_count = agents
90            .get("agents")
91            .and_then(|value| value.as_array())
92            .map(|items| items.len())
93            .unwrap_or(0);
94        require(agent_count == 1, format!("agent registration missing: {agents}"))?;
95        require(
96            outcome_response
97                .get("success")
98                .and_then(|value| value.as_bool())
99                .unwrap_or(false),
100            format!("record_outcome failed: {outcome_response}"),
101        )?;
102        let strategy_count = strategy_response
103            .get("strategies")
104            .and_then(|value| value.as_array())
105            .map(|items| items.len())
106            .unwrap_or(0);
107
108        metrics = json!({
109            "run_id": run_id,
110            "checkpoint_id": checkpoint_response.get("checkpoint_id").cloned().unwrap_or(serde_json::Value::Null),
111            "agent_count": agent_count,
112            "strategy_count": strategy_count,
113        });
114
115        Ok::<(), Box<dyn Error>>(())
116    }
117    .await;
118
119    if let Err(err) = scenario {
120        passed = false;
121        detail = err.to_string();
122    }
123
124    let cleanup_ok = cleanup_run(&client, &run_id).await;
125    if !cleanup_ok {
126        passed = false;
127        detail = format!("{detail} | cleanup failures");
128    }
129
130    print_summary(
131        name,
132        passed,
133        &detail,
134        &metrics,
135        started.elapsed().as_secs_f64(),
136        cleanup_ok,
137    );
138
139    if passed {
140        Ok(())
141    } else {
142        Err(boxed_error(detail))
143    }
144}
More examples
Hide additional examples
examples/public/03_checkpoint_reflect_outcome.rs (line 80)
14async fn main() -> Result<(), Box<dyn Error>> {
15    let name = "public_03_checkpoint_reflect_outcome";
16    let started = Instant::now();
17    let client = create_client().await?;
18    let run_id = new_run_id("public_03_checkpoint_reflect_outcome");
19    client.set_run_id(Some(run_id.clone()));
20    client.set_transport(TransportMode::Http);
21
22    let mut passed = true;
23    let mut detail = "validated helper MAS checkpoint/outcome/strategies flow".to_string();
24    let mut metrics = json!({});
25
26    let scenario = async {
27        let mut register = RegisterAgentOptions::new("planner");
28        register.run_id = Some(run_id.clone());
29        register.role = "planner".to_string();
30        register.read_scopes = vec!["rule".to_string(), "lesson".to_string(), "fact".to_string()];
31        register.write_scopes = vec!["lesson".to_string(), "trace".to_string()];
32        register.shared_memory_lanes = vec!["knowledge".to_string(), "history".to_string()];
33        client.register_agent(register).await?;
34
35        let mut remember = RememberOptions::new(
36            "If a retry succeeds after token signer rotation, record it as a reusable recovery pattern.",
37        );
38        remember.run_id = Some(run_id.clone());
39        remember.agent_id = Some("planner".to_string());
40        remember.intent = Some("lesson".to_string());
41        remember.lesson_type = Some("success".to_string());
42        remember.lesson_scope = Some("session".to_string());
43        remember.lesson_importance = Some("high".to_string());
44        client.remember(remember).await?;
45
46        let mut checkpoint = CheckpointOptions::new(
47            "Planner isolated the recovery path to token signer rotation.",
48        );
49        checkpoint.run_id = Some(run_id.clone());
50        checkpoint.label = Some("pre-compaction-1".to_string());
51        checkpoint.metadata = Some(json!({ "stage": "analysis" }));
52        checkpoint.agent_id = Some("planner".to_string());
53        let checkpoint_response = client.checkpoint(checkpoint).await?;
54
55        let mut list_agents = ListAgentsOptions::default();
56        list_agents.run_id = Some(run_id.clone());
57        let agents = client.list_agents(list_agents).await?;
58
59        let lessons = client.control.lessons(json!({ "run_id": run_id, "limit": 10 })).await?;
60        let lesson_id = lessons
61            .get("lessons")
62            .and_then(|value| value.as_array())
63            .and_then(|items| items.first())
64            .and_then(|item| item.get("id"))
65            .and_then(|value| value.as_str())
66            .ok_or_else(|| boxed_error(format!("expected at least one lesson to record outcome against: {lessons}")))?
67            .to_string();
68
69        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
70        outcome.run_id = Some(run_id.clone());
71        outcome.signal = 0.75;
72        outcome.rationale = "Recovery succeeded after following the stored lesson.".to_string();
73        outcome.agent_id = Some("planner".to_string());
74        let outcome_response = client.record_outcome(outcome).await?;
75
76        let mut strategies = SurfaceStrategiesOptions::default();
77        strategies.run_id = Some(run_id.clone());
78        strategies.lesson_types = vec!["success".to_string(), "failure".to_string()];
79        strategies.max_strategies = 5;
80        let strategy_response = client.surface_strategies(strategies).await?;
81
82        require(
83            checkpoint_response
84                .get("success")
85                .and_then(|value| value.as_bool())
86                .unwrap_or(false),
87            format!("checkpoint failed: {checkpoint_response}"),
88        )?;
89        let agent_count = agents
90            .get("agents")
91            .and_then(|value| value.as_array())
92            .map(|items| items.len())
93            .unwrap_or(0);
94        require(agent_count == 1, format!("agent registration missing: {agents}"))?;
95        require(
96            outcome_response
97                .get("success")
98                .and_then(|value| value.as_bool())
99                .unwrap_or(false),
100            format!("record_outcome failed: {outcome_response}"),
101        )?;
102        let strategy_count = strategy_response
103            .get("strategies")
104            .and_then(|value| value.as_array())
105            .map(|items| items.len())
106            .unwrap_or(0);
107
108        metrics = json!({
109            "run_id": run_id,
110            "checkpoint_id": checkpoint_response.get("checkpoint_id").cloned().unwrap_or(serde_json::Value::Null),
111            "agent_count": agent_count,
112            "strategy_count": strategy_count,
113        });
114
115        Ok::<(), Box<dyn Error>>(())
116    }
117    .await;
118
119    if let Err(err) = scenario {
120        passed = false;
121        detail = err.to_string();
122    }
123
124    let cleanup_ok = cleanup_run(&client, &run_id).await;
125    if !cleanup_ok {
126        passed = false;
127        detail = format!("{detail} | cleanup failures");
128    }
129
130    print_summary(
131        name,
132        passed,
133        &detail,
134        &metrics,
135        started.elapsed().as_secs_f64(),
136        cleanup_ok,
137    );
138
139    if passed {
140        Ok(())
141    } else {
142        Err(boxed_error(detail))
143    }
144}
examples/public/10_full_learning_loop_smoke.rs (line 149)
16async fn main() -> Result<(), Box<dyn Error>> {
17    let name = "public_10_full_learning_loop_smoke";
18    let started = Instant::now();
19    let client = create_client().await?;
20    let run_id = new_run_id("public_10_full_learning_loop_smoke");
21    client.set_run_id(Some(run_id.clone()));
22    client.set_transport(TransportMode::Http);
23
24    let mut passed = true;
25    let mut detail = "validated all helper flows".to_string();
26    let mut metrics = json!({});
27
28    let scenario = async {
29        let mut remember = RememberOptions::new("Policy limit is 5000 and claimant city is Leeds.");
30        remember.run_id = Some(run_id.clone());
31        remember.agent_id = Some("planner".to_string());
32        remember.intent = Some("fact".to_string());
33        remember.metadata = Some(json!({"suite": "all-helpers", "family": "claims"}));
34        remember.importance = Some("high".to_string());
35        remember.occurrence_time = Some(std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as i64 - 86400);
36        let remember_response = client.remember(remember).await?;
37
38        let mut lesson = RememberOptions::new("If city is missing from the latest step, check stored claim facts before escalating.");
39        lesson.run_id = Some(run_id.clone());
40        lesson.agent_id = Some("planner".to_string());
41        lesson.intent = Some("lesson".to_string());
42        lesson.lesson_type = Some("success".to_string());
43        lesson.lesson_scope = Some("session".to_string());
44        lesson.lesson_importance = Some("high".to_string());
45        let lesson_response = client.remember(lesson).await?;
46
47        let mut mental_model = RememberOptions::new(
48            "Claims case overview: Policy limit 5000 GBP, claimant city Leeds, \
49             missing-city branch resolved via stored claim facts. Lesson: check stored facts before escalating.",
50        );
51        mental_model.run_id = Some(run_id.clone());
52        mental_model.agent_id = Some("planner".to_string());
53        mental_model.intent = Some("mental_model".to_string());
54        mental_model.importance = Some("critical".to_string());
55        mental_model.metadata = Some(json!({"suite": "all-helpers", "entity": "claims-case", "consolidated": true}));
56        let mental_model_response = client.remember(mental_model).await?;
57
58        let mut recall = RecallOptions::new("What is the policy limit?");
59        recall.run_id = Some(run_id.clone());
60        recall.agent_id = Some("planner".to_string());
61        recall.limit = 5;
62        let recall_response = client.recall(recall).await?;
63
64        let mut context = GetContextOptions::default();
65        context.run_id = Some(run_id.clone());
66        context.query = Some("Prepare a short adjuster summary".to_string());
67        context.agent_id = Some("planner".to_string());
68        context.limit = Some(6);
69        context.max_token_budget = Some(700);
70        let context_response = client.get_context(context).await?;
71
72        let mut health = MemoryHealthOptions::default();
73        health.run_id = Some(run_id.clone());
74        health.limit = 50;
75        let health_response = client.memory_health(health).await?;
76
77        let mut diagnose = DiagnoseOptions::new("policy limit lookup returned empty");
78        diagnose.run_id = Some(run_id.clone());
79        diagnose.error_type = Some("retrieval".to_string());
80        diagnose.limit = 5;
81        let diagnose_response = client.diagnose(diagnose).await?;
82
83        let mut reflect = ReflectOptions::default();
84        reflect.run_id = Some(run_id.clone());
85        let reflect_response = client.reflect(reflect).await?;
86
87        let mut register = RegisterAgentOptions::new("planner");
88        register.run_id = Some(run_id.clone());
89        register.role = "planner".to_string();
90        register.read_scopes = vec!["fact".into(), "lesson".into(), "rule".into(), "mental_model".into(), "archive_block".into(), "handoff".into(), "feedback".into()];
91        register.write_scopes = vec!["fact".into(), "trace".into(), "lesson".into(), "observation".into(), "archive_block".into()];
92        register.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
93        let register_response = client.register_agent(register).await?;
94
95        let mut list_agents = ListAgentsOptions::default();
96        list_agents.run_id = Some(run_id.clone());
97        let agents_response = client.list_agents(list_agents).await?;
98
99        let mut archive = ArchiveOptions::new(
100            "Exact adjuster note: claimant confirmed city is Leeds during triage.",
101            "adjuster_note",
102        );
103        archive.run_id = Some(run_id.clone());
104        archive.agent_id = Some("planner".to_string());
105        archive.origin_agent_id = Some("planner".to_string());
106        archive.source_attempt_id = Some("attempt-1".to_string());
107        archive.source_tool = Some("phone_call".to_string());
108        archive.labels = vec!["claims".to_string(), "triage".to_string()];
109        archive.family = Some("claims-adjustment".to_string());
110        archive.metadata = Some(json!({"case": "all-helpers"}));
111        let archive_response = client.archive(archive).await?;
112        let reference_id = archive_response
113            .get("reference_id")
114            .and_then(Value::as_str)
115            .ok_or_else(|| boxed_error(format!("archive reference missing: {archive_response}")))?
116            .to_string();
117
118        let mut dereference = DereferenceOptions::new(reference_id.clone());
119        dereference.run_id = Some(run_id.clone());
120        dereference.agent_id = Some("planner".to_string());
121        let dereference_response = client.dereference(dereference).await?;
122
123        let mut checkpoint = CheckpointOptions::new("Planner captured claim facts before window compaction.");
124        checkpoint.run_id = Some(run_id.clone());
125        checkpoint.label = Some("pre-compaction".to_string());
126        checkpoint.metadata = Some(json!({"stage": "analysis"}));
127        checkpoint.agent_id = Some("planner".to_string());
128        let checkpoint_response = client.checkpoint(checkpoint).await?;
129
130        let lessons_response = client.control.lessons(json!({"run_id": run_id, "limit": 20})).await?;
131        let lesson_id = lessons_response
132            .get("lessons")
133            .and_then(Value::as_array)
134            .and_then(|items| items.iter().find_map(|item| item.get("id").and_then(Value::as_str)))
135            .ok_or_else(|| boxed_error(format!("expected lesson id for outcome flow: {lessons_response}")))?
136            .to_string();
137
138        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
139        outcome.run_id = Some(run_id.clone());
140        outcome.signal = 0.75;
141        outcome.rationale = "Planner reused stored claim fact and resolved the missing-city branch.".to_string();
142        outcome.agent_id = Some("planner".to_string());
143        let outcome_response = client.record_outcome(outcome).await?;
144
145        let mut strategies = SurfaceStrategiesOptions::default();
146        strategies.run_id = Some(run_id.clone());
147        strategies.lesson_types = vec!["success".to_string(), "rule".to_string()];
148        strategies.max_strategies = 5;
149        let strategies_response = client.surface_strategies(strategies).await?;
150
151        let mut handoff = HandoffOptions::new(
152            "claim-1",
153            "planner",
154            "reviewer",
155            "Review whether the stored claimant city is sufficient for routing.",
156        );
157        handoff.run_id = Some(run_id.clone());
158        handoff.requested_action = "review".to_string();
159        handoff.metadata = Some(json!({"team": "claims"}));
160        let handoff_response = client.handoff(handoff).await?;
161        let handoff_id = handoff_response
162            .get("handoff_id")
163            .and_then(Value::as_str)
164            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
165            .to_string();
166
167        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
168        feedback.run_id = Some(run_id.clone());
169        feedback.comments = "Stored fact is sufficient; proceed without escalation.".to_string();
170        feedback.from_agent_id = Some("reviewer".to_string());
171        feedback.metadata = Some(json!({"team": "claims"}));
172        let feedback_response = client.feedback(feedback).await?;
173
174        require(remember_response.get("job_id").is_some() || remember_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("remember failed: {remember_response}"))?;
175        require(mental_model_response.get("job_id").is_some() || mental_model_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("mental_model remember failed: {mental_model_response}"))?;
176        require(lesson_response.get("job_id").is_some() || lesson_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("lesson remember failed: {lesson_response}"))?;
177        require(recall_response.get("final_answer").is_some() || recall_response.get("evidence").is_some(), format!("recall failed: {recall_response}"))?;
178        require(context_response.get("sources").and_then(Value::as_array).is_some(), format!("context malformed: {context_response}"))?;
179        require(health_response.get("entry_counts").and_then(Value::as_object).is_some(), format!("memory_health malformed: {health_response}"))?;
180        require(diagnose_response.get("failure_lessons").and_then(Value::as_array).is_some(), format!("diagnose malformed: {diagnose_response}"))?;
181        require(reflect_response.get("lessons").and_then(Value::as_array).is_some(), format!("reflect malformed: {reflect_response}"))?;
182        require(register_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("register_agent failed: {register_response}"))?;
183        require(agents_response.get("agents").and_then(Value::as_array).map(|items| !items.is_empty()).unwrap_or(false), format!("list_agents failed: {agents_response}"))?;
184        require(archive_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("archive failed: {archive_response}"))?;
185        require(dereference_response.get("found").and_then(Value::as_bool).unwrap_or(false), format!("dereference failed: {dereference_response}"))?;
186        require(checkpoint_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
187        require(outcome_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("record_outcome failed: {outcome_response}"))?;
188        require(strategies_response.get("strategies").and_then(Value::as_array).is_some(), format!("surface_strategies malformed: {strategies_response}"))?;
189        require(handoff_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
190        require(feedback_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
191
192        let strategy_count = strategies_response
193            .get("strategies")
194            .and_then(Value::as_array)
195            .map(|items| items.len())
196            .unwrap_or(0);
197        let agent_count = agents_response
198            .get("agents")
199            .and_then(Value::as_array)
200            .map(|items| items.len())
201            .unwrap_or(0);
202        let lesson_count = lessons_response
203            .get("lessons")
204            .and_then(Value::as_array)
205            .map(|items| items.len())
206            .unwrap_or(0);
207
208        metrics = json!({
209            "run_id": run_id,
210            "agent_count": agent_count,
211            "strategy_count": strategy_count,
212            "reference_id": reference_id,
213            "lesson_count": lesson_count,
214        });
215
216        Ok::<(), Box<dyn Error>>(())
217    }
218    .await;
219
220    if let Err(err) = scenario {
221        passed = false;
222        detail = err.to_string();
223    }
224
225    let cleanup_ok = cleanup_run(&client, &run_id).await;
226    if !cleanup_ok {
227        passed = false;
228        detail = format!("{detail} | cleanup failures");
229    }
230
231    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
232
233    if passed { Ok(()) } else { Err(boxed_error(detail)) }
234}
examples/helper_all_helpers.rs (line 137)
16async fn main() -> Result<(), Box<dyn Error>> {
17    let name = "helper_all_helpers";
18    let started = Instant::now();
19    let client = create_client().await?;
20    let run_id = new_run_id("helper_all_helpers");
21    client.set_run_id(Some(run_id.clone()));
22    client.set_transport(TransportMode::Http);
23
24    let mut passed = true;
25    let mut detail = "validated all helper flows".to_string();
26    let mut metrics = json!({});
27
28    let scenario = async {
29        let mut remember = RememberOptions::new("Policy limit is 5000 and claimant city is Leeds.");
30        remember.run_id = Some(run_id.clone());
31        remember.agent_id = Some("planner".to_string());
32        remember.intent = Some("fact".to_string());
33        remember.metadata = Some(json!({"suite": "all-helpers", "family": "claims"}));
34        remember.importance = Some("high".to_string());
35        let remember_response = client.remember(remember).await?;
36
37        let mut lesson = RememberOptions::new("If city is missing from the latest step, check stored claim facts before escalating.");
38        lesson.run_id = Some(run_id.clone());
39        lesson.agent_id = Some("planner".to_string());
40        lesson.intent = Some("lesson".to_string());
41        lesson.lesson_type = Some("success".to_string());
42        lesson.lesson_scope = Some("session".to_string());
43        lesson.lesson_importance = Some("high".to_string());
44        let lesson_response = client.remember(lesson).await?;
45
46        let mut recall = RecallOptions::new("What is the policy limit?");
47        recall.run_id = Some(run_id.clone());
48        recall.agent_id = Some("planner".to_string());
49        recall.limit = 5;
50        let recall_response = client.recall(recall).await?;
51
52        let mut context = GetContextOptions::default();
53        context.run_id = Some(run_id.clone());
54        context.query = Some("Prepare a short adjuster summary".to_string());
55        context.agent_id = Some("planner".to_string());
56        context.limit = Some(6);
57        context.max_token_budget = Some(700);
58        let context_response = client.get_context(context).await?;
59
60        let mut health = MemoryHealthOptions::default();
61        health.run_id = Some(run_id.clone());
62        health.limit = 50;
63        let health_response = client.memory_health(health).await?;
64
65        let mut diagnose = DiagnoseOptions::new("policy limit lookup returned empty");
66        diagnose.run_id = Some(run_id.clone());
67        diagnose.error_type = Some("retrieval".to_string());
68        diagnose.limit = 5;
69        let diagnose_response = client.diagnose(diagnose).await?;
70
71        let mut reflect = ReflectOptions::default();
72        reflect.run_id = Some(run_id.clone());
73        let reflect_response = client.reflect(reflect).await?;
74
75        let mut register = RegisterAgentOptions::new("planner");
76        register.run_id = Some(run_id.clone());
77        register.role = "planner".to_string();
78        register.read_scopes = vec!["fact".into(), "lesson".into(), "rule".into(), "archive_block".into(), "handoff".into(), "feedback".into()];
79        register.write_scopes = vec!["fact".into(), "trace".into(), "lesson".into(), "observation".into(), "archive_block".into()];
80        register.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
81        let register_response = client.register_agent(register).await?;
82
83        let mut list_agents = ListAgentsOptions::default();
84        list_agents.run_id = Some(run_id.clone());
85        let agents_response = client.list_agents(list_agents).await?;
86
87        let mut archive = ArchiveOptions::new(
88            "Exact adjuster note: claimant confirmed city is Leeds during triage.",
89            "adjuster_note",
90        );
91        archive.run_id = Some(run_id.clone());
92        archive.agent_id = Some("planner".to_string());
93        archive.origin_agent_id = Some("planner".to_string());
94        archive.source_attempt_id = Some("attempt-1".to_string());
95        archive.source_tool = Some("phone_call".to_string());
96        archive.labels = vec!["claims".to_string(), "triage".to_string()];
97        archive.family = Some("claims-adjustment".to_string());
98        archive.metadata = Some(json!({"case": "all-helpers"}));
99        let archive_response = client.archive(archive).await?;
100        let reference_id = archive_response
101            .get("reference_id")
102            .and_then(Value::as_str)
103            .ok_or_else(|| boxed_error(format!("archive reference missing: {archive_response}")))?
104            .to_string();
105
106        let mut dereference = DereferenceOptions::new(reference_id.clone());
107        dereference.run_id = Some(run_id.clone());
108        dereference.agent_id = Some("planner".to_string());
109        let dereference_response = client.dereference(dereference).await?;
110
111        let mut checkpoint = CheckpointOptions::new("Planner captured claim facts before window compaction.");
112        checkpoint.run_id = Some(run_id.clone());
113        checkpoint.label = Some("pre-compaction".to_string());
114        checkpoint.metadata = Some(json!({"stage": "analysis"}));
115        checkpoint.agent_id = Some("planner".to_string());
116        let checkpoint_response = client.checkpoint(checkpoint).await?;
117
118        let lessons_response = client.control.lessons(json!({"run_id": run_id, "limit": 20})).await?;
119        let lesson_id = lessons_response
120            .get("lessons")
121            .and_then(Value::as_array)
122            .and_then(|items| items.iter().find_map(|item| item.get("id").and_then(Value::as_str)))
123            .ok_or_else(|| boxed_error(format!("expected lesson id for outcome flow: {lessons_response}")))?
124            .to_string();
125
126        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
127        outcome.run_id = Some(run_id.clone());
128        outcome.signal = 0.75;
129        outcome.rationale = "Planner reused stored claim fact and resolved the missing-city branch.".to_string();
130        outcome.agent_id = Some("planner".to_string());
131        let outcome_response = client.record_outcome(outcome).await?;
132
133        let mut strategies = SurfaceStrategiesOptions::default();
134        strategies.run_id = Some(run_id.clone());
135        strategies.lesson_types = vec!["success".to_string(), "rule".to_string()];
136        strategies.max_strategies = 5;
137        let strategies_response = client.surface_strategies(strategies).await?;
138
139        let mut handoff = HandoffOptions::new(
140            "claim-1",
141            "planner",
142            "reviewer",
143            "Review whether the stored claimant city is sufficient for routing.",
144        );
145        handoff.run_id = Some(run_id.clone());
146        handoff.requested_action = "review".to_string();
147        handoff.metadata = Some(json!({"team": "claims"}));
148        let handoff_response = client.handoff(handoff).await?;
149        let handoff_id = handoff_response
150            .get("handoff_id")
151            .and_then(Value::as_str)
152            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
153            .to_string();
154
155        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
156        feedback.run_id = Some(run_id.clone());
157        feedback.comments = "Stored fact is sufficient; proceed without escalation.".to_string();
158        feedback.from_agent_id = Some("reviewer".to_string());
159        feedback.metadata = Some(json!({"team": "claims"}));
160        let feedback_response = client.feedback(feedback).await?;
161
162        let scratch_run = format!("{run_id}_forget");
163        let mut scratch = RememberOptions::new("Scratch run for forget helper coverage.");
164        scratch.run_id = Some(scratch_run.clone());
165        scratch.agent_id = Some("planner".to_string());
166        scratch.intent = Some("fact".to_string());
167        scratch.metadata = Some(json!({"suite": "all-helpers", "temporary": true}));
168        let scratch_response = client.remember(scratch).await?;
169
170        let forget_response = client
171            .forget(ForgetOptions::for_run(scratch_run.clone()))
172            .await?;
173
174        let mut forgotten = RecallOptions::new("What temporary scratch fact exists?");
175        forgotten.run_id = Some(scratch_run.clone());
176        forgotten.limit = 3;
177        let forgotten_response = client.recall(forgotten).await?;
178
179        require(remember_response.get("job_id").is_some() || remember_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("remember failed: {remember_response}"))?;
180        require(lesson_response.get("job_id").is_some() || lesson_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("lesson remember failed: {lesson_response}"))?;
181        require(recall_response.get("final_answer").is_some() || recall_response.get("evidence").is_some(), format!("recall failed: {recall_response}"))?;
182        require(context_response.get("sources").and_then(Value::as_array).is_some(), format!("context malformed: {context_response}"))?;
183        require(health_response.get("entry_counts").and_then(Value::as_object).is_some(), format!("memory_health malformed: {health_response}"))?;
184        require(diagnose_response.get("failure_lessons").and_then(Value::as_array).is_some(), format!("diagnose malformed: {diagnose_response}"))?;
185        require(reflect_response.get("lessons").and_then(Value::as_array).is_some(), format!("reflect malformed: {reflect_response}"))?;
186        require(register_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("register_agent failed: {register_response}"))?;
187        require(agents_response.get("agents").and_then(Value::as_array).map(|items| !items.is_empty()).unwrap_or(false), format!("list_agents failed: {agents_response}"))?;
188        require(archive_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("archive failed: {archive_response}"))?;
189        require(dereference_response.get("found").and_then(Value::as_bool).unwrap_or(false), format!("dereference failed: {dereference_response}"))?;
190        require(checkpoint_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
191        require(outcome_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("record_outcome failed: {outcome_response}"))?;
192        require(strategies_response.get("strategies").and_then(Value::as_array).is_some(), format!("surface_strategies malformed: {strategies_response}"))?;
193        require(handoff_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
194        require(feedback_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
195        require(scratch_response.get("job_id").is_some() || scratch_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("scratch remember failed: {scratch_response}"))?;
196        require(forget_response.get("success").and_then(Value::as_bool).unwrap_or(true), format!("forget failed: {forget_response}"))?;
197        let scratch_fact_visible = forgotten_response
198            .get("evidence")
199            .and_then(Value::as_array)
200            .map(|items| {
201                items.iter().any(|item| {
202                    item.get("run_id").and_then(Value::as_str) == Some(scratch_run.as_str())
203                        || item
204                            .get("content")
205                            .and_then(Value::as_str)
206                            .map(|content| {
207                                content
208                                    .to_ascii_lowercase()
209                                    .contains("scratch run for forget helper coverage")
210                            })
211                            .unwrap_or(false)
212                })
213            })
214            .unwrap_or(false);
215        require(!scratch_fact_visible, format!("scratch fact should be forgotten even if same-user lessons still surface: {forgotten_response}"))?;
216
217        let strategy_count = strategies_response
218            .get("strategies")
219            .and_then(Value::as_array)
220            .map(|items| items.len())
221            .unwrap_or(0);
222        let agent_count = agents_response
223            .get("agents")
224            .and_then(Value::as_array)
225            .map(|items| items.len())
226            .unwrap_or(0);
227        let lesson_count = lessons_response
228            .get("lessons")
229            .and_then(Value::as_array)
230            .map(|items| items.len())
231            .unwrap_or(0);
232
233        metrics = json!({
234            "run_id": run_id,
235            "agent_count": agent_count,
236            "strategy_count": strategy_count,
237            "reference_id": reference_id,
238            "lesson_count": lesson_count,
239            "forgotten_run": scratch_run,
240        });
241
242        Ok::<(), Box<dyn Error>>(())
243    }
244    .await;
245
246    if let Err(err) = scenario {
247        passed = false;
248        detail = err.to_string();
249    }
250
251    let cleanup_ok = cleanup_run(&client, &run_id).await;
252    if !cleanup_ok {
253        passed = false;
254        detail = format!("{detail} | cleanup failures");
255    }
256
257    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
258
259    if passed { Ok(()) } else { Err(boxed_error(detail)) }
260}
Source

pub async fn handoff(&self, options: HandoffOptions) -> Result<Value>

Examples found in repository?
examples/helper_handoff_feedback.rs (line 45)
13async fn main() -> Result<(), Box<dyn Error>> {
14    let name = "helper_handoff_feedback";
15    let started = Instant::now();
16    let client = create_client().await?;
17    let run_id = new_run_id("helper_handoff_feedback");
18    client.set_run_id(Some(run_id.clone()));
19    client.set_transport(TransportMode::Http);
20
21    let mut passed = true;
22    let mut detail = "validated helper handoff + feedback flow".to_string();
23    let mut metrics = json!({});
24
25    let scenario = async {
26        let mut planner = RegisterAgentOptions::new("planner");
27        planner.run_id = Some(run_id.clone());
28        planner.role = "planner".to_string();
29        client.register_agent(planner).await?;
30
31        let mut reviewer = RegisterAgentOptions::new("reviewer");
32        reviewer.run_id = Some(run_id.clone());
33        reviewer.role = "reviewer".to_string();
34        client.register_agent(reviewer).await?;
35
36        let mut handoff = HandoffOptions::new(
37            "task-1",
38            "planner",
39            "reviewer",
40            "Review the retry policy patch before rollout.",
41        );
42        handoff.run_id = Some(run_id.clone());
43        handoff.requested_action = "review".to_string();
44        handoff.metadata = Some(json!({ "source": "rust-helper-example" }));
45        let handoff_response = client.handoff(handoff).await?;
46        let handoff_id = handoff_response
47            .get("handoff_id")
48            .and_then(|value| value.as_str())
49            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
50            .to_string();
51
52        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
53        feedback.run_id = Some(run_id.clone());
54        feedback.comments = "Patch looks safe for rollout.".to_string();
55        feedback.from_agent_id = Some("reviewer".to_string());
56        feedback.metadata = Some(json!({ "source": "rust-helper-example" }));
57        let feedback_response = client.feedback(feedback).await?;
58
59        let mut context = GetContextOptions::default();
60        context.run_id = Some(run_id.clone());
61        context.query = Some("What coordination artifacts were recorded for this review handoff?".to_string());
62        context.mode = Some("sections".to_string());
63        context.sections = vec!["handoffs".to_string(), "feedback".to_string()];
64        let context_response = client.get_context(context).await?;
65
66        require(
67            handoff_response
68                .get("success")
69                .and_then(|value| value.as_bool())
70                .unwrap_or(false),
71            format!("handoff failed: {handoff_response}"),
72        )?;
73        require(
74            feedback_response
75                .get("success")
76                .and_then(|value| value.as_bool())
77                .unwrap_or(false),
78            format!("feedback failed: {feedback_response}"),
79        )?;
80        let section_count = context_response
81            .get("section_summaries")
82            .and_then(|value| value.as_array())
83            .map(|items| items.len())
84            .unwrap_or(0);
85
86        metrics = json!({
87            "run_id": run_id,
88            "handoff_id": handoff_id,
89            "feedback_id": feedback_response.get("feedback_id").cloned().unwrap_or(serde_json::Value::Null),
90            "section_count": section_count,
91        });
92
93        Ok::<(), Box<dyn Error>>(())
94    }
95    .await;
96
97    if let Err(err) = scenario {
98        passed = false;
99        detail = err.to_string();
100    }
101
102    let cleanup_ok = cleanup_run(&client, &run_id).await;
103    if !cleanup_ok {
104        passed = false;
105        detail = format!("{detail} | cleanup failures");
106    }
107
108    print_summary(
109        name,
110        passed,
111        &detail,
112        &metrics,
113        started.elapsed().as_secs_f64(),
114        cleanup_ok,
115    );
116
117    if passed {
118        Ok(())
119    } else {
120        Err(boxed_error(detail))
121    }
122}
More examples
Hide additional examples
examples/public/06_handoff_feedback.rs (line 45)
13async fn main() -> Result<(), Box<dyn Error>> {
14    let name = "public_06_handoff_feedback";
15    let started = Instant::now();
16    let client = create_client().await?;
17    let run_id = new_run_id("public_06_handoff_feedback");
18    client.set_run_id(Some(run_id.clone()));
19    client.set_transport(TransportMode::Http);
20
21    let mut passed = true;
22    let mut detail = "validated helper handoff + feedback flow".to_string();
23    let mut metrics = json!({});
24
25    let scenario = async {
26        let mut planner = RegisterAgentOptions::new("planner");
27        planner.run_id = Some(run_id.clone());
28        planner.role = "planner".to_string();
29        client.register_agent(planner).await?;
30
31        let mut reviewer = RegisterAgentOptions::new("reviewer");
32        reviewer.run_id = Some(run_id.clone());
33        reviewer.role = "reviewer".to_string();
34        client.register_agent(reviewer).await?;
35
36        let mut handoff = HandoffOptions::new(
37            "task-1",
38            "planner",
39            "reviewer",
40            "Review the retry policy patch before rollout.",
41        );
42        handoff.run_id = Some(run_id.clone());
43        handoff.requested_action = "review".to_string();
44        handoff.metadata = Some(json!({ "source": "rust-helper-example" }));
45        let handoff_response = client.handoff(handoff).await?;
46        let handoff_id = handoff_response
47            .get("handoff_id")
48            .and_then(|value| value.as_str())
49            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
50            .to_string();
51
52        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
53        feedback.run_id = Some(run_id.clone());
54        feedback.comments = "Patch looks safe for rollout.".to_string();
55        feedback.from_agent_id = Some("reviewer".to_string());
56        feedback.metadata = Some(json!({ "source": "rust-helper-example" }));
57        let feedback_response = client.feedback(feedback).await?;
58
59        let mut context = GetContextOptions::default();
60        context.run_id = Some(run_id.clone());
61        context.query = Some("What coordination artifacts were recorded for this review handoff?".to_string());
62        context.mode = Some("sections".to_string());
63        context.sections = vec!["handoffs".to_string(), "feedback".to_string()];
64        let context_response = client.get_context(context).await?;
65
66        require(
67            handoff_response
68                .get("success")
69                .and_then(|value| value.as_bool())
70                .unwrap_or(false),
71            format!("handoff failed: {handoff_response}"),
72        )?;
73        require(
74            feedback_response
75                .get("success")
76                .and_then(|value| value.as_bool())
77                .unwrap_or(false),
78            format!("feedback failed: {feedback_response}"),
79        )?;
80        let section_count = context_response
81            .get("section_summaries")
82            .and_then(|value| value.as_array())
83            .map(|items| items.len())
84            .unwrap_or(0);
85
86        metrics = json!({
87            "run_id": run_id,
88            "handoff_id": handoff_id,
89            "feedback_id": feedback_response.get("feedback_id").cloned().unwrap_or(serde_json::Value::Null),
90            "section_count": section_count,
91        });
92
93        Ok::<(), Box<dyn Error>>(())
94    }
95    .await;
96
97    if let Err(err) = scenario {
98        passed = false;
99        detail = err.to_string();
100    }
101
102    let cleanup_ok = cleanup_run(&client, &run_id).await;
103    if !cleanup_ok {
104        passed = false;
105        detail = format!("{detail} | cleanup failures");
106    }
107
108    print_summary(
109        name,
110        passed,
111        &detail,
112        &metrics,
113        started.elapsed().as_secs_f64(),
114        cleanup_ok,
115    );
116
117    if passed {
118        Ok(())
119    } else {
120        Err(boxed_error(detail))
121    }
122}
examples/public/08_multi_agent_claims_or_support_flow.rs (line 67)
11async fn main() -> Result<(), Box<dyn Error>> {
12    let name = "public_08_multi_agent_claims_or_support_flow";
13    let started = Instant::now();
14    let client = create_client().await?;
15    let run_id = new_run_id("public_claims_flow");
16    client.set_run_id(Some(run_id.clone()));
17    client.set_transport(TransportMode::Http);
18
19    let mut passed = true;
20    let mut detail = "validated multi-agent claims/support flow".to_string();
21    let mut metrics = json!({});
22
23    let scenario = async {
24        for (agent_id, role, read_scopes, write_scopes) in [
25            ("intake", "intake", vec!["fact", "archive_block"], vec!["fact", "archive_block", "trace"]),
26            ("coverage", "coverage", vec!["fact", "rule", "archive_block", "handoff", "feedback"], vec!["fact", "trace", "lesson"]),
27            ("reviewer", "reviewer", vec!["fact", "archive_block", "handoff", "feedback", "rule"], vec!["feedback", "rule"]),
28        ] {
29            let mut agent = RegisterAgentOptions::new(agent_id);
30            agent.run_id = Some(run_id.clone());
31            agent.role = role.to_string();
32            agent.read_scopes = read_scopes.into_iter().map(String::from).collect();
33            agent.write_scopes = write_scopes.into_iter().map(String::from).collect();
34            agent.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
35            client.register_agent(agent).await?;
36        }
37
38        let mut fact = RememberOptions::new("Policy P-8842 covers windshield damage with a 250 GBP deductible.");
39        fact.run_id = Some(run_id.clone());
40        fact.agent_id = Some("intake".into());
41        fact.intent = Some("fact".into());
42        fact.metadata = Some(json!({"claim_id": "CLM-8842", "source": "intake-form"}));
43        client.remember(fact).await?;
44
45        let mut archive = ArchiveOptions::new("Exact adjuster note: customer confirmed the damage happened on the motorway and no third party was involved.", "adjuster_note");
46        archive.run_id = Some(run_id.clone());
47        archive.agent_id = Some("intake".into());
48        archive.origin_agent_id = Some("intake".into());
49        archive.source_attempt_id = Some("attempt-1".into());
50        archive.source_tool = Some("claim-review".into());
51        archive.labels = vec!["claims".into(), "coverage".into()];
52        archive.family = Some("windshield".into());
53        let archived = client.archive(archive).await?;
54        let reference_id = archived.get("reference_id").and_then(|v| v.as_str()).ok_or_else(|| boxed_error(format!("archive reference missing: {archived}")))?.to_string();
55
56        let mut checkpoint = CheckpointOptions::new("Coverage verified deductible and adjuster note before escalation.");
57        checkpoint.run_id = Some(run_id.clone());
58        checkpoint.label = Some("pre-review".into());
59        checkpoint.agent_id = Some("coverage".into());
60        checkpoint.metadata = Some(json!({"claim_id": "CLM-8842"}));
61        let checkpoint_response = client.checkpoint(checkpoint).await?;
62
63        let mut handoff = HandoffOptions::new("claim-8842", "coverage", "reviewer", "Review whether the adjuster note is enough to approve the claim.");
64        handoff.run_id = Some(run_id.clone());
65        handoff.requested_action = "review".into();
66        handoff.metadata = Some(json!({"claim_id": "CLM-8842"}));
67        let handoff_response = client.handoff(handoff).await?;
68        let handoff_id = handoff_response.get("handoff_id").and_then(|v| v.as_str()).ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?.to_string();
69
70        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
71        feedback.run_id = Some(run_id.clone());
72        feedback.from_agent_id = Some("reviewer".into());
73        feedback.comments = "Deductible and adjuster note are sufficient for routing.".into();
74        feedback.metadata = Some(json!({"claim_id": "CLM-8842"}));
75        let feedback_response = client.feedback(feedback).await?;
76
77        let mut context_opts = GetContextOptions::default();
78        context_opts.run_id = Some(run_id.clone());
79        context_opts.query = Some("Prepare the final claims routing summary.".into());
80        context_opts.agent_id = Some("coverage".into());
81        context_opts.sections = vec!["archive".into(), "facts".into(), "handoffs".into(), "feedback".into()];
82        context_opts.mode = Some("sections".into());
83        let context = client.get_context(context_opts).await?;
84
85        let mut dereference = DereferenceOptions::new(reference_id.clone());
86        dereference.run_id = Some(run_id.clone());
87        dereference.agent_id = Some("coverage".into());
88        let exact = client.dereference(dereference).await?;
89
90        let mut recall = RecallOptions::new("What deductible applies and what did the adjuster confirm?");
91        recall.run_id = Some(run_id.clone());
92        recall.agent_id = Some("coverage".into());
93        recall.entry_types = vec!["fact".into(), "archive_block".into(), "feedback".into()];
94        let recall_response = client.recall(recall).await?;
95
96        require(checkpoint_response.get("success").and_then(|v| v.as_bool()).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
97        require(handoff_response.get("success").and_then(|v| v.as_bool()).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
98        require(feedback_response.get("success").and_then(|v| v.as_bool()).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
99        require(exact.get("found").and_then(|v| v.as_bool()).unwrap_or(false), format!("dereference failed: {exact}"))?;
100        let context_text = context.get("context_block").and_then(|v| v.as_str()).unwrap_or("").to_lowercase();
101        let recall_text = recall_response.get("final_answer").and_then(|v| v.as_str()).unwrap_or("").to_lowercase();
102        let has_archive_source = context
103            .get("sources")
104            .and_then(|v| v.as_array())
105            .map(|sources| {
106                sources.iter().any(|source| {
107                    source
108                        .get("entry_type")
109                        .and_then(|v| v.as_str())
110                        == Some("archive_block")
111                })
112            })
113            .unwrap_or(false);
114        let exact_refs_surfaced = context
115            .get("exact_references_surfaced")
116            .and_then(|v| v.as_u64())
117            .unwrap_or(0);
118        require(
119            context_text.contains("adjuster note")
120                || context_text.contains("motorway")
121                || has_archive_source
122                || exact_refs_surfaced > 0,
123            format!("expected explicit or telemetry-backed exact reuse in context: {context}"),
124        )?;
125        require(recall_text.contains("250") && (recall_text.contains("motorway") || recall_text.contains("third party")), format!("expected recall to include fact + archive content: {recall_response}"))?;
126
127        metrics = json!({
128            "run_id": run_id,
129            "handoff_id": handoff_id,
130            "reference_id": reference_id,
131            "feedback_id": feedback_response.get("feedback_id").cloned().unwrap_or(serde_json::Value::Null),
132        });
133        Ok::<(), Box<dyn Error>>(())
134    }
135    .await;
136
137    if let Err(err) = scenario {
138        passed = false;
139        detail = err.to_string();
140    }
141
142    let cleanup_ok = cleanup_run(&client, &run_id).await;
143    if !cleanup_ok {
144        passed = false;
145        detail = format!("{detail} | cleanup failures");
146    }
147
148    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
149    if passed { Ok(()) } else { Err(boxed_error(detail)) }
150}
examples/public/10_full_learning_loop_smoke.rs (line 160)
16async fn main() -> Result<(), Box<dyn Error>> {
17    let name = "public_10_full_learning_loop_smoke";
18    let started = Instant::now();
19    let client = create_client().await?;
20    let run_id = new_run_id("public_10_full_learning_loop_smoke");
21    client.set_run_id(Some(run_id.clone()));
22    client.set_transport(TransportMode::Http);
23
24    let mut passed = true;
25    let mut detail = "validated all helper flows".to_string();
26    let mut metrics = json!({});
27
28    let scenario = async {
29        let mut remember = RememberOptions::new("Policy limit is 5000 and claimant city is Leeds.");
30        remember.run_id = Some(run_id.clone());
31        remember.agent_id = Some("planner".to_string());
32        remember.intent = Some("fact".to_string());
33        remember.metadata = Some(json!({"suite": "all-helpers", "family": "claims"}));
34        remember.importance = Some("high".to_string());
35        remember.occurrence_time = Some(std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as i64 - 86400);
36        let remember_response = client.remember(remember).await?;
37
38        let mut lesson = RememberOptions::new("If city is missing from the latest step, check stored claim facts before escalating.");
39        lesson.run_id = Some(run_id.clone());
40        lesson.agent_id = Some("planner".to_string());
41        lesson.intent = Some("lesson".to_string());
42        lesson.lesson_type = Some("success".to_string());
43        lesson.lesson_scope = Some("session".to_string());
44        lesson.lesson_importance = Some("high".to_string());
45        let lesson_response = client.remember(lesson).await?;
46
47        let mut mental_model = RememberOptions::new(
48            "Claims case overview: Policy limit 5000 GBP, claimant city Leeds, \
49             missing-city branch resolved via stored claim facts. Lesson: check stored facts before escalating.",
50        );
51        mental_model.run_id = Some(run_id.clone());
52        mental_model.agent_id = Some("planner".to_string());
53        mental_model.intent = Some("mental_model".to_string());
54        mental_model.importance = Some("critical".to_string());
55        mental_model.metadata = Some(json!({"suite": "all-helpers", "entity": "claims-case", "consolidated": true}));
56        let mental_model_response = client.remember(mental_model).await?;
57
58        let mut recall = RecallOptions::new("What is the policy limit?");
59        recall.run_id = Some(run_id.clone());
60        recall.agent_id = Some("planner".to_string());
61        recall.limit = 5;
62        let recall_response = client.recall(recall).await?;
63
64        let mut context = GetContextOptions::default();
65        context.run_id = Some(run_id.clone());
66        context.query = Some("Prepare a short adjuster summary".to_string());
67        context.agent_id = Some("planner".to_string());
68        context.limit = Some(6);
69        context.max_token_budget = Some(700);
70        let context_response = client.get_context(context).await?;
71
72        let mut health = MemoryHealthOptions::default();
73        health.run_id = Some(run_id.clone());
74        health.limit = 50;
75        let health_response = client.memory_health(health).await?;
76
77        let mut diagnose = DiagnoseOptions::new("policy limit lookup returned empty");
78        diagnose.run_id = Some(run_id.clone());
79        diagnose.error_type = Some("retrieval".to_string());
80        diagnose.limit = 5;
81        let diagnose_response = client.diagnose(diagnose).await?;
82
83        let mut reflect = ReflectOptions::default();
84        reflect.run_id = Some(run_id.clone());
85        let reflect_response = client.reflect(reflect).await?;
86
87        let mut register = RegisterAgentOptions::new("planner");
88        register.run_id = Some(run_id.clone());
89        register.role = "planner".to_string();
90        register.read_scopes = vec!["fact".into(), "lesson".into(), "rule".into(), "mental_model".into(), "archive_block".into(), "handoff".into(), "feedback".into()];
91        register.write_scopes = vec!["fact".into(), "trace".into(), "lesson".into(), "observation".into(), "archive_block".into()];
92        register.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
93        let register_response = client.register_agent(register).await?;
94
95        let mut list_agents = ListAgentsOptions::default();
96        list_agents.run_id = Some(run_id.clone());
97        let agents_response = client.list_agents(list_agents).await?;
98
99        let mut archive = ArchiveOptions::new(
100            "Exact adjuster note: claimant confirmed city is Leeds during triage.",
101            "adjuster_note",
102        );
103        archive.run_id = Some(run_id.clone());
104        archive.agent_id = Some("planner".to_string());
105        archive.origin_agent_id = Some("planner".to_string());
106        archive.source_attempt_id = Some("attempt-1".to_string());
107        archive.source_tool = Some("phone_call".to_string());
108        archive.labels = vec!["claims".to_string(), "triage".to_string()];
109        archive.family = Some("claims-adjustment".to_string());
110        archive.metadata = Some(json!({"case": "all-helpers"}));
111        let archive_response = client.archive(archive).await?;
112        let reference_id = archive_response
113            .get("reference_id")
114            .and_then(Value::as_str)
115            .ok_or_else(|| boxed_error(format!("archive reference missing: {archive_response}")))?
116            .to_string();
117
118        let mut dereference = DereferenceOptions::new(reference_id.clone());
119        dereference.run_id = Some(run_id.clone());
120        dereference.agent_id = Some("planner".to_string());
121        let dereference_response = client.dereference(dereference).await?;
122
123        let mut checkpoint = CheckpointOptions::new("Planner captured claim facts before window compaction.");
124        checkpoint.run_id = Some(run_id.clone());
125        checkpoint.label = Some("pre-compaction".to_string());
126        checkpoint.metadata = Some(json!({"stage": "analysis"}));
127        checkpoint.agent_id = Some("planner".to_string());
128        let checkpoint_response = client.checkpoint(checkpoint).await?;
129
130        let lessons_response = client.control.lessons(json!({"run_id": run_id, "limit": 20})).await?;
131        let lesson_id = lessons_response
132            .get("lessons")
133            .and_then(Value::as_array)
134            .and_then(|items| items.iter().find_map(|item| item.get("id").and_then(Value::as_str)))
135            .ok_or_else(|| boxed_error(format!("expected lesson id for outcome flow: {lessons_response}")))?
136            .to_string();
137
138        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
139        outcome.run_id = Some(run_id.clone());
140        outcome.signal = 0.75;
141        outcome.rationale = "Planner reused stored claim fact and resolved the missing-city branch.".to_string();
142        outcome.agent_id = Some("planner".to_string());
143        let outcome_response = client.record_outcome(outcome).await?;
144
145        let mut strategies = SurfaceStrategiesOptions::default();
146        strategies.run_id = Some(run_id.clone());
147        strategies.lesson_types = vec!["success".to_string(), "rule".to_string()];
148        strategies.max_strategies = 5;
149        let strategies_response = client.surface_strategies(strategies).await?;
150
151        let mut handoff = HandoffOptions::new(
152            "claim-1",
153            "planner",
154            "reviewer",
155            "Review whether the stored claimant city is sufficient for routing.",
156        );
157        handoff.run_id = Some(run_id.clone());
158        handoff.requested_action = "review".to_string();
159        handoff.metadata = Some(json!({"team": "claims"}));
160        let handoff_response = client.handoff(handoff).await?;
161        let handoff_id = handoff_response
162            .get("handoff_id")
163            .and_then(Value::as_str)
164            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
165            .to_string();
166
167        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
168        feedback.run_id = Some(run_id.clone());
169        feedback.comments = "Stored fact is sufficient; proceed without escalation.".to_string();
170        feedback.from_agent_id = Some("reviewer".to_string());
171        feedback.metadata = Some(json!({"team": "claims"}));
172        let feedback_response = client.feedback(feedback).await?;
173
174        require(remember_response.get("job_id").is_some() || remember_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("remember failed: {remember_response}"))?;
175        require(mental_model_response.get("job_id").is_some() || mental_model_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("mental_model remember failed: {mental_model_response}"))?;
176        require(lesson_response.get("job_id").is_some() || lesson_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("lesson remember failed: {lesson_response}"))?;
177        require(recall_response.get("final_answer").is_some() || recall_response.get("evidence").is_some(), format!("recall failed: {recall_response}"))?;
178        require(context_response.get("sources").and_then(Value::as_array).is_some(), format!("context malformed: {context_response}"))?;
179        require(health_response.get("entry_counts").and_then(Value::as_object).is_some(), format!("memory_health malformed: {health_response}"))?;
180        require(diagnose_response.get("failure_lessons").and_then(Value::as_array).is_some(), format!("diagnose malformed: {diagnose_response}"))?;
181        require(reflect_response.get("lessons").and_then(Value::as_array).is_some(), format!("reflect malformed: {reflect_response}"))?;
182        require(register_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("register_agent failed: {register_response}"))?;
183        require(agents_response.get("agents").and_then(Value::as_array).map(|items| !items.is_empty()).unwrap_or(false), format!("list_agents failed: {agents_response}"))?;
184        require(archive_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("archive failed: {archive_response}"))?;
185        require(dereference_response.get("found").and_then(Value::as_bool).unwrap_or(false), format!("dereference failed: {dereference_response}"))?;
186        require(checkpoint_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
187        require(outcome_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("record_outcome failed: {outcome_response}"))?;
188        require(strategies_response.get("strategies").and_then(Value::as_array).is_some(), format!("surface_strategies malformed: {strategies_response}"))?;
189        require(handoff_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
190        require(feedback_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
191
192        let strategy_count = strategies_response
193            .get("strategies")
194            .and_then(Value::as_array)
195            .map(|items| items.len())
196            .unwrap_or(0);
197        let agent_count = agents_response
198            .get("agents")
199            .and_then(Value::as_array)
200            .map(|items| items.len())
201            .unwrap_or(0);
202        let lesson_count = lessons_response
203            .get("lessons")
204            .and_then(Value::as_array)
205            .map(|items| items.len())
206            .unwrap_or(0);
207
208        metrics = json!({
209            "run_id": run_id,
210            "agent_count": agent_count,
211            "strategy_count": strategy_count,
212            "reference_id": reference_id,
213            "lesson_count": lesson_count,
214        });
215
216        Ok::<(), Box<dyn Error>>(())
217    }
218    .await;
219
220    if let Err(err) = scenario {
221        passed = false;
222        detail = err.to_string();
223    }
224
225    let cleanup_ok = cleanup_run(&client, &run_id).await;
226    if !cleanup_ok {
227        passed = false;
228        detail = format!("{detail} | cleanup failures");
229    }
230
231    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
232
233    if passed { Ok(()) } else { Err(boxed_error(detail)) }
234}
examples/helper_all_helpers.rs (line 148)
16async fn main() -> Result<(), Box<dyn Error>> {
17    let name = "helper_all_helpers";
18    let started = Instant::now();
19    let client = create_client().await?;
20    let run_id = new_run_id("helper_all_helpers");
21    client.set_run_id(Some(run_id.clone()));
22    client.set_transport(TransportMode::Http);
23
24    let mut passed = true;
25    let mut detail = "validated all helper flows".to_string();
26    let mut metrics = json!({});
27
28    let scenario = async {
29        let mut remember = RememberOptions::new("Policy limit is 5000 and claimant city is Leeds.");
30        remember.run_id = Some(run_id.clone());
31        remember.agent_id = Some("planner".to_string());
32        remember.intent = Some("fact".to_string());
33        remember.metadata = Some(json!({"suite": "all-helpers", "family": "claims"}));
34        remember.importance = Some("high".to_string());
35        let remember_response = client.remember(remember).await?;
36
37        let mut lesson = RememberOptions::new("If city is missing from the latest step, check stored claim facts before escalating.");
38        lesson.run_id = Some(run_id.clone());
39        lesson.agent_id = Some("planner".to_string());
40        lesson.intent = Some("lesson".to_string());
41        lesson.lesson_type = Some("success".to_string());
42        lesson.lesson_scope = Some("session".to_string());
43        lesson.lesson_importance = Some("high".to_string());
44        let lesson_response = client.remember(lesson).await?;
45
46        let mut recall = RecallOptions::new("What is the policy limit?");
47        recall.run_id = Some(run_id.clone());
48        recall.agent_id = Some("planner".to_string());
49        recall.limit = 5;
50        let recall_response = client.recall(recall).await?;
51
52        let mut context = GetContextOptions::default();
53        context.run_id = Some(run_id.clone());
54        context.query = Some("Prepare a short adjuster summary".to_string());
55        context.agent_id = Some("planner".to_string());
56        context.limit = Some(6);
57        context.max_token_budget = Some(700);
58        let context_response = client.get_context(context).await?;
59
60        let mut health = MemoryHealthOptions::default();
61        health.run_id = Some(run_id.clone());
62        health.limit = 50;
63        let health_response = client.memory_health(health).await?;
64
65        let mut diagnose = DiagnoseOptions::new("policy limit lookup returned empty");
66        diagnose.run_id = Some(run_id.clone());
67        diagnose.error_type = Some("retrieval".to_string());
68        diagnose.limit = 5;
69        let diagnose_response = client.diagnose(diagnose).await?;
70
71        let mut reflect = ReflectOptions::default();
72        reflect.run_id = Some(run_id.clone());
73        let reflect_response = client.reflect(reflect).await?;
74
75        let mut register = RegisterAgentOptions::new("planner");
76        register.run_id = Some(run_id.clone());
77        register.role = "planner".to_string();
78        register.read_scopes = vec!["fact".into(), "lesson".into(), "rule".into(), "archive_block".into(), "handoff".into(), "feedback".into()];
79        register.write_scopes = vec!["fact".into(), "trace".into(), "lesson".into(), "observation".into(), "archive_block".into()];
80        register.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
81        let register_response = client.register_agent(register).await?;
82
83        let mut list_agents = ListAgentsOptions::default();
84        list_agents.run_id = Some(run_id.clone());
85        let agents_response = client.list_agents(list_agents).await?;
86
87        let mut archive = ArchiveOptions::new(
88            "Exact adjuster note: claimant confirmed city is Leeds during triage.",
89            "adjuster_note",
90        );
91        archive.run_id = Some(run_id.clone());
92        archive.agent_id = Some("planner".to_string());
93        archive.origin_agent_id = Some("planner".to_string());
94        archive.source_attempt_id = Some("attempt-1".to_string());
95        archive.source_tool = Some("phone_call".to_string());
96        archive.labels = vec!["claims".to_string(), "triage".to_string()];
97        archive.family = Some("claims-adjustment".to_string());
98        archive.metadata = Some(json!({"case": "all-helpers"}));
99        let archive_response = client.archive(archive).await?;
100        let reference_id = archive_response
101            .get("reference_id")
102            .and_then(Value::as_str)
103            .ok_or_else(|| boxed_error(format!("archive reference missing: {archive_response}")))?
104            .to_string();
105
106        let mut dereference = DereferenceOptions::new(reference_id.clone());
107        dereference.run_id = Some(run_id.clone());
108        dereference.agent_id = Some("planner".to_string());
109        let dereference_response = client.dereference(dereference).await?;
110
111        let mut checkpoint = CheckpointOptions::new("Planner captured claim facts before window compaction.");
112        checkpoint.run_id = Some(run_id.clone());
113        checkpoint.label = Some("pre-compaction".to_string());
114        checkpoint.metadata = Some(json!({"stage": "analysis"}));
115        checkpoint.agent_id = Some("planner".to_string());
116        let checkpoint_response = client.checkpoint(checkpoint).await?;
117
118        let lessons_response = client.control.lessons(json!({"run_id": run_id, "limit": 20})).await?;
119        let lesson_id = lessons_response
120            .get("lessons")
121            .and_then(Value::as_array)
122            .and_then(|items| items.iter().find_map(|item| item.get("id").and_then(Value::as_str)))
123            .ok_or_else(|| boxed_error(format!("expected lesson id for outcome flow: {lessons_response}")))?
124            .to_string();
125
126        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
127        outcome.run_id = Some(run_id.clone());
128        outcome.signal = 0.75;
129        outcome.rationale = "Planner reused stored claim fact and resolved the missing-city branch.".to_string();
130        outcome.agent_id = Some("planner".to_string());
131        let outcome_response = client.record_outcome(outcome).await?;
132
133        let mut strategies = SurfaceStrategiesOptions::default();
134        strategies.run_id = Some(run_id.clone());
135        strategies.lesson_types = vec!["success".to_string(), "rule".to_string()];
136        strategies.max_strategies = 5;
137        let strategies_response = client.surface_strategies(strategies).await?;
138
139        let mut handoff = HandoffOptions::new(
140            "claim-1",
141            "planner",
142            "reviewer",
143            "Review whether the stored claimant city is sufficient for routing.",
144        );
145        handoff.run_id = Some(run_id.clone());
146        handoff.requested_action = "review".to_string();
147        handoff.metadata = Some(json!({"team": "claims"}));
148        let handoff_response = client.handoff(handoff).await?;
149        let handoff_id = handoff_response
150            .get("handoff_id")
151            .and_then(Value::as_str)
152            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
153            .to_string();
154
155        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
156        feedback.run_id = Some(run_id.clone());
157        feedback.comments = "Stored fact is sufficient; proceed without escalation.".to_string();
158        feedback.from_agent_id = Some("reviewer".to_string());
159        feedback.metadata = Some(json!({"team": "claims"}));
160        let feedback_response = client.feedback(feedback).await?;
161
162        let scratch_run = format!("{run_id}_forget");
163        let mut scratch = RememberOptions::new("Scratch run for forget helper coverage.");
164        scratch.run_id = Some(scratch_run.clone());
165        scratch.agent_id = Some("planner".to_string());
166        scratch.intent = Some("fact".to_string());
167        scratch.metadata = Some(json!({"suite": "all-helpers", "temporary": true}));
168        let scratch_response = client.remember(scratch).await?;
169
170        let forget_response = client
171            .forget(ForgetOptions::for_run(scratch_run.clone()))
172            .await?;
173
174        let mut forgotten = RecallOptions::new("What temporary scratch fact exists?");
175        forgotten.run_id = Some(scratch_run.clone());
176        forgotten.limit = 3;
177        let forgotten_response = client.recall(forgotten).await?;
178
179        require(remember_response.get("job_id").is_some() || remember_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("remember failed: {remember_response}"))?;
180        require(lesson_response.get("job_id").is_some() || lesson_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("lesson remember failed: {lesson_response}"))?;
181        require(recall_response.get("final_answer").is_some() || recall_response.get("evidence").is_some(), format!("recall failed: {recall_response}"))?;
182        require(context_response.get("sources").and_then(Value::as_array).is_some(), format!("context malformed: {context_response}"))?;
183        require(health_response.get("entry_counts").and_then(Value::as_object).is_some(), format!("memory_health malformed: {health_response}"))?;
184        require(diagnose_response.get("failure_lessons").and_then(Value::as_array).is_some(), format!("diagnose malformed: {diagnose_response}"))?;
185        require(reflect_response.get("lessons").and_then(Value::as_array).is_some(), format!("reflect malformed: {reflect_response}"))?;
186        require(register_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("register_agent failed: {register_response}"))?;
187        require(agents_response.get("agents").and_then(Value::as_array).map(|items| !items.is_empty()).unwrap_or(false), format!("list_agents failed: {agents_response}"))?;
188        require(archive_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("archive failed: {archive_response}"))?;
189        require(dereference_response.get("found").and_then(Value::as_bool).unwrap_or(false), format!("dereference failed: {dereference_response}"))?;
190        require(checkpoint_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
191        require(outcome_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("record_outcome failed: {outcome_response}"))?;
192        require(strategies_response.get("strategies").and_then(Value::as_array).is_some(), format!("surface_strategies malformed: {strategies_response}"))?;
193        require(handoff_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
194        require(feedback_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
195        require(scratch_response.get("job_id").is_some() || scratch_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("scratch remember failed: {scratch_response}"))?;
196        require(forget_response.get("success").and_then(Value::as_bool).unwrap_or(true), format!("forget failed: {forget_response}"))?;
197        let scratch_fact_visible = forgotten_response
198            .get("evidence")
199            .and_then(Value::as_array)
200            .map(|items| {
201                items.iter().any(|item| {
202                    item.get("run_id").and_then(Value::as_str) == Some(scratch_run.as_str())
203                        || item
204                            .get("content")
205                            .and_then(Value::as_str)
206                            .map(|content| {
207                                content
208                                    .to_ascii_lowercase()
209                                    .contains("scratch run for forget helper coverage")
210                            })
211                            .unwrap_or(false)
212                })
213            })
214            .unwrap_or(false);
215        require(!scratch_fact_visible, format!("scratch fact should be forgotten even if same-user lessons still surface: {forgotten_response}"))?;
216
217        let strategy_count = strategies_response
218            .get("strategies")
219            .and_then(Value::as_array)
220            .map(|items| items.len())
221            .unwrap_or(0);
222        let agent_count = agents_response
223            .get("agents")
224            .and_then(Value::as_array)
225            .map(|items| items.len())
226            .unwrap_or(0);
227        let lesson_count = lessons_response
228            .get("lessons")
229            .and_then(Value::as_array)
230            .map(|items| items.len())
231            .unwrap_or(0);
232
233        metrics = json!({
234            "run_id": run_id,
235            "agent_count": agent_count,
236            "strategy_count": strategy_count,
237            "reference_id": reference_id,
238            "lesson_count": lesson_count,
239            "forgotten_run": scratch_run,
240        });
241
242        Ok::<(), Box<dyn Error>>(())
243    }
244    .await;
245
246    if let Err(err) = scenario {
247        passed = false;
248        detail = err.to_string();
249    }
250
251    let cleanup_ok = cleanup_run(&client, &run_id).await;
252    if !cleanup_ok {
253        passed = false;
254        detail = format!("{detail} | cleanup failures");
255    }
256
257    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
258
259    if passed { Ok(()) } else { Err(boxed_error(detail)) }
260}
Source

pub async fn feedback(&self, options: FeedbackOptions) -> Result<Value>

Examples found in repository?
examples/helper_handoff_feedback.rs (line 57)
13async fn main() -> Result<(), Box<dyn Error>> {
14    let name = "helper_handoff_feedback";
15    let started = Instant::now();
16    let client = create_client().await?;
17    let run_id = new_run_id("helper_handoff_feedback");
18    client.set_run_id(Some(run_id.clone()));
19    client.set_transport(TransportMode::Http);
20
21    let mut passed = true;
22    let mut detail = "validated helper handoff + feedback flow".to_string();
23    let mut metrics = json!({});
24
25    let scenario = async {
26        let mut planner = RegisterAgentOptions::new("planner");
27        planner.run_id = Some(run_id.clone());
28        planner.role = "planner".to_string();
29        client.register_agent(planner).await?;
30
31        let mut reviewer = RegisterAgentOptions::new("reviewer");
32        reviewer.run_id = Some(run_id.clone());
33        reviewer.role = "reviewer".to_string();
34        client.register_agent(reviewer).await?;
35
36        let mut handoff = HandoffOptions::new(
37            "task-1",
38            "planner",
39            "reviewer",
40            "Review the retry policy patch before rollout.",
41        );
42        handoff.run_id = Some(run_id.clone());
43        handoff.requested_action = "review".to_string();
44        handoff.metadata = Some(json!({ "source": "rust-helper-example" }));
45        let handoff_response = client.handoff(handoff).await?;
46        let handoff_id = handoff_response
47            .get("handoff_id")
48            .and_then(|value| value.as_str())
49            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
50            .to_string();
51
52        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
53        feedback.run_id = Some(run_id.clone());
54        feedback.comments = "Patch looks safe for rollout.".to_string();
55        feedback.from_agent_id = Some("reviewer".to_string());
56        feedback.metadata = Some(json!({ "source": "rust-helper-example" }));
57        let feedback_response = client.feedback(feedback).await?;
58
59        let mut context = GetContextOptions::default();
60        context.run_id = Some(run_id.clone());
61        context.query = Some("What coordination artifacts were recorded for this review handoff?".to_string());
62        context.mode = Some("sections".to_string());
63        context.sections = vec!["handoffs".to_string(), "feedback".to_string()];
64        let context_response = client.get_context(context).await?;
65
66        require(
67            handoff_response
68                .get("success")
69                .and_then(|value| value.as_bool())
70                .unwrap_or(false),
71            format!("handoff failed: {handoff_response}"),
72        )?;
73        require(
74            feedback_response
75                .get("success")
76                .and_then(|value| value.as_bool())
77                .unwrap_or(false),
78            format!("feedback failed: {feedback_response}"),
79        )?;
80        let section_count = context_response
81            .get("section_summaries")
82            .and_then(|value| value.as_array())
83            .map(|items| items.len())
84            .unwrap_or(0);
85
86        metrics = json!({
87            "run_id": run_id,
88            "handoff_id": handoff_id,
89            "feedback_id": feedback_response.get("feedback_id").cloned().unwrap_or(serde_json::Value::Null),
90            "section_count": section_count,
91        });
92
93        Ok::<(), Box<dyn Error>>(())
94    }
95    .await;
96
97    if let Err(err) = scenario {
98        passed = false;
99        detail = err.to_string();
100    }
101
102    let cleanup_ok = cleanup_run(&client, &run_id).await;
103    if !cleanup_ok {
104        passed = false;
105        detail = format!("{detail} | cleanup failures");
106    }
107
108    print_summary(
109        name,
110        passed,
111        &detail,
112        &metrics,
113        started.elapsed().as_secs_f64(),
114        cleanup_ok,
115    );
116
117    if passed {
118        Ok(())
119    } else {
120        Err(boxed_error(detail))
121    }
122}
More examples
Hide additional examples
examples/public/06_handoff_feedback.rs (line 57)
13async fn main() -> Result<(), Box<dyn Error>> {
14    let name = "public_06_handoff_feedback";
15    let started = Instant::now();
16    let client = create_client().await?;
17    let run_id = new_run_id("public_06_handoff_feedback");
18    client.set_run_id(Some(run_id.clone()));
19    client.set_transport(TransportMode::Http);
20
21    let mut passed = true;
22    let mut detail = "validated helper handoff + feedback flow".to_string();
23    let mut metrics = json!({});
24
25    let scenario = async {
26        let mut planner = RegisterAgentOptions::new("planner");
27        planner.run_id = Some(run_id.clone());
28        planner.role = "planner".to_string();
29        client.register_agent(planner).await?;
30
31        let mut reviewer = RegisterAgentOptions::new("reviewer");
32        reviewer.run_id = Some(run_id.clone());
33        reviewer.role = "reviewer".to_string();
34        client.register_agent(reviewer).await?;
35
36        let mut handoff = HandoffOptions::new(
37            "task-1",
38            "planner",
39            "reviewer",
40            "Review the retry policy patch before rollout.",
41        );
42        handoff.run_id = Some(run_id.clone());
43        handoff.requested_action = "review".to_string();
44        handoff.metadata = Some(json!({ "source": "rust-helper-example" }));
45        let handoff_response = client.handoff(handoff).await?;
46        let handoff_id = handoff_response
47            .get("handoff_id")
48            .and_then(|value| value.as_str())
49            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
50            .to_string();
51
52        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
53        feedback.run_id = Some(run_id.clone());
54        feedback.comments = "Patch looks safe for rollout.".to_string();
55        feedback.from_agent_id = Some("reviewer".to_string());
56        feedback.metadata = Some(json!({ "source": "rust-helper-example" }));
57        let feedback_response = client.feedback(feedback).await?;
58
59        let mut context = GetContextOptions::default();
60        context.run_id = Some(run_id.clone());
61        context.query = Some("What coordination artifacts were recorded for this review handoff?".to_string());
62        context.mode = Some("sections".to_string());
63        context.sections = vec!["handoffs".to_string(), "feedback".to_string()];
64        let context_response = client.get_context(context).await?;
65
66        require(
67            handoff_response
68                .get("success")
69                .and_then(|value| value.as_bool())
70                .unwrap_or(false),
71            format!("handoff failed: {handoff_response}"),
72        )?;
73        require(
74            feedback_response
75                .get("success")
76                .and_then(|value| value.as_bool())
77                .unwrap_or(false),
78            format!("feedback failed: {feedback_response}"),
79        )?;
80        let section_count = context_response
81            .get("section_summaries")
82            .and_then(|value| value.as_array())
83            .map(|items| items.len())
84            .unwrap_or(0);
85
86        metrics = json!({
87            "run_id": run_id,
88            "handoff_id": handoff_id,
89            "feedback_id": feedback_response.get("feedback_id").cloned().unwrap_or(serde_json::Value::Null),
90            "section_count": section_count,
91        });
92
93        Ok::<(), Box<dyn Error>>(())
94    }
95    .await;
96
97    if let Err(err) = scenario {
98        passed = false;
99        detail = err.to_string();
100    }
101
102    let cleanup_ok = cleanup_run(&client, &run_id).await;
103    if !cleanup_ok {
104        passed = false;
105        detail = format!("{detail} | cleanup failures");
106    }
107
108    print_summary(
109        name,
110        passed,
111        &detail,
112        &metrics,
113        started.elapsed().as_secs_f64(),
114        cleanup_ok,
115    );
116
117    if passed {
118        Ok(())
119    } else {
120        Err(boxed_error(detail))
121    }
122}
examples/public/08_multi_agent_claims_or_support_flow.rs (line 75)
11async fn main() -> Result<(), Box<dyn Error>> {
12    let name = "public_08_multi_agent_claims_or_support_flow";
13    let started = Instant::now();
14    let client = create_client().await?;
15    let run_id = new_run_id("public_claims_flow");
16    client.set_run_id(Some(run_id.clone()));
17    client.set_transport(TransportMode::Http);
18
19    let mut passed = true;
20    let mut detail = "validated multi-agent claims/support flow".to_string();
21    let mut metrics = json!({});
22
23    let scenario = async {
24        for (agent_id, role, read_scopes, write_scopes) in [
25            ("intake", "intake", vec!["fact", "archive_block"], vec!["fact", "archive_block", "trace"]),
26            ("coverage", "coverage", vec!["fact", "rule", "archive_block", "handoff", "feedback"], vec!["fact", "trace", "lesson"]),
27            ("reviewer", "reviewer", vec!["fact", "archive_block", "handoff", "feedback", "rule"], vec!["feedback", "rule"]),
28        ] {
29            let mut agent = RegisterAgentOptions::new(agent_id);
30            agent.run_id = Some(run_id.clone());
31            agent.role = role.to_string();
32            agent.read_scopes = read_scopes.into_iter().map(String::from).collect();
33            agent.write_scopes = write_scopes.into_iter().map(String::from).collect();
34            agent.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
35            client.register_agent(agent).await?;
36        }
37
38        let mut fact = RememberOptions::new("Policy P-8842 covers windshield damage with a 250 GBP deductible.");
39        fact.run_id = Some(run_id.clone());
40        fact.agent_id = Some("intake".into());
41        fact.intent = Some("fact".into());
42        fact.metadata = Some(json!({"claim_id": "CLM-8842", "source": "intake-form"}));
43        client.remember(fact).await?;
44
45        let mut archive = ArchiveOptions::new("Exact adjuster note: customer confirmed the damage happened on the motorway and no third party was involved.", "adjuster_note");
46        archive.run_id = Some(run_id.clone());
47        archive.agent_id = Some("intake".into());
48        archive.origin_agent_id = Some("intake".into());
49        archive.source_attempt_id = Some("attempt-1".into());
50        archive.source_tool = Some("claim-review".into());
51        archive.labels = vec!["claims".into(), "coverage".into()];
52        archive.family = Some("windshield".into());
53        let archived = client.archive(archive).await?;
54        let reference_id = archived.get("reference_id").and_then(|v| v.as_str()).ok_or_else(|| boxed_error(format!("archive reference missing: {archived}")))?.to_string();
55
56        let mut checkpoint = CheckpointOptions::new("Coverage verified deductible and adjuster note before escalation.");
57        checkpoint.run_id = Some(run_id.clone());
58        checkpoint.label = Some("pre-review".into());
59        checkpoint.agent_id = Some("coverage".into());
60        checkpoint.metadata = Some(json!({"claim_id": "CLM-8842"}));
61        let checkpoint_response = client.checkpoint(checkpoint).await?;
62
63        let mut handoff = HandoffOptions::new("claim-8842", "coverage", "reviewer", "Review whether the adjuster note is enough to approve the claim.");
64        handoff.run_id = Some(run_id.clone());
65        handoff.requested_action = "review".into();
66        handoff.metadata = Some(json!({"claim_id": "CLM-8842"}));
67        let handoff_response = client.handoff(handoff).await?;
68        let handoff_id = handoff_response.get("handoff_id").and_then(|v| v.as_str()).ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?.to_string();
69
70        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
71        feedback.run_id = Some(run_id.clone());
72        feedback.from_agent_id = Some("reviewer".into());
73        feedback.comments = "Deductible and adjuster note are sufficient for routing.".into();
74        feedback.metadata = Some(json!({"claim_id": "CLM-8842"}));
75        let feedback_response = client.feedback(feedback).await?;
76
77        let mut context_opts = GetContextOptions::default();
78        context_opts.run_id = Some(run_id.clone());
79        context_opts.query = Some("Prepare the final claims routing summary.".into());
80        context_opts.agent_id = Some("coverage".into());
81        context_opts.sections = vec!["archive".into(), "facts".into(), "handoffs".into(), "feedback".into()];
82        context_opts.mode = Some("sections".into());
83        let context = client.get_context(context_opts).await?;
84
85        let mut dereference = DereferenceOptions::new(reference_id.clone());
86        dereference.run_id = Some(run_id.clone());
87        dereference.agent_id = Some("coverage".into());
88        let exact = client.dereference(dereference).await?;
89
90        let mut recall = RecallOptions::new("What deductible applies and what did the adjuster confirm?");
91        recall.run_id = Some(run_id.clone());
92        recall.agent_id = Some("coverage".into());
93        recall.entry_types = vec!["fact".into(), "archive_block".into(), "feedback".into()];
94        let recall_response = client.recall(recall).await?;
95
96        require(checkpoint_response.get("success").and_then(|v| v.as_bool()).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
97        require(handoff_response.get("success").and_then(|v| v.as_bool()).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
98        require(feedback_response.get("success").and_then(|v| v.as_bool()).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
99        require(exact.get("found").and_then(|v| v.as_bool()).unwrap_or(false), format!("dereference failed: {exact}"))?;
100        let context_text = context.get("context_block").and_then(|v| v.as_str()).unwrap_or("").to_lowercase();
101        let recall_text = recall_response.get("final_answer").and_then(|v| v.as_str()).unwrap_or("").to_lowercase();
102        let has_archive_source = context
103            .get("sources")
104            .and_then(|v| v.as_array())
105            .map(|sources| {
106                sources.iter().any(|source| {
107                    source
108                        .get("entry_type")
109                        .and_then(|v| v.as_str())
110                        == Some("archive_block")
111                })
112            })
113            .unwrap_or(false);
114        let exact_refs_surfaced = context
115            .get("exact_references_surfaced")
116            .and_then(|v| v.as_u64())
117            .unwrap_or(0);
118        require(
119            context_text.contains("adjuster note")
120                || context_text.contains("motorway")
121                || has_archive_source
122                || exact_refs_surfaced > 0,
123            format!("expected explicit or telemetry-backed exact reuse in context: {context}"),
124        )?;
125        require(recall_text.contains("250") && (recall_text.contains("motorway") || recall_text.contains("third party")), format!("expected recall to include fact + archive content: {recall_response}"))?;
126
127        metrics = json!({
128            "run_id": run_id,
129            "handoff_id": handoff_id,
130            "reference_id": reference_id,
131            "feedback_id": feedback_response.get("feedback_id").cloned().unwrap_or(serde_json::Value::Null),
132        });
133        Ok::<(), Box<dyn Error>>(())
134    }
135    .await;
136
137    if let Err(err) = scenario {
138        passed = false;
139        detail = err.to_string();
140    }
141
142    let cleanup_ok = cleanup_run(&client, &run_id).await;
143    if !cleanup_ok {
144        passed = false;
145        detail = format!("{detail} | cleanup failures");
146    }
147
148    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
149    if passed { Ok(()) } else { Err(boxed_error(detail)) }
150}
examples/public/10_full_learning_loop_smoke.rs (line 172)
16async fn main() -> Result<(), Box<dyn Error>> {
17    let name = "public_10_full_learning_loop_smoke";
18    let started = Instant::now();
19    let client = create_client().await?;
20    let run_id = new_run_id("public_10_full_learning_loop_smoke");
21    client.set_run_id(Some(run_id.clone()));
22    client.set_transport(TransportMode::Http);
23
24    let mut passed = true;
25    let mut detail = "validated all helper flows".to_string();
26    let mut metrics = json!({});
27
28    let scenario = async {
29        let mut remember = RememberOptions::new("Policy limit is 5000 and claimant city is Leeds.");
30        remember.run_id = Some(run_id.clone());
31        remember.agent_id = Some("planner".to_string());
32        remember.intent = Some("fact".to_string());
33        remember.metadata = Some(json!({"suite": "all-helpers", "family": "claims"}));
34        remember.importance = Some("high".to_string());
35        remember.occurrence_time = Some(std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as i64 - 86400);
36        let remember_response = client.remember(remember).await?;
37
38        let mut lesson = RememberOptions::new("If city is missing from the latest step, check stored claim facts before escalating.");
39        lesson.run_id = Some(run_id.clone());
40        lesson.agent_id = Some("planner".to_string());
41        lesson.intent = Some("lesson".to_string());
42        lesson.lesson_type = Some("success".to_string());
43        lesson.lesson_scope = Some("session".to_string());
44        lesson.lesson_importance = Some("high".to_string());
45        let lesson_response = client.remember(lesson).await?;
46
47        let mut mental_model = RememberOptions::new(
48            "Claims case overview: Policy limit 5000 GBP, claimant city Leeds, \
49             missing-city branch resolved via stored claim facts. Lesson: check stored facts before escalating.",
50        );
51        mental_model.run_id = Some(run_id.clone());
52        mental_model.agent_id = Some("planner".to_string());
53        mental_model.intent = Some("mental_model".to_string());
54        mental_model.importance = Some("critical".to_string());
55        mental_model.metadata = Some(json!({"suite": "all-helpers", "entity": "claims-case", "consolidated": true}));
56        let mental_model_response = client.remember(mental_model).await?;
57
58        let mut recall = RecallOptions::new("What is the policy limit?");
59        recall.run_id = Some(run_id.clone());
60        recall.agent_id = Some("planner".to_string());
61        recall.limit = 5;
62        let recall_response = client.recall(recall).await?;
63
64        let mut context = GetContextOptions::default();
65        context.run_id = Some(run_id.clone());
66        context.query = Some("Prepare a short adjuster summary".to_string());
67        context.agent_id = Some("planner".to_string());
68        context.limit = Some(6);
69        context.max_token_budget = Some(700);
70        let context_response = client.get_context(context).await?;
71
72        let mut health = MemoryHealthOptions::default();
73        health.run_id = Some(run_id.clone());
74        health.limit = 50;
75        let health_response = client.memory_health(health).await?;
76
77        let mut diagnose = DiagnoseOptions::new("policy limit lookup returned empty");
78        diagnose.run_id = Some(run_id.clone());
79        diagnose.error_type = Some("retrieval".to_string());
80        diagnose.limit = 5;
81        let diagnose_response = client.diagnose(diagnose).await?;
82
83        let mut reflect = ReflectOptions::default();
84        reflect.run_id = Some(run_id.clone());
85        let reflect_response = client.reflect(reflect).await?;
86
87        let mut register = RegisterAgentOptions::new("planner");
88        register.run_id = Some(run_id.clone());
89        register.role = "planner".to_string();
90        register.read_scopes = vec!["fact".into(), "lesson".into(), "rule".into(), "mental_model".into(), "archive_block".into(), "handoff".into(), "feedback".into()];
91        register.write_scopes = vec!["fact".into(), "trace".into(), "lesson".into(), "observation".into(), "archive_block".into()];
92        register.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
93        let register_response = client.register_agent(register).await?;
94
95        let mut list_agents = ListAgentsOptions::default();
96        list_agents.run_id = Some(run_id.clone());
97        let agents_response = client.list_agents(list_agents).await?;
98
99        let mut archive = ArchiveOptions::new(
100            "Exact adjuster note: claimant confirmed city is Leeds during triage.",
101            "adjuster_note",
102        );
103        archive.run_id = Some(run_id.clone());
104        archive.agent_id = Some("planner".to_string());
105        archive.origin_agent_id = Some("planner".to_string());
106        archive.source_attempt_id = Some("attempt-1".to_string());
107        archive.source_tool = Some("phone_call".to_string());
108        archive.labels = vec!["claims".to_string(), "triage".to_string()];
109        archive.family = Some("claims-adjustment".to_string());
110        archive.metadata = Some(json!({"case": "all-helpers"}));
111        let archive_response = client.archive(archive).await?;
112        let reference_id = archive_response
113            .get("reference_id")
114            .and_then(Value::as_str)
115            .ok_or_else(|| boxed_error(format!("archive reference missing: {archive_response}")))?
116            .to_string();
117
118        let mut dereference = DereferenceOptions::new(reference_id.clone());
119        dereference.run_id = Some(run_id.clone());
120        dereference.agent_id = Some("planner".to_string());
121        let dereference_response = client.dereference(dereference).await?;
122
123        let mut checkpoint = CheckpointOptions::new("Planner captured claim facts before window compaction.");
124        checkpoint.run_id = Some(run_id.clone());
125        checkpoint.label = Some("pre-compaction".to_string());
126        checkpoint.metadata = Some(json!({"stage": "analysis"}));
127        checkpoint.agent_id = Some("planner".to_string());
128        let checkpoint_response = client.checkpoint(checkpoint).await?;
129
130        let lessons_response = client.control.lessons(json!({"run_id": run_id, "limit": 20})).await?;
131        let lesson_id = lessons_response
132            .get("lessons")
133            .and_then(Value::as_array)
134            .and_then(|items| items.iter().find_map(|item| item.get("id").and_then(Value::as_str)))
135            .ok_or_else(|| boxed_error(format!("expected lesson id for outcome flow: {lessons_response}")))?
136            .to_string();
137
138        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
139        outcome.run_id = Some(run_id.clone());
140        outcome.signal = 0.75;
141        outcome.rationale = "Planner reused stored claim fact and resolved the missing-city branch.".to_string();
142        outcome.agent_id = Some("planner".to_string());
143        let outcome_response = client.record_outcome(outcome).await?;
144
145        let mut strategies = SurfaceStrategiesOptions::default();
146        strategies.run_id = Some(run_id.clone());
147        strategies.lesson_types = vec!["success".to_string(), "rule".to_string()];
148        strategies.max_strategies = 5;
149        let strategies_response = client.surface_strategies(strategies).await?;
150
151        let mut handoff = HandoffOptions::new(
152            "claim-1",
153            "planner",
154            "reviewer",
155            "Review whether the stored claimant city is sufficient for routing.",
156        );
157        handoff.run_id = Some(run_id.clone());
158        handoff.requested_action = "review".to_string();
159        handoff.metadata = Some(json!({"team": "claims"}));
160        let handoff_response = client.handoff(handoff).await?;
161        let handoff_id = handoff_response
162            .get("handoff_id")
163            .and_then(Value::as_str)
164            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
165            .to_string();
166
167        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
168        feedback.run_id = Some(run_id.clone());
169        feedback.comments = "Stored fact is sufficient; proceed without escalation.".to_string();
170        feedback.from_agent_id = Some("reviewer".to_string());
171        feedback.metadata = Some(json!({"team": "claims"}));
172        let feedback_response = client.feedback(feedback).await?;
173
174        require(remember_response.get("job_id").is_some() || remember_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("remember failed: {remember_response}"))?;
175        require(mental_model_response.get("job_id").is_some() || mental_model_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("mental_model remember failed: {mental_model_response}"))?;
176        require(lesson_response.get("job_id").is_some() || lesson_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("lesson remember failed: {lesson_response}"))?;
177        require(recall_response.get("final_answer").is_some() || recall_response.get("evidence").is_some(), format!("recall failed: {recall_response}"))?;
178        require(context_response.get("sources").and_then(Value::as_array).is_some(), format!("context malformed: {context_response}"))?;
179        require(health_response.get("entry_counts").and_then(Value::as_object).is_some(), format!("memory_health malformed: {health_response}"))?;
180        require(diagnose_response.get("failure_lessons").and_then(Value::as_array).is_some(), format!("diagnose malformed: {diagnose_response}"))?;
181        require(reflect_response.get("lessons").and_then(Value::as_array).is_some(), format!("reflect malformed: {reflect_response}"))?;
182        require(register_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("register_agent failed: {register_response}"))?;
183        require(agents_response.get("agents").and_then(Value::as_array).map(|items| !items.is_empty()).unwrap_or(false), format!("list_agents failed: {agents_response}"))?;
184        require(archive_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("archive failed: {archive_response}"))?;
185        require(dereference_response.get("found").and_then(Value::as_bool).unwrap_or(false), format!("dereference failed: {dereference_response}"))?;
186        require(checkpoint_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
187        require(outcome_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("record_outcome failed: {outcome_response}"))?;
188        require(strategies_response.get("strategies").and_then(Value::as_array).is_some(), format!("surface_strategies malformed: {strategies_response}"))?;
189        require(handoff_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
190        require(feedback_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
191
192        let strategy_count = strategies_response
193            .get("strategies")
194            .and_then(Value::as_array)
195            .map(|items| items.len())
196            .unwrap_or(0);
197        let agent_count = agents_response
198            .get("agents")
199            .and_then(Value::as_array)
200            .map(|items| items.len())
201            .unwrap_or(0);
202        let lesson_count = lessons_response
203            .get("lessons")
204            .and_then(Value::as_array)
205            .map(|items| items.len())
206            .unwrap_or(0);
207
208        metrics = json!({
209            "run_id": run_id,
210            "agent_count": agent_count,
211            "strategy_count": strategy_count,
212            "reference_id": reference_id,
213            "lesson_count": lesson_count,
214        });
215
216        Ok::<(), Box<dyn Error>>(())
217    }
218    .await;
219
220    if let Err(err) = scenario {
221        passed = false;
222        detail = err.to_string();
223    }
224
225    let cleanup_ok = cleanup_run(&client, &run_id).await;
226    if !cleanup_ok {
227        passed = false;
228        detail = format!("{detail} | cleanup failures");
229    }
230
231    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
232
233    if passed { Ok(()) } else { Err(boxed_error(detail)) }
234}
examples/helper_all_helpers.rs (line 160)
16async fn main() -> Result<(), Box<dyn Error>> {
17    let name = "helper_all_helpers";
18    let started = Instant::now();
19    let client = create_client().await?;
20    let run_id = new_run_id("helper_all_helpers");
21    client.set_run_id(Some(run_id.clone()));
22    client.set_transport(TransportMode::Http);
23
24    let mut passed = true;
25    let mut detail = "validated all helper flows".to_string();
26    let mut metrics = json!({});
27
28    let scenario = async {
29        let mut remember = RememberOptions::new("Policy limit is 5000 and claimant city is Leeds.");
30        remember.run_id = Some(run_id.clone());
31        remember.agent_id = Some("planner".to_string());
32        remember.intent = Some("fact".to_string());
33        remember.metadata = Some(json!({"suite": "all-helpers", "family": "claims"}));
34        remember.importance = Some("high".to_string());
35        let remember_response = client.remember(remember).await?;
36
37        let mut lesson = RememberOptions::new("If city is missing from the latest step, check stored claim facts before escalating.");
38        lesson.run_id = Some(run_id.clone());
39        lesson.agent_id = Some("planner".to_string());
40        lesson.intent = Some("lesson".to_string());
41        lesson.lesson_type = Some("success".to_string());
42        lesson.lesson_scope = Some("session".to_string());
43        lesson.lesson_importance = Some("high".to_string());
44        let lesson_response = client.remember(lesson).await?;
45
46        let mut recall = RecallOptions::new("What is the policy limit?");
47        recall.run_id = Some(run_id.clone());
48        recall.agent_id = Some("planner".to_string());
49        recall.limit = 5;
50        let recall_response = client.recall(recall).await?;
51
52        let mut context = GetContextOptions::default();
53        context.run_id = Some(run_id.clone());
54        context.query = Some("Prepare a short adjuster summary".to_string());
55        context.agent_id = Some("planner".to_string());
56        context.limit = Some(6);
57        context.max_token_budget = Some(700);
58        let context_response = client.get_context(context).await?;
59
60        let mut health = MemoryHealthOptions::default();
61        health.run_id = Some(run_id.clone());
62        health.limit = 50;
63        let health_response = client.memory_health(health).await?;
64
65        let mut diagnose = DiagnoseOptions::new("policy limit lookup returned empty");
66        diagnose.run_id = Some(run_id.clone());
67        diagnose.error_type = Some("retrieval".to_string());
68        diagnose.limit = 5;
69        let diagnose_response = client.diagnose(diagnose).await?;
70
71        let mut reflect = ReflectOptions::default();
72        reflect.run_id = Some(run_id.clone());
73        let reflect_response = client.reflect(reflect).await?;
74
75        let mut register = RegisterAgentOptions::new("planner");
76        register.run_id = Some(run_id.clone());
77        register.role = "planner".to_string();
78        register.read_scopes = vec!["fact".into(), "lesson".into(), "rule".into(), "archive_block".into(), "handoff".into(), "feedback".into()];
79        register.write_scopes = vec!["fact".into(), "trace".into(), "lesson".into(), "observation".into(), "archive_block".into()];
80        register.shared_memory_lanes = vec!["knowledge".into(), "history".into()];
81        let register_response = client.register_agent(register).await?;
82
83        let mut list_agents = ListAgentsOptions::default();
84        list_agents.run_id = Some(run_id.clone());
85        let agents_response = client.list_agents(list_agents).await?;
86
87        let mut archive = ArchiveOptions::new(
88            "Exact adjuster note: claimant confirmed city is Leeds during triage.",
89            "adjuster_note",
90        );
91        archive.run_id = Some(run_id.clone());
92        archive.agent_id = Some("planner".to_string());
93        archive.origin_agent_id = Some("planner".to_string());
94        archive.source_attempt_id = Some("attempt-1".to_string());
95        archive.source_tool = Some("phone_call".to_string());
96        archive.labels = vec!["claims".to_string(), "triage".to_string()];
97        archive.family = Some("claims-adjustment".to_string());
98        archive.metadata = Some(json!({"case": "all-helpers"}));
99        let archive_response = client.archive(archive).await?;
100        let reference_id = archive_response
101            .get("reference_id")
102            .and_then(Value::as_str)
103            .ok_or_else(|| boxed_error(format!("archive reference missing: {archive_response}")))?
104            .to_string();
105
106        let mut dereference = DereferenceOptions::new(reference_id.clone());
107        dereference.run_id = Some(run_id.clone());
108        dereference.agent_id = Some("planner".to_string());
109        let dereference_response = client.dereference(dereference).await?;
110
111        let mut checkpoint = CheckpointOptions::new("Planner captured claim facts before window compaction.");
112        checkpoint.run_id = Some(run_id.clone());
113        checkpoint.label = Some("pre-compaction".to_string());
114        checkpoint.metadata = Some(json!({"stage": "analysis"}));
115        checkpoint.agent_id = Some("planner".to_string());
116        let checkpoint_response = client.checkpoint(checkpoint).await?;
117
118        let lessons_response = client.control.lessons(json!({"run_id": run_id, "limit": 20})).await?;
119        let lesson_id = lessons_response
120            .get("lessons")
121            .and_then(Value::as_array)
122            .and_then(|items| items.iter().find_map(|item| item.get("id").and_then(Value::as_str)))
123            .ok_or_else(|| boxed_error(format!("expected lesson id for outcome flow: {lessons_response}")))?
124            .to_string();
125
126        let mut outcome = RecordOutcomeOptions::new(lesson_id, "success");
127        outcome.run_id = Some(run_id.clone());
128        outcome.signal = 0.75;
129        outcome.rationale = "Planner reused stored claim fact and resolved the missing-city branch.".to_string();
130        outcome.agent_id = Some("planner".to_string());
131        let outcome_response = client.record_outcome(outcome).await?;
132
133        let mut strategies = SurfaceStrategiesOptions::default();
134        strategies.run_id = Some(run_id.clone());
135        strategies.lesson_types = vec!["success".to_string(), "rule".to_string()];
136        strategies.max_strategies = 5;
137        let strategies_response = client.surface_strategies(strategies).await?;
138
139        let mut handoff = HandoffOptions::new(
140            "claim-1",
141            "planner",
142            "reviewer",
143            "Review whether the stored claimant city is sufficient for routing.",
144        );
145        handoff.run_id = Some(run_id.clone());
146        handoff.requested_action = "review".to_string();
147        handoff.metadata = Some(json!({"team": "claims"}));
148        let handoff_response = client.handoff(handoff).await?;
149        let handoff_id = handoff_response
150            .get("handoff_id")
151            .and_then(Value::as_str)
152            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
153            .to_string();
154
155        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
156        feedback.run_id = Some(run_id.clone());
157        feedback.comments = "Stored fact is sufficient; proceed without escalation.".to_string();
158        feedback.from_agent_id = Some("reviewer".to_string());
159        feedback.metadata = Some(json!({"team": "claims"}));
160        let feedback_response = client.feedback(feedback).await?;
161
162        let scratch_run = format!("{run_id}_forget");
163        let mut scratch = RememberOptions::new("Scratch run for forget helper coverage.");
164        scratch.run_id = Some(scratch_run.clone());
165        scratch.agent_id = Some("planner".to_string());
166        scratch.intent = Some("fact".to_string());
167        scratch.metadata = Some(json!({"suite": "all-helpers", "temporary": true}));
168        let scratch_response = client.remember(scratch).await?;
169
170        let forget_response = client
171            .forget(ForgetOptions::for_run(scratch_run.clone()))
172            .await?;
173
174        let mut forgotten = RecallOptions::new("What temporary scratch fact exists?");
175        forgotten.run_id = Some(scratch_run.clone());
176        forgotten.limit = 3;
177        let forgotten_response = client.recall(forgotten).await?;
178
179        require(remember_response.get("job_id").is_some() || remember_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("remember failed: {remember_response}"))?;
180        require(lesson_response.get("job_id").is_some() || lesson_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("lesson remember failed: {lesson_response}"))?;
181        require(recall_response.get("final_answer").is_some() || recall_response.get("evidence").is_some(), format!("recall failed: {recall_response}"))?;
182        require(context_response.get("sources").and_then(Value::as_array).is_some(), format!("context malformed: {context_response}"))?;
183        require(health_response.get("entry_counts").and_then(Value::as_object).is_some(), format!("memory_health malformed: {health_response}"))?;
184        require(diagnose_response.get("failure_lessons").and_then(Value::as_array).is_some(), format!("diagnose malformed: {diagnose_response}"))?;
185        require(reflect_response.get("lessons").and_then(Value::as_array).is_some(), format!("reflect malformed: {reflect_response}"))?;
186        require(register_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("register_agent failed: {register_response}"))?;
187        require(agents_response.get("agents").and_then(Value::as_array).map(|items| !items.is_empty()).unwrap_or(false), format!("list_agents failed: {agents_response}"))?;
188        require(archive_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("archive failed: {archive_response}"))?;
189        require(dereference_response.get("found").and_then(Value::as_bool).unwrap_or(false), format!("dereference failed: {dereference_response}"))?;
190        require(checkpoint_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("checkpoint failed: {checkpoint_response}"))?;
191        require(outcome_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("record_outcome failed: {outcome_response}"))?;
192        require(strategies_response.get("strategies").and_then(Value::as_array).is_some(), format!("surface_strategies malformed: {strategies_response}"))?;
193        require(handoff_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("handoff failed: {handoff_response}"))?;
194        require(feedback_response.get("success").and_then(Value::as_bool).unwrap_or(false), format!("feedback failed: {feedback_response}"))?;
195        require(scratch_response.get("job_id").is_some() || scratch_response.get("accepted").and_then(Value::as_bool).unwrap_or(false), format!("scratch remember failed: {scratch_response}"))?;
196        require(forget_response.get("success").and_then(Value::as_bool).unwrap_or(true), format!("forget failed: {forget_response}"))?;
197        let scratch_fact_visible = forgotten_response
198            .get("evidence")
199            .and_then(Value::as_array)
200            .map(|items| {
201                items.iter().any(|item| {
202                    item.get("run_id").and_then(Value::as_str) == Some(scratch_run.as_str())
203                        || item
204                            .get("content")
205                            .and_then(Value::as_str)
206                            .map(|content| {
207                                content
208                                    .to_ascii_lowercase()
209                                    .contains("scratch run for forget helper coverage")
210                            })
211                            .unwrap_or(false)
212                })
213            })
214            .unwrap_or(false);
215        require(!scratch_fact_visible, format!("scratch fact should be forgotten even if same-user lessons still surface: {forgotten_response}"))?;
216
217        let strategy_count = strategies_response
218            .get("strategies")
219            .and_then(Value::as_array)
220            .map(|items| items.len())
221            .unwrap_or(0);
222        let agent_count = agents_response
223            .get("agents")
224            .and_then(Value::as_array)
225            .map(|items| items.len())
226            .unwrap_or(0);
227        let lesson_count = lessons_response
228            .get("lessons")
229            .and_then(Value::as_array)
230            .map(|items| items.len())
231            .unwrap_or(0);
232
233        metrics = json!({
234            "run_id": run_id,
235            "agent_count": agent_count,
236            "strategy_count": strategy_count,
237            "reference_id": reference_id,
238            "lesson_count": lesson_count,
239            "forgotten_run": scratch_run,
240        });
241
242        Ok::<(), Box<dyn Error>>(())
243    }
244    .await;
245
246    if let Err(err) = scenario {
247        passed = false;
248        detail = err.to_string();
249    }
250
251    let cleanup_ok = cleanup_run(&client, &run_id).await;
252    if !cleanup_ok {
253        passed = false;
254        detail = format!("{detail} | cleanup failures");
255    }
256
257    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
258
259    if passed { Ok(()) } else { Err(boxed_error(detail)) }
260}

Trait Implementations§

Source§

impl Clone for Client

Source§

fn clone(&self) -> Client

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoRequest<T> for T

Source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more