LlmToolkit.Composition (llm_toolkit v0.1.0)

Copy Markdown View Source

Compose multiple tool resolvers into one.

Allows consumers to merge base tools (from LlmToolkit.CodeTools) with their own domain-specific tools into a single resolver.

Example

# Base tools + domain tools
resolver = LlmToolkit.Composition.new([
  {LlmToolkit.CodeTools, "/project"},
  MyApp.DomainTools
])

{:ok, tools} = resolver.available_tools()
# Returns all base tools + domain tools

{:ok, result} = resolver.resolve(%Call{name: "read_file", arguments: %{...}})
# Dispatches to CodeTools

{:ok, result} = resolver.resolve(%Call{name: "search", arguments: %{...}})
# Dispatches to MyApp.DomainTools

Priority

Resolvers are tried in order. First match wins. This means consumer-specific tools can override base tools if needed (e.g., a custom bash tool with sandboxing).

Resolver formats

Each element in the list can be:

  • A module implementing LlmToolkit.ToolResolver (cwd = ".")
  • A {module, cwd} tuple for cwd-aware resolvers like CodeTools

Summary

Functions

Returns all available tools from all composed resolvers.

Returns the dispatch recipe for a tool name by checking each resolver.

Creates a composed resolver from a list of resolver specs.

Resolves a tool call by trying each resolver in order.

Types

t()

@type t() :: %LlmToolkit.Composition{resolvers: [{module(), String.t()}]}

Functions

available_tools(composition)

@spec available_tools(t()) :: [LlmToolkit.Tool.t()]

Returns all available tools from all composed resolvers.

Tools from earlier resolvers appear first. Duplicate tool names are kept (the first resolver to match a tool name wins during dispatch).

dispatch_recipe(composition, tool_name)

@spec dispatch_recipe(t(), String.t()) :: (map() -> map()) | nil

Returns the dispatch recipe for a tool name by checking each resolver.

First non-nil recipe wins.

new(specs)

@spec new([module() | {module(), String.t()}]) :: t()

Creates a composed resolver from a list of resolver specs.

Each spec is either a module (uses "." as cwd) or a {module, cwd} tuple.

resolve(composition, call)

@spec resolve(t(), LlmToolkit.Tool.Call.t()) ::
  {:ok, String.t()} | {:error, String.t()}

Resolves a tool call by trying each resolver in order.

The first resolver to return something other than "Unknown tool" wins.