Capability Layer API
ftooling provides the tool registration and execution runtime for Fiddlesticks.
It is designed to plug into fchat tool loops while staying provider-agnostic by using fprovider tool contracts.
Responsibilities
- Register tools and expose their
ToolDefinitionmetadata - Execute tool calls from model output (
fprovider::ToolCall) - Return tool outputs as structured execution results
- Offer runtime hooks and timeout controls for observability and resilience
ftooling does not:
- Decide when to call tools during a conversation (
fchatowns that) - Persist conversation state (
fmemoryowns that) - Implement model transport/provider adapters (
fproviderowns that)
Add dependency
[]
= { = "../ftooling" }
= { = "../fprovider" }
Core types
Tool: trait for executable capabilitiesToolRegistry: registry keyed by tool nameToolRuntime: runtime contract for tool executionDefaultToolRuntime: registry-backed runtime implementationToolExecutionContext: session/trace metadata passed to toolsToolExecutionResult: normalized output payloadToolError: typed error with retryability and optional call metadata
Easiest registration path
You can register tools without implementing a custom struct.
Sync closure
use ToolDefinition;
use *;
let mut registry = new;
registry.register_sync_fn;
Async closure
use ToolDefinition;
use *;
let mut registry = new;
registry.register_fn;
Runtime usage
use Arc;
use ToolCall;
use *;
async
Argument helper utilities
ftooling exposes lightweight JSON helpers so tool closures do not need to repeat parsing boilerplate:
parse_json_value(args_json)parse_json_object(args_json)required_string(&args, key)
use *;
let args = parse_json_object?;
let query = required_string?;
let _ = query;
Hooks and timeout
DefaultToolRuntime::with_hooks(...)attaches runtime lifecycle hooksDefaultToolRuntime::with_timeout(...)enforces per-call timeout- Hook events include start/success/failure with elapsed duration
- Hook order contract:
on_execution_start- exactly one of
on_execution_successoron_execution_failure
use Arc;
use Duration;
use *;
let runtime = new
.with_hooks
.with_timeout;
let _ = runtime;
Error model
ToolErrorKind variants:
NotFoundInvalidArgumentsExecutionTimeoutUnauthorizedOther
ToolError includes:
retryablefor policy decisions- optional
tool_nameandtool_call_idfor richer context - helper methods:
is_retryable(),is_user_error()
When errors are produced by DefaultToolRuntime, tool_name and tool_call_id are populated automatically.
Integration with fchat
fchat can consume ftooling::ToolRuntime directly:
- configure on
ChatServicevia.with_tool_runtime(...) - cap loops with
.with_max_tool_round_trips(...) fchatmapsToolErrortoChatErrorKind::Tooling