Skip to main content

ToolContext

Struct ToolContext 

Source
pub struct ToolContext { /* private fields */ }
Expand description

Context passed to Rust tools during dispatch.

Provides access to the current conversation ID and a shared key-value state store that persists across tool calls within the same agent turn.

The state is backed by Arc<RwLock<HashMap>> so it can be cheaply cloned and shared across concurrent tool invocations. Reads acquire a shared lock; only writes take an exclusive lock.

§get_state vs set_state error handling

These two methods intentionally handle mutex poisoning differently:

  • get_state acquires a read lock and returns the caller-supplied default when the lock is poisoned. Reads are best-effort — a missing value is indistinguishable from a default, so returning default keeps the tool running without surfacing infrastructure errors to the model.

  • set_state acquires a write lock and returns Err when the lock is poisoned. Writes that silently vanish can cause subtle logic bugs, so callers must handle the failure explicitly.

§Typed extensions

In addition to the string-keyed JSON state, ToolContext supports typed extensions via set_ext / get_ext. These use std::any::Any under the hood and are keyed by TypeId, so callers store and retrieve strongly-typed values (typically Arc<T>) without serialization.

use std::sync::Arc;

use llm_tool::ToolContext;

struct MyState {
    session_dir: String,
}

let ctx = ToolContext::new();
ctx.set_ext(Arc::new(MyState {
    session_dir: "/tmp".into(),
}))
.unwrap();

let state: Arc<MyState> = ctx.get_ext::<Arc<MyState>>().unwrap();
assert_eq!(state.session_dir, "/tmp");

Implementations§

Source§

impl ToolContext

Source

pub fn new() -> Self

Create a new, empty context: no conversation ID and a fresh state store.

Customize it with with_conversation_id and with_shared_state.

Source

pub fn with_conversation_id(self, conversation_id: impl Into<String>) -> Self

Set the conversation ID. Chainable.

Source

pub fn with_caller(&self, conversation_id: impl Into<String>) -> Self

Derive a new context that carries a different conversation ID while sharing this context’s state store and typed extensions.

Both the shared state (SharedState) and the typed extension map are held behind Arc, so the returned context reads and writes the same underlying stores — only the conversation identity differs. This is the primitive a single MCP server uses to serve many callers: each connection derives its own identity from the shared, session-wide context without duplicating extensions like injected session state.

use std::sync::Arc;

use llm_tool::ToolContext;

let session = ToolContext::new().with_conversation_id("server");
session.set_ext(Arc::new(42u64)).unwrap();

let alice = session.with_caller("alice");
assert_eq!(alice.conversation_id(), Some("alice"));
// Extensions are shared, not copied.
assert_eq!(alice.get_ext::<Arc<u64>>().as_deref(), Some(&42));
Source

pub fn with_shared_state(self, state: SharedState) -> Self

Use an externally-provided SharedState as this context’s state store.

Use this when multiple ToolContext instances (e.g. successive tool calls within the same agent) must read/write the same state store. Obtain a handle from an existing context via shared_state.

Source

pub fn shared_state(&self) -> SharedState

Return a cloneable handle to this context’s shared state store.

Pass the returned handle to with_shared_state on another context to share the same underlying store.

Source

pub fn conversation_id(&self) -> Option<&str>

Return the conversation ID, if one has been set.

Source

pub fn get_state(&self, key: &str, default: Value) -> Value

Retrieve a value from the shared state, returning default if the key is absent or the lock is poisoned.

This method never fails — on a poisoned lock it logs a warning and returns default. See the struct-level docs for rationale.

Source

pub fn set_state(&self, key: &str, value: Value) -> Result<(), ToolError>

Insert or update a value in the shared state.

Unlike get_state, this method returns Err on a poisoned lock because silently dropping a write can cause subtle bugs. See the struct-level docs for rationale.

§Errors

Returns ToolError if the lock is poisoned.

Source

pub fn set_ext<T: Send + Sync + 'static>( &self, value: T, ) -> Result<(), ToolError>

Store a typed value in the extensions map.

Values are keyed by TypeId, so each concrete type can only appear once. Typically used to store Arc<T> for shared, cloneable access.

§Errors

Returns ToolError if the lock is poisoned.

Source

pub fn get_ext<T: Clone + Send + Sync + 'static>(&self) -> Option<T>

Retrieve a clone of a typed value from the extensions map.

Returns None if no value of type T has been stored via set_ext.

Trait Implementations§

Source§

impl Default for ToolContext

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more