pub struct ToolOutput { /* private fields */ }Expand description
The return value of a Rust tool execution.
Every tool produces a ToolOutput containing:
content: the text sent back to the model.metadata: an optional structured key-value map available to hooks, policies, and logging pipelines — but never sent to the model.
§Ergonomics
ToolOutput implements From<String>, From<&str>, and Display, so
simple tools can return plain strings without ceremony:
use llm_tool::ToolOutput;
use serde::Serialize;
// From a String
let out: ToolOutput = "hello".to_string().into();
assert_eq!(out.content(), "hello");
assert!(out.metadata().is_empty());
// From &str
let out: ToolOutput = "world".into();
assert_eq!(out.content(), "world");
// Structured metadata from a typed struct (preferred)
#[derive(Serialize)]
struct ReadMeta {
bytes_read: usize,
cached: bool,
}
let out = ToolOutput::new("file contents…")
.with_metadata(&ReadMeta {
bytes_read: 1024,
cached: true,
})
.unwrap();
assert_eq!(out.metadata()["bytes_read"], 1024);
assert_eq!(out.metadata()["cached"], true);
// Single ad-hoc entry
let out = ToolOutput::new("done").with_meta("exit_code", serde_json::json!(0));
assert_eq!(out.metadata()["exit_code"], 0);Implementations§
Source§impl ToolOutput
impl ToolOutput
Sourcepub fn sanitized(self) -> Self
pub fn sanitized(self) -> Self
Return a sanitized copy of this ToolOutput, neutralizing control
delimiters (DELIMITER_RULES) and <tool_output_quarantine> breakout tags
in a single pass without wrapping in outer XML tags.
Zero-allocation when the content contains no delimiters, and idempotent when called on an already-sanitized or already-quarantined output.
Sourcepub fn is_sanitized(&self) -> bool
pub fn is_sanitized(&self) -> bool
Returns true if this output’s content contains no un-neutralized
DELIMITER_RULES or <tool_output_quarantine> breakout tags (or is
wrapped in a verified <tool_output_quarantine> envelope).
Sourcepub fn quarantined(self) -> Self
pub fn quarantined(self) -> Self
Return a quarantined copy of this ToolOutput, neutralizing control
delimiters and wrapping the content in <tool_output_quarantine> tags.
Idempotent when called on an already-quarantined output.
Sourcepub fn is_quarantined(&self) -> bool
pub fn is_quarantined(&self) -> bool
Returns true if this output’s content is wrapped in a verified
<tool_output_quarantine> envelope with no un-neutralized delimiters.
Sourcepub fn sanitized_block(self, tag: &str) -> Self
pub fn sanitized_block(self, tag: &str) -> Self
Return a sanitized copy of this ToolOutput, wrapped in <tag> with the default
boundary notice and control tokens neutralized.
Idempotent when called on an already-sanitized block with matching tag.
§Panics
Panics if tag is not a valid ASCII XML NCName.
Sourcepub fn sanitized_with(self, tag: &str, notice: &str) -> Self
pub fn sanitized_with(self, tag: &str, notice: &str) -> Self
Return a sanitized copy of this ToolOutput, wrapped in <tag> with a custom
notice and control tokens neutralized.
Idempotent when called on an already-sanitized block with matching tag.
§Panics
Panics if tag is not a valid ASCII XML NCName.
Sourcepub fn is_sanitized_with(&self, tag: &str) -> bool
pub fn is_sanitized_with(&self, tag: &str) -> bool
Returns true if this output is wrapped in a verified <tag> boundary envelope.
Sourcepub fn unsanitized_with<'a>(&'a self, tag: &str) -> Option<&'a str>
pub fn unsanitized_with<'a>(&'a self, tag: &str) -> Option<&'a str>
Extract the inner payload if this output is a verified <tag> boundary block.
Sourcepub fn is_sanitized_with_notice(&self, tag: &str, notice: &str) -> bool
pub fn is_sanitized_with_notice(&self, tag: &str, notice: &str) -> bool
Returns true if this output is wrapped in <tag> with the exact specified notice.
Sourcepub fn unsanitized_with_notice<'a>(
&'a self,
tag: &str,
notice: &str,
) -> Option<&'a str>
pub fn unsanitized_with_notice<'a>( &'a self, tag: &str, notice: &str, ) -> Option<&'a str>
Extract the inner payload if this output is wrapped in <tag> with the exact specified notice.
Sourcepub fn sanitized_truncated(self, policy: &TruncationPolicy) -> Self
pub fn sanitized_truncated(self, policy: &TruncationPolicy) -> Self
Sanitize and truncate this ToolOutput according to policy, ensuring
that control tokens and any split tokens formed across the truncation cut
boundary are neutralized while respecting policy.max_bytes.
Sourcepub fn quarantined_truncated(self, policy: &TruncationPolicy) -> Self
pub fn quarantined_truncated(self, policy: &TruncationPolicy) -> Self
Quarantine and truncate this ToolOutput according to policy, preserving
the outer <tool_output_quarantine> envelope and neutralizing any split
tokens formed across the truncation cut boundary while fitting the total
envelope inside policy.max_bytes.
Source§impl ToolOutput
impl ToolOutput
Sourcepub fn new(content: impl Into<String>) -> Self
pub fn new(content: impl Into<String>) -> Self
Create a new ToolOutput with the given content and no metadata.
Sourcepub fn json<T: Serialize>(value: &T) -> Result<Self, ToolError>
pub fn json<T: Serialize>(value: &T) -> Result<Self, ToolError>
Serialize a value to JSON and wrap it as tool output.
The JSON string becomes the content sent to the model, but no
metadata is attached. For the zero-redundancy path that populates
both content and metadata from the same struct, use
from_metadata.
use llm_tool::{ToolOutput, ToolError};
let data = serde_json::json!({"temp": 72, "unit": "F"});
let output = ToolOutput::json(&data).unwrap();
assert!(output.content().contains("72"));
assert!(output.metadata().is_empty()); // no metadata attached§Errors
Returns Err(ToolError) if serialization fails.
Sourcepub fn from_metadata<T: Serialize>(value: &T) -> Result<Self, ToolError>
pub fn from_metadata<T: Serialize>(value: &T) -> Result<Self, ToolError>
Create a ToolOutput where both the content and metadata come
from the same serializable value.
- Content (sent to the model): the JSON representation of
value. - Metadata (hooks / policies / logging): the flattened object fields.
This is the zero-redundancy path: define one struct, derive
Serialize, and everything is populated automatically.
§Errors
Returns Err(ToolError) if value doesn’t serialize to a JSON object.
§Example
use llm_tool::ToolOutput;
use serde::Serialize;
#[derive(Serialize)]
struct Weather {
location: String,
temp_f: i32,
condition: String,
}
let out = ToolOutput::from_metadata(&Weather {
location: "Seattle".into(),
temp_f: 72,
condition: "Sunny".into(),
})
.unwrap();
// Model sees the JSON string
assert!(out.content().contains("Seattle"));
assert!(out.content().contains("72"));
// Hooks see typed fields
assert_eq!(out.metadata()["location"], "Seattle");
assert_eq!(out.metadata()["temp_f"], 72);Sourcepub fn with_meta(self, key: impl Into<String>, value: Value) -> Self
pub fn with_meta(self, key: impl Into<String>, value: Value) -> Self
Attach a single metadata key-value pair. Chainable.
For attaching multiple fields at once, prefer
with_metadata with a typed struct.
Sourcepub fn with_metadata<T: Serialize>(self, value: &T) -> Result<Self, ToolError>
pub fn with_metadata<T: Serialize>(self, value: &T) -> Result<Self, ToolError>
Attach structured metadata from a serializable value.
The value is serialized to a JSON object and its fields are merged into the metadata map. This is the preferred way to attach metadata because it avoids stringly-typed keys and data duplication.
§Errors
Returns Err(ToolError) if value doesn’t serialize to a JSON object
(e.g. it serializes to a scalar or array).
§Example
use llm_tool::ToolOutput;
use serde::Serialize;
#[derive(Serialize)]
struct FileMeta {
bytes_read: usize,
source: String,
}
let out = ToolOutput::new("file contents")
.with_metadata(&FileMeta {
bytes_read: 1024,
source: "/etc/hosts".into(),
})
.unwrap();
assert_eq!(out.metadata()["bytes_read"], 1024);
assert_eq!(out.metadata()["source"], "/etc/hosts");Sourcepub fn into_content(self) -> String
pub fn into_content(self) -> String
Consume self and return the owned content string.
Sourcepub fn truncated(self, policy: &TruncationPolicy) -> Self
pub fn truncated(self, policy: &TruncationPolicy) -> Self
Truncate the output text content according to the given TruncationPolicy.
Sourcepub fn truncate_detailed(
&mut self,
policy: &TruncationPolicy,
) -> Result<TruncationOutcome<'static>, SpillError>
pub fn truncate_detailed( &mut self, policy: &TruncationPolicy, ) -> Result<TruncationOutcome<'static>, SpillError>
Truncate the output text content according to the given TruncationPolicy,
returning a detailed TruncationOutcome.
§Errors
Returns SpillError if an OutputSpillSink is configured and fails.
Sourcepub fn truncate_detailed_with_context(
&mut self,
policy: &TruncationPolicy,
ctx: &SpillContext<'_>,
) -> Result<TruncationOutcome<'static>, SpillError>
pub fn truncate_detailed_with_context( &mut self, policy: &TruncationPolicy, ctx: &SpillContext<'_>, ) -> Result<TruncationOutcome<'static>, SpillError>
Truncate the output text content with caller context according to TruncationPolicy.
§Errors
Returns SpillError if an OutputSpillSink is configured and fails.
Trait Implementations§
Source§impl Clone for ToolOutput
impl Clone for ToolOutput
Source§impl Debug for ToolOutput
impl Debug for ToolOutput
Source§impl<'de> Deserialize<'de> for ToolOutput
impl<'de> Deserialize<'de> for ToolOutput
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl Display for ToolOutput
impl Display for ToolOutput
impl Eq for ToolOutput
Source§impl From<&str> for ToolOutput
impl From<&str> for ToolOutput
Source§impl From<Sanitized<ToolOutput>> for ToolOutput
impl From<Sanitized<ToolOutput>> for ToolOutput
Source§impl From<String> for ToolOutput
impl From<String> for ToolOutput
Source§impl From<Untrusted<ToolOutput>> for ToolOutput
impl From<Untrusted<ToolOutput>> for ToolOutput
Source§impl From<Value> for ToolOutput
impl From<Value> for ToolOutput
Source§impl From<bool> for ToolOutput
impl From<bool> for ToolOutput
Source§impl From<f64> for ToolOutput
impl From<f64> for ToolOutput
Source§impl From<i64> for ToolOutput
impl From<i64> for ToolOutput
Source§impl PartialEq for ToolOutput
impl PartialEq for ToolOutput
Source§impl Serialize for ToolOutput
impl Serialize for ToolOutput
impl StructuralPartialEq for ToolOutput
Auto Trait Implementations§
impl Freeze for ToolOutput
impl RefUnwindSafe for ToolOutput
impl Send for ToolOutput
impl Sync for ToolOutput
impl Unpin for ToolOutput
impl UnsafeUnpin for ToolOutput
impl UnwindSafe for ToolOutput
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
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.