README

#Tool Package

The tool package provides the core abstractions for defining and executing tools that the AI agent can call.

#Core Types

#ToolDesc

Describes a tool's interface for the AI model.

///|
pub struct ToolDesc {
description : String
name : String
schema : JsonSchema
} derive(ToJson, Eq, Show)

Fields:
  • description: Human-readable description for the AI
  • name: Unique identifier for the tool
  • schema: JSON Schema defining the expected parameters

#Tool[Output]

A tool with its execution function.

///|
pub struct Tool[Output] {
desc : ToolDesc
// private: f : ToolFn[Output]
}

#ToolFn[Output]

The function type for tool execution.

///|
pub(all) struct ToolFn[Output](async (Json) -> ToolResult[Output] noraise)

#ToolResult[Output]

Result of a tool execution.

///|
pub enum ToolResult[Output] {
Ok(Output)
Error(Error, String)
} derive(ToJson)

#AgentTool

A tool adapted for agent use (output is JSON + rendered string).

///|
type AgentTool // Wraps Tool[(Json, String)]

#JsonSchema

Wrapper for JSON Schema validation.

///|
pub(all) struct JsonSchema(Json)

#Key APIs

#Tool Creation

pub fn[Output] Tool::new(
description~ : String,
name~ : String,
schema~ : JsonSchema,
f : ToolFn[Output],
) -> Tool[Output]

#Tool Execution

pub async fn[Output] Tool::call(
tool : Tool[Output],
args : Json,
) -> ToolResult[Output] noraise

#Result Constructors

pub fn[Output] ToolResult::ok(output : Output) -> ToolResult[Output]
pub fn[Output] ToolResult::error(
output : String,
error? : Error,
) -> ToolResult[Output]

#Conversion to AgentTool

pub fn[Output : ToJson + Show] Tool::to_agent_tool(
self : Tool[Output],
) -> AgentTool

#OpenAI Conversion

pub fn ToolDesc::to_openai(
tool_desc : ToolDesc,
) -> @openai.ChatCompletionToolParam

#Creating a Custom Tool

// Define the output type

///|
struct WeatherOutput {
temperature : Double
conditions : String
} derive(ToJson, Show)

// Define the JSON schema

///|
let weather_schema : @tool.JsonSchema = {
"type": "object",
"properties": { "location": { "type": "string", "description": "City name" } },
"required": ["location"],
}

// Create the tool

///|
let weather_tool : @tool.Tool[WeatherOutput] = @tool.new(
description="Get current weather for a location",
name="get_weather",
schema=weather_schema,
@tool.ToolFn(async fn(args) -> @tool.ToolResult[WeatherOutput] noraise {
guard args is { "location": String(location), .. } else {
return @tool.error("Missing 'location' parameter")
}

// Simulate weather API call
@tool.ok({ temperature: 72.5, conditions: "Sunny" })
}),
)

// Convert for agent use

///|
let agent_tool = weather_tool.to_agent_tool()

#Tool Execution Flow

AI Model │ ▼ Tool Call Request (JSON arguments) │ ▼ Tool::call(args) │ ├─► Validate args against schema │ ├─► Execute ToolFn │ ▼ ToolResult │ ├─► Ok(Output) ──► to_json() ──► Return to AI │ └─► Error(Error, String) ──► Return error message

#AgentTool vs Tool[Output]

  • Tool[Output]: Generic tool with custom output type
  • AgentTool: Tool adapted for agent use with (Json, String) output
    • Json: Structured result for AI consumption
    • String: Human-readable rendering

The to_agent_tool() method handles this conversion automatically.

#Usage with Agent

// Create tools
let cmd_tool = @execute_command.new(job_manager).to_agent_tool()
let file_tool = @read_file.new(file_manager).to_agent_tool()

// Add to agent
agent.add_tools([cmd_tool, file_tool])

#Dependencies

  • openai: OpenAI API types for conversion
  • json: JSON handling

#
AgentTool

type AgentTool

#
AgentTool::call

async fn AgentTool::call(self : AgentTool, args : Json) -> ToolResult[(Json, String)] noraise

#
AgentTool::desc

fn AgentTool::desc(self : AgentTool) -> ToolDesc

#
JsonSchema

pub(all) struct JsonSchema(Json) derive(Eq,
Debug
)

#
JsonSchema::from_json

fn JsonSchema::from_json(schema : Json) -> JsonSchema

#
Tool

pub struct Tool[Output] {
desc : ToolDesc
// private fields
}

#
Tool::call

#as_free_fn
async fn[Output] Tool::call(tool : Tool[Output], args : Json) -> ToolResult[Output] noraise

#
Tool::new

#as_free_fn
fn[Output] Tool::new(description~ : String, name~ : String, schema~ : JsonSchema, f : ToolFn[Output]) -> Tool[Output]

  • description: Tool description that can be read by the LLM.
  • name: Tool name used by the LLM to call the tool.
  • schema: JSON schema to validate LLM-generated output and provide type information to the LLM. schema should be an object type. Related issue: #258
  • f: Function whose input must conform to the schema defined above.

#
Tool::to_agent_tool

fn[Output : ToJson] Tool::to_agent_tool(self : Tool[Output]) -> AgentTool

Convert a Tool[Output] to Tool[Json] by converting outputs to Json

#
ToolDesc

pub struct ToolDesc {
description : String
name : String
schema : JsonSchema
} derive(Eq, ToJson,
Debug
)

#
ToolFn

pub(all) struct ToolFn[Output](async (Json) -> ToolResult[Output] noraise)

#
ToolResult

pub enum ToolResult[Output] {
Ok(Output)
Error(Error, String)
} derive(ToJson)

impl Show for ToolResult[Output]

#
ToolResult::error

#as_free_fn
fn[Output] ToolResult::error(output : String, error? : Error) -> ToolResult[Output]

#
ToolResult::ok

#as_free_fn
fn[Output] ToolResult::ok(output : Output) -> ToolResult[Output]

#
tool_desc

fn tool_desc(description~ : String, name~ : String, schema~ : JsonSchema) -> ToolDesc