pub struct Client {
pub auth: AuthClient,
pub core: CoreClient,
pub control: ControlClient,
/* private fields */
}Fields§
§auth: AuthClient§core: CoreClient§control: ControlClientImplementations§
Source§impl Client
impl Client
Sourcepub fn new(config: ClientConfig) -> Result<Self>
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}Sourcepub fn set_api_key(&self, api_key: Option<String>)
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}pub fn set_token(&self, token: Option<String>)
Sourcepub fn set_run_id(&self, run_id: Option<String>)
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
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}Additional examples can be found in:
- examples/control_state_structured_variables.rs
- examples/internal/control_ingest_batch_job_lifecycle.rs
- examples/helper_archive_dereference.rs
- examples/public/07_archive_dereference.rs
- examples/public/04_memory_health_and_diagnose.rs
- examples/helper_context_diagnose_memory_health.rs
- examples/helper_handoff_feedback.rs
- examples/public/06_handoff_feedback.rs
- examples/public/01_remember_recall.rs
- examples/control_ingest_idempotency.rs
- examples/internal/upsert_key_idempotency.rs
- examples/helper_mas_learning_loop.rs
- examples/public/03_checkpoint_reflect_outcome.rs
- examples/public/09_user_scoping_and_isolation.rs
- examples/public/02_context_budget_and_sections.rs
- examples/public/11_temporal_entity_mental_model.rs
- examples/public/05_agent_registration_and_scoped_access.rs
- examples/control_batch_insert_semantic_direct.rs
- examples/control_ingest_job_lifecycle.rs
- examples/control_query_agent_routed.rs
- examples/internal/legacy_state_compatibility.rs
- examples/control_legacy_state_compat.rs
- examples/public/08_multi_agent_claims_or_support_flow.rs
- examples/public/10_full_learning_loop_smoke.rs
- examples/helper_all_helpers.rs
Sourcepub fn set_transport(&self, transport: TransportMode)
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
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}Additional examples can be found in:
- examples/helper_remember_recall.rs
- examples/control_state_structured_variables.rs
- examples/internal/control_ingest_batch_job_lifecycle.rs
- examples/helper_archive_dereference.rs
- examples/public/07_archive_dereference.rs
- examples/public/04_memory_health_and_diagnose.rs
- examples/helper_context_diagnose_memory_health.rs
- examples/helper_handoff_feedback.rs
- examples/public/06_handoff_feedback.rs
- examples/public/01_remember_recall.rs
- examples/control_ingest_idempotency.rs
- examples/internal/upsert_key_idempotency.rs
- examples/helper_mas_learning_loop.rs
- examples/public/03_checkpoint_reflect_outcome.rs
- examples/public/09_user_scoping_and_isolation.rs
- examples/public/02_context_budget_and_sections.rs
- examples/public/11_temporal_entity_mental_model.rs
- examples/public/05_agent_registration_and_scoped_access.rs
- examples/control_batch_insert_semantic_direct.rs
- examples/control_ingest_job_lifecycle.rs
- examples/control_query_agent_routed.rs
- examples/internal/legacy_state_compatibility.rs
- examples/control_legacy_state_compat.rs
- examples/public/08_multi_agent_claims_or_support_flow.rs
- examples/public/10_full_learning_loop_smoke.rs
- examples/helper_all_helpers.rs
Source§impl Client
impl Client
Sourcepub async fn remember(&self, options: RememberOptions) -> Result<Value>
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
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}Additional examples can be found in:
- examples/public/03_checkpoint_reflect_outcome.rs
- examples/public/09_user_scoping_and_isolation.rs
- examples/public/02_context_budget_and_sections.rs
- examples/public/11_temporal_entity_mental_model.rs
- examples/public/05_agent_registration_and_scoped_access.rs
- examples/public/08_multi_agent_claims_or_support_flow.rs
- examples/public/10_full_learning_loop_smoke.rs
- examples/helper_all_helpers.rs
Sourcepub async fn recall(&self, options: RecallOptions) -> Result<Value>
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
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}Additional examples can be found in:
Sourcepub async fn get_context(&self, options: GetContextOptions) -> Result<Value>
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
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}Sourcepub async fn archive(&self, options: ArchiveOptions) -> Result<Value>
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
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}pub async fn archive_block(&self, options: ArchiveOptions) -> Result<Value>
Sourcepub async fn dereference(&self, options: DereferenceOptions) -> Result<Value>
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
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}Sourcepub async fn memory_health(&self, options: MemoryHealthOptions) -> Result<Value>
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
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}Sourcepub async fn diagnose(&self, options: DiagnoseOptions) -> Result<Value>
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
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}Sourcepub async fn reflect(&self, options: ReflectOptions) -> Result<Value>
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
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}Sourcepub async fn forget(&self, options: ForgetOptions) -> Result<Value>
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}Sourcepub async fn checkpoint(&self, options: CheckpointOptions) -> Result<Value>
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
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}Sourcepub async fn register_agent(
&self,
options: RegisterAgentOptions,
) -> Result<Value>
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
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}Additional examples can be found in:
Sourcepub async fn list_agents(&self, options: ListAgentsOptions) -> Result<Value>
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
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}Sourcepub async fn record_outcome(
&self,
options: RecordOutcomeOptions,
) -> Result<Value>
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
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}pub async fn record_step_outcome( &self, options: RecordStepOutcomeOptions, ) -> Result<Value>
Sourcepub async fn surface_strategies(
&self,
options: SurfaceStrategiesOptions,
) -> Result<Value>
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
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}Sourcepub async fn handoff(&self, options: HandoffOptions) -> Result<Value>
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
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}Sourcepub async fn feedback(&self, options: FeedbackOptions) -> Result<Value>
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
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§
Auto Trait Implementations§
impl Freeze for Client
impl !RefUnwindSafe for Client
impl Send for Client
impl Sync for Client
impl Unpin for Client
impl UnsafeUnpin for Client
impl !UnwindSafe for Client
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
Wrap the input message
T in a tonic::Request