Normandy.Tools.Executor (normandy v2.2.0)

View Source

Runs one tool call safely: Normandy.Tool.run/2 in a separate task, with a timeout and error handling.

  • The tool gets the %Normandy.Tools.Context{} passed as :context; its input is the call's validated input.
  • Timeout: :timeout milliseconds, default default_timeout/0. The dispatch pipeline passes the tool's registration timeout (Normandy.Tools.Toolset.register/3); a :timeout field on the tool struct is never read.
  • A raise, exit, throw or timeout becomes {:error, message}.
  • A result that is not {:ok, value} or {:error, reason} becomes an error.

Error messages reach the model as tool results, so an exit or throw is named by its tag only (its terms can carry call arguments), an exception whose message shows the term it failed on (KeyError, MatchError, CaseClauseError, Protocol.UndefinedError, ...) is named by its module (a KeyError also by its key), and any other exception message is cut to 500 characters.

No controls

execute_tool/2 and execute_tool_classified/2 run the tool and nothing else: no policy, no approval, no hooks, no budget and no input validation. The agent loop runs tools through Normandy.Agents.Dispatch, which applies all of them; call these only for a tool and an input you have already checked.

Summary

Types

What made a tool execution fail: the tool raised (or threw) (:exception), exited (:exit), ran past its timeout (:timeout), returned {:error, _} itself (:tool_error), or returned something else (:invalid_result).

Functions

The timeout of a tool registered without :timeout, in milliseconds.

Runs tool with the given context.

Like execute_tool/2, but also says why a failed execution failed (see error_type/0); the error type is nil on success. The {:error, message} result is exactly the one execute_tool/2 returns.

Types

error_type()

@type error_type() :: :exception | :exit | :timeout | :tool_error | :invalid_result

What made a tool execution fail: the tool raised (or threw) (:exception), exited (:exit), ran past its timeout (:timeout), returned {:error, _} itself (:tool_error), or returned something else (:invalid_result).

execution_options()

@type execution_options() :: [
  context: Normandy.Tools.Context.t(),
  timeout: pos_integer()
]

execution_result()

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

Functions

default_timeout()

@spec default_timeout() :: pos_integer()

The timeout of a tool registered without :timeout, in milliseconds.

execute_tool(tool, opts \\ [])

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

Runs tool with the given context.

Options

  • :context (a Normandy.Tools.Context) - Required. The call's %Normandy.Tools.Context{}, carrying the validated input.

  • :timeout (pos_integer/0) - Milliseconds the tool may run before the call fails with a timeout. The default value is 30000.

execute_tool_classified(tool, opts \\ [])

@spec execute_tool_classified(
  struct(),
  execution_options()
) :: {{:ok, term()}, nil} | {{:error, String.t()}, error_type()}

Like execute_tool/2, but also says why a failed execution failed (see error_type/0); the error type is nil on success. The {:error, message} result is exactly the one execute_tool/2 returns.