pub fn replay(store: &MemoryStore, run_id: &str) -> Result<ReplaySummary>Examples found in repository?
examples/three_minute_demo.rs (line 99)
20fn main() -> agentledger::Result<()> {
21 let mut runtime = Runtime::new();
22 runtime.register_tool(
23 ToolSpec::new(
24 "ticket.create",
25 Box::new(|args| {
26 Ok(Value::Object(state(&[
27 ("external_id", "TICKET-1".into()),
28 ("title", args["title"].clone()),
29 ])))
30 }),
31 )
32 .side_effect("external_write")
33 .idempotency_required(true)
34 .input_schema(Value::Object(state(&[
35 ("type", "object".into()),
36 (
37 "required",
38 Value::Array(vec![Value::String("title".to_string())]),
39 ),
40 ]))),
41 );
42 let (run_id, _) = runtime.create_run(State::new());
43
44 let first_claim = runtime.store.claim_step("worker-before-crash", &run_id, 60.0)?;
45 let first_ctx = AgentContext {
46 run_id: run_id.clone(),
47 session_id: first_claim.session_id.clone(),
48 step_id: first_claim.step_id.clone(),
49 agent_role: "SupportAgent".to_string(),
50 lease_token: first_claim.lease_token.clone(),
51 attempt: first_claim.attempt,
52 state_version: first_claim.state_version,
53 pending_patch: State::new(),
54 };
55 let ticket = runtime.call_tool(
56 &first_ctx,
57 "ticket.create",
58 state(&[
59 ("title", "Investigate failed payment".into()),
60 ("_logical_operation", "open-payment-ticket".into()),
61 ]),
62 )?;
63 runtime.store.mark_retry(
64 &run_id,
65 &first_ctx.step_id,
66 "RetryableAgentError",
67 "after external ticket create, before state commit",
68 );
69
70 let second_claim = runtime.store.claim_step("worker-after-restart", &run_id, 60.0)?;
71 let mut second_ctx = AgentContext {
72 run_id: run_id.clone(),
73 session_id: second_claim.session_id.clone(),
74 step_id: second_claim.step_id.clone(),
75 agent_role: "SupportAgent".to_string(),
76 lease_token: second_claim.lease_token.clone(),
77 attempt: second_claim.attempt,
78 state_version: second_claim.state_version,
79 pending_patch: State::new(),
80 };
81 let replayed_ticket = runtime.call_tool(
82 &second_ctx,
83 "ticket.create",
84 state(&[
85 ("title", "Investigate failed payment".into()),
86 ("_logical_operation", "open-payment-ticket".into()),
87 ]),
88 )?;
89 second_ctx.write_state("ticket", replayed_ticket);
90 second_ctx.write_state("recovered", true.into());
91 runtime.store.commit_state_patch(
92 &run_id,
93 &second_ctx.step_id,
94 &second_ctx.lease_token,
95 second_ctx.state_version,
96 second_ctx.pending_patch,
97 )?;
98
99 let summary = replay(&runtime.store, &run_id)?;
100 let ledger = runtime.store.ledger(&run_id);
101 let final_state = runtime.store.final_state(&run_id)?;
102 println!(
103 "{{\n \"run_id\": \"{}\",\n \"first_attempt_ok\": false,\n \"second_attempt_ok\": true,\n \"external_ticket_count\": 1,\n \"actual_tool_executions\": 1,\n \"tool_ledger_count\": {},\n \"tool_ledger_status\": \"{}\",\n \"first_ticket_external_id\": \"{}\",\n \"final_state_recovered\": {},\n \"replay\": {{\n \"safe\": {},\n \"event_count\": {},\n \"tool_call_count\": {}\n }}\n}}",
104 run_id,
105 ledger.len(),
106 ledger.first().map(|row| row.status.as_str()).unwrap_or(""),
107 get_string(&ticket, "external_id"),
108 final_state.get("recovered") == Some(&Value::Bool(true)),
109 summary.replay_safe,
110 summary.event_count,
111 summary.tool_call_count
112 );
113 Ok(())
114}