# `ToolCall.Runner`

Validates and dispatches a decoded argument map to the tool function.

Validation is generated from the same IR that produced the schema, so the
parameter set, its names and its types cannot drift between the two.

# `run`

```elixir
@spec run(module(), [ToolCall.IR.Tool.t()], atom() | String.t(), term()) ::
  {:ok, term()} | {:error, term()}
```

Runs a tool by name.

`args` uses string keys, as JSON decodes them, including nested object values;
`keyword(t)` values also accept atom keys because a keyword list is their value
domain. Invalid UTF-8 binaries in string arguments become
`{:invalid_argument, {name, {:invalid_utf8, value}}}` errors.

Runtime tool lists are validated before dispatch. Compiled tools can use
`run_prepared/4` to skip that validation.

# `run_prepared`

```elixir
@spec run_prepared(module(), [ToolCall.IR.Tool.t()], atom() | String.t(), term()) ::
  {:ok, term()} | {:error, term()}
```

Internal fast path for already prepared tools.

This skips runtime IR validation. Callers must pass tools prepared by
`ToolCall.Typespec.validate_tool!/1`; use `run/4` for arbitrary runtime tools.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
