When a tool completes its execution, it returns a ToolResult. This result contains the data intended for the LLM and, optionally, instructions on how to display that data in the UI.

ToolResult

The ToolResult struct captures the output of a single tool execution.

pub struct ToolResult {
    /// The actual data to return to the LLM (usually JSON)
    pub output: String,
    
    /// Optional configuration for how to display this result in the UI
    pub display: Option<DisplayConfig>,
    
    /// Whether the execution was successful
    pub is_error: bool,
}

DisplayConfig

DisplayConfig allows a tool to control its visual representation without being coupled to a specific UI implementation (like the TUI or a web interface).

pub struct DisplayConfig {
    pub title: String,
    pub content_type: ContentType,
    pub collapsed: bool,
}

pub enum ContentType {
    Text,
    Markdown,
    Json,
    Code(String), // Language tag
}

By providing a DisplayConfig, a tool can ensure that its output is rendered as a formatted code block, a markdown table, or a simple text summary.

ToolBatchResult

Since tools can be executed in batches, the system uses ToolBatchResult to aggregate the results of multiple calls.

pub struct ToolBatchResult {
    pub results: Vec<ToolCallResult>,
}

pub struct ToolCallResult {
    pub call_id: String,
    pub result: ToolResult,
}

From ToolResult to UI Message

The conversion from a raw ToolResult to a UI element follows this path:

  1. Tool Execution: Returns ToolResult.
  2. Controller: Receives ToolBatchResult.
  3. Event Conversion: The controller emits a ControllerEvent::ToolResult.
  4. UI Adapter: The UI (e.g., the TUI) receives the event and uses the DisplayConfig to create a DisplayResult widget.

Error Results

If a tool encounters an error, it should still return a ToolResult with is_error: true. This allows the LLM to see the error message and potentially try a different approach or correct its input.

// Example of an error result
ToolResult {
    output: "Permission denied: Cannot write to /etc/shadow".to_string(),
    display: Some(DisplayConfig {
        title: "File Write Error".to_string(),
        content_type: ContentType::Text,
        collapsed: false,
    }),
    is_error: true,
}