Skip to main content

ToolOutput

Struct ToolOutput 

Source
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

Source

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.

Source

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).

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn is_sanitized_with(&self, tag: &str) -> bool

Returns true if this output is wrapped in a verified <tag> boundary envelope.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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

Source

pub fn new(content: impl Into<String>) -> Self

Create a new ToolOutput with the given content and no metadata.

Source

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.

Source

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);
Source

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.

Source

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");
Source

pub fn content(&self) -> &str

The text content sent back to the model.

Source

pub fn into_content(self) -> String

Consume self and return the owned content string.

Source

pub const fn metadata(&self) -> &HashMap<String, Value>

The structured metadata map.

Source

pub fn truncated(self, policy: &TruncationPolicy) -> Self

Truncate the output text content according to the given TruncationPolicy.

Source

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.

Source

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

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ToolOutput

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for ToolOutput

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Display for ToolOutput

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Eq for ToolOutput

Source§

impl From<&str> for ToolOutput

Source§

fn from(content: &str) -> Self

Converts to this type from the input type.
Source§

impl<T: Serialize> From<Json<T>> for ToolOutput

Source§

fn from(json: Json<T>) -> Self

Converts to this type from the input type.
Source§

impl From<Sanitized<&str>> for ToolOutput

Source§

fn from(value: Sanitized<&str>) -> Self

Converts to this type from the input type.
Source§

impl<T: Serialize> From<Sanitized<Json<T>>> for ToolOutput

Source§

fn from(value: Sanitized<Json<T>>) -> Self

Converts to this type from the input type.
Source§

impl From<Sanitized<String>> for ToolOutput

Source§

fn from(value: Sanitized<String>) -> Self

Converts to this type from the input type.
Source§

impl From<Sanitized<ToolOutput>> for ToolOutput

Source§

fn from(value: Sanitized<Self>) -> Self

Converts to this type from the input type.
Source§

impl From<String> for ToolOutput

Source§

fn from(content: String) -> Self

Converts to this type from the input type.
Source§

impl From<Untrusted<&str>> for ToolOutput

Source§

fn from(value: Untrusted<&str>) -> Self

Converts to this type from the input type.
Source§

impl<T: Serialize> From<Untrusted<Json<T>>> for ToolOutput

Source§

fn from(value: Untrusted<Json<T>>) -> Self

Converts to this type from the input type.
Source§

impl From<Untrusted<String>> for ToolOutput

Source§

fn from(value: Untrusted<String>) -> Self

Converts to this type from the input type.
Source§

impl From<Untrusted<ToolOutput>> for ToolOutput

Source§

fn from(value: Untrusted<Self>) -> Self

Converts to this type from the input type.
Source§

impl From<Value> for ToolOutput

Source§

fn from(value: Value) -> Self

Converts to this type from the input type.
Source§

impl From<bool> for ToolOutput

Source§

fn from(value: bool) -> Self

Converts to this type from the input type.
Source§

impl From<f64> for ToolOutput

Source§

fn from(value: f64) -> Self

Converts to this type from the input type.
Source§

impl From<i64> for ToolOutput

Source§

fn from(value: i64) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for ToolOutput

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl Serialize for ToolOutput

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for ToolOutput

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

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

Source§

type Error = !

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

fn try_from(value: U) -> Result<T, !>

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