Normandy.Tools.Executor (normandy v0.6.2)

View Source

Executes tools safely with timeout and error handling.

The Executor provides a controlled environment for running tools with:

  • Timeout protection
  • Error catching and formatting
  • Execution logging
  • Result validation

Summary

Functions

Executes a tool by name from the registry.

Executes multiple tools in parallel.

Executes multiple tools sequentially.

Executes a tool instance directly.

Types

execution_options()

@type execution_options() :: [timeout: pos_integer(), max_retries: non_neg_integer()]

execution_result()

@type execution_result() :: {:ok, term()} | {:error, String.t()}

Functions

execute(registry, tool_name, opts \\ [])

Executes a tool by name from the registry.

Options

  • :timeout - Maximum execution time in milliseconds (default: 30000)
  • :max_retries - Number of retry attempts on failure (default: 0)

Examples

iex> registry = Normandy.Tools.Registry.new([%CalculatorTool{operation: :add, a: 5, b: 3}])
iex> Normandy.Tools.Executor.execute(registry, "calculator")
{:ok, 8}

iex> Normandy.Tools.Executor.execute(registry, "nonexistent")
{:error, "Tool 'nonexistent' not found in registry"}

execute_parallel(registry, tool_specs, opts \\ [])

@spec execute_parallel(
  Normandy.Tools.Registry.t(),
  [{String.t(), struct()}],
  execution_options()
) :: [
  execution_result()
]

Executes multiple tools in parallel.

Returns a list of results in the same order as the input tools.

Examples

iex> tools = [
...>   {"calc1", %CalculatorTool{operation: :add, a: 1, b: 2}},
...>   {"calc2", %CalculatorTool{operation: :multiply, a: 3, b: 4}}
...> ]
iex> Normandy.Tools.Executor.execute_parallel(registry, tools)
[
  {:ok, 3},
  {:ok, 12}
]

execute_sequential(registry, tool_names, opts \\ [])

@spec execute_sequential(
  Normandy.Tools.Registry.t(),
  [String.t()],
  execution_options()
) ::
  {:ok, [term()]} | {:error, String.t()}

Executes multiple tools sequentially.

Stops execution if any tool returns an error (fail-fast behavior).

Examples

iex> tools = ["tool1", "tool2", "tool3"]
iex> Normandy.Tools.Executor.execute_sequential(registry, tools)
{:ok, [result1, result2, result3]}

execute_tool(tool, opts \\ [])

@spec execute_tool(
  struct(),
  execution_options()
) :: execution_result()

Executes a tool instance directly.

Examples

iex> tool = %CalculatorTool{operation: :add, a: 2, b: 3}
iex> Normandy.Tools.Executor.execute_tool(tool)
{:ok, 5}