pub struct ToolSpec {
pub name: String,
pub version: String,
pub side_effect: String,
pub risk_level: String,
pub idempotency_required: bool,
pub approval_required: bool,
pub sandbox_required: bool,
pub sandbox_executor: String,
pub sandbox_policy: State,
pub input_schema: Option<Value>,
pub output_schema: Option<Value>,
pub func: ToolFunc,
}Fields§
§name: String§version: String§side_effect: String§risk_level: String§idempotency_required: bool§approval_required: bool§sandbox_required: bool§sandbox_executor: String§sandbox_policy: State§input_schema: Option<Value>§output_schema: Option<Value>§func: ToolFuncImplementations§
Source§impl ToolSpec
impl ToolSpec
Sourcepub fn new(name: &str, func: ToolFunc) -> Self
pub fn new(name: &str, func: ToolFunc) -> Self
Examples found in repository?
examples/three_minute_demo.rs (lines 23-31)
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}Sourcepub fn side_effect(self, side_effect: &str) -> Self
pub fn side_effect(self, side_effect: &str) -> Self
Examples found in repository?
examples/three_minute_demo.rs (line 32)
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}pub fn risk_level(self, risk_level: &str) -> Self
Sourcepub fn idempotency_required(self, required: bool) -> Self
pub fn idempotency_required(self, required: bool) -> Self
Examples found in repository?
examples/three_minute_demo.rs (line 33)
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}pub fn approval_required(self, required: bool) -> Self
pub fn sandbox_required(self, required: bool) -> Self
pub fn sandbox_executor(self, executor: &str) -> Self
pub fn sandbox_policy(self, policy: State) -> Self
Sourcepub fn input_schema(self, schema: Value) -> Self
pub fn input_schema(self, schema: Value) -> Self
Examples found in repository?
examples/three_minute_demo.rs (lines 34-40)
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}pub fn output_schema(self, schema: Value) -> Self
Auto Trait Implementations§
impl !RefUnwindSafe for ToolSpec
impl !UnwindSafe for ToolSpec
impl Freeze for ToolSpec
impl Send for ToolSpec
impl Sync for ToolSpec
impl Unpin for ToolSpec
impl UnsafeUnpin for ToolSpec
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