pub struct AgentContext {
pub run_id: String,
pub session_id: String,
pub step_id: String,
pub agent_role: String,
pub lease_token: String,
pub attempt: u64,
pub state_version: u64,
pub pending_patch: State,
}Fields§
§run_id: String§session_id: String§step_id: String§agent_role: String§lease_token: String§attempt: u64§state_version: u64§pending_patch: StateImplementations§
Source§impl AgentContext
impl AgentContext
Sourcepub fn write_state(&mut self, key: &str, value: Value)
pub fn write_state(&mut self, key: &str, value: Value)
Examples found in repository?
examples/three_minute_demo.rs (line 89)
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}More examples
examples/mcp_governance.rs (line 139)
33fn main() -> agentledger::Result<()> {
34 let mut runtime = Runtime::new();
35 runtime.set_sandbox(Box::new(DemoSandboxExecutor));
36 let mut server = InMemoryMCPToolServer::new();
37 server.add_tool(
38 state(&[
39 ("name", "mcp.github.create_pr".into()),
40 (
41 "inputSchema",
42 Value::Object(state(&[
43 ("type", "object".into()),
44 (
45 "required",
46 Value::Array(vec![Value::String("title".to_string())]),
47 ),
48 (
49 "properties",
50 Value::Object(state(&[(
51 "title",
52 Value::Object(state(&[
53 ("type", "string".into()),
54 ("minLength", 1_i64.into()),
55 ])),
56 )])),
57 ),
58 ])),
59 ),
60 (
61 "annotations",
62 Value::Object(state(&[
63 ("side_effect", "external_write".into()),
64 ("risk_level", "high".into()),
65 ("idempotency_required", true.into()),
66 ("approval_required", true.into()),
67 ("sandbox_required", true.into()),
68 (
69 "sandbox_policy",
70 Value::Object(state(&[
71 ("network", "deny".into()),
72 ("filesystem", "read-only".into()),
73 ])),
74 ),
75 ])),
76 ),
77 ]),
78 create_pr,
79 );
80 let adapter = MCPToolAdapter { client_call: create_pr };
81 for descriptor in server.list_tools() {
82 runtime.register_tool(adapter.tool_spec_from_descriptor(&descriptor));
83 }
84
85 let (run_id, _) = runtime.create_run(State::new());
86 let first_claim = runtime.store.claim_step("worker-before-approval", &run_id, 60.0)?;
87 let first_ctx = AgentContext {
88 run_id: run_id.clone(),
89 session_id: first_claim.session_id.clone(),
90 step_id: first_claim.step_id.clone(),
91 agent_role: "MCPAgent".to_string(),
92 lease_token: first_claim.lease_token.clone(),
93 attempt: first_claim.attempt,
94 state_version: first_claim.state_version,
95 pending_patch: State::new(),
96 };
97 let first = runtime.call_tool(
98 &first_ctx,
99 "mcp.github.create_pr",
100 state(&[
101 ("title", "Update runtime docs".into()),
102 ("_logical_operation", "docs-pr".into()),
103 ]),
104 );
105 let approval_id = first
106 .unwrap_err()
107 .0
108 .trim_start_matches("approval required:")
109 .to_string();
110 runtime.store.mark_waiting_human(
111 &run_id,
112 &first_ctx.step_id,
113 "approval required for tool mcp.github.create_pr",
114 &approval_id,
115 );
116 runtime
117 .store
118 .approve_request(&approval_id, "maintainer", "demo approval")?;
119
120 let second_claim = runtime.store.claim_step("worker-after-approval", &run_id, 60.0)?;
121 let mut second_ctx = AgentContext {
122 run_id: run_id.clone(),
123 session_id: second_claim.session_id.clone(),
124 step_id: second_claim.step_id.clone(),
125 agent_role: "MCPAgent".to_string(),
126 lease_token: second_claim.lease_token.clone(),
127 attempt: second_claim.attempt,
128 state_version: second_claim.state_version,
129 pending_patch: State::new(),
130 };
131 let result = runtime.call_tool(
132 &second_ctx,
133 "mcp.github.create_pr",
134 state(&[
135 ("title", "Update runtime docs".into()),
136 ("_logical_operation", "docs-pr".into()),
137 ]),
138 )?;
139 second_ctx.write_state("pull_request", result);
140 runtime.store.commit_state_patch(
141 &run_id,
142 &second_ctx.step_id,
143 &second_ctx.lease_token,
144 second_ctx.state_version,
145 second_ctx.pending_patch,
146 )?;
147
148 let approvals = runtime.store.approval_requests(&run_id);
149 println!(
150 "{{\n \"run_id\": \"{}\",\n \"first_attempt_waited_for_approval\": true,\n \"second_attempt_ok\": true,\n \"approval_count\": {},\n \"approval_status\": \"{}\",\n \"external_action_count\": 1,\n \"final_state_has_pull_request\": {}\n}}",
151 run_id,
152 approvals.len(),
153 approvals.first().map(|row| row.status.as_str()).unwrap_or(""),
154 runtime
155 .store
156 .final_state(&run_id)?
157 .contains_key("pull_request")
158 );
159 Ok(())
160}Trait Implementations§
Source§impl Clone for AgentContext
impl Clone for AgentContext
Source§fn clone(&self) -> AgentContext
fn clone(&self) -> AgentContext
Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · 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 AgentContext
impl RefUnwindSafe for AgentContext
impl Send for AgentContext
impl Sync for AgentContext
impl Unpin for AgentContext
impl UnsafeUnpin for AgentContext
impl UnwindSafe for AgentContext
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