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.
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_stateacquires a write lock and returnsErrwhen 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
impl ToolContext
Sourcepub fn new() -> Self
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.
Sourcepub fn with_conversation_id(self, conversation_id: impl Into<String>) -> Self
pub fn with_conversation_id(self, conversation_id: impl Into<String>) -> Self
Set the conversation ID. Chainable.
Sourcepub fn with_caller(&self, conversation_id: impl Into<String>) -> Self
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));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.
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.
Sourcepub fn conversation_id(&self) -> Option<&str>
pub fn conversation_id(&self) -> Option<&str>
Return the conversation ID, if one has been set.
Sourcepub fn get_state(&self, key: &str, default: Value) -> Value
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.
Sourcepub fn set_state(&self, key: &str, value: Value) -> Result<(), ToolError>
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.