pub struct RecallOptions {Show 16 fields
pub run_id: Option<String>,
pub query: String,
pub schema: Option<String>,
pub mode: String,
pub direct_lane: String,
pub include_linked_runs: bool,
pub limit: u64,
pub embedding: Vec<f32>,
pub entry_types: Vec<String>,
pub include_working_memory: bool,
pub user_id: Option<String>,
pub agent_id: Option<String>,
pub lane: Option<String>,
pub min_timestamp: Option<i64>,
pub max_timestamp: Option<i64>,
pub budget: Option<String>,
}Fields§
§run_id: Option<String>§query: String§schema: Option<String>§mode: String§direct_lane: String§include_linked_runs: bool§limit: u64§embedding: Vec<f32>§entry_types: Vec<String>§include_working_memory: bool§user_id: Option<String>§agent_id: Option<String>§lane: Option<String>§min_timestamp: Option<i64>Temporal range filter lower bound (unix seconds, inclusive).
max_timestamp: Option<i64>Temporal range filter upper bound (unix seconds, inclusive).
budget: Option<String>Search budget tier: “low”, “mid”, “high”.
Implementations§
Source§impl RecallOptions
impl RecallOptions
Sourcepub fn new(query: impl Into<String>) -> Self
pub fn new(query: impl Into<String>) -> Self
Examples found in repository?
examples/helper_remember_recall.rs (line 44)
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 65)
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 (lines 59-61)
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 66)
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 90)
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 58)
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:
Trait Implementations§
Source§impl Clone for RecallOptions
impl Clone for RecallOptions
Source§fn clone(&self) -> RecallOptions
fn clone(&self) -> RecallOptions
Returns a duplicate of the value. Read more
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moreAuto Trait Implementations§
impl Freeze for RecallOptions
impl RefUnwindSafe for RecallOptions
impl Send for RecallOptions
impl Sync for RecallOptions
impl Unpin for RecallOptions
impl UnsafeUnpin for RecallOptions
impl UnwindSafe for RecallOptions
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