# `Impact.Tool`

Span helpers for LLM tool / function calls. Provider-agnostic — works for any
agent loop where the LLM emits structured tool requests and the app executes
them.

## High-level usage

    Impact.Tool.with_call(tool_call, position, fn ->
      Tools.Registry.execute(tool_call.name, tool_call.arguments)
    end)

Opens a `tool.<name>` span, sets request-side `gen_ai.tool.*` attributes
upfront, runs the closure, and stamps result-side attributes (`gen_ai.tool.
call.result`, `gen_ai.tool.call.result.status`) before returning whatever
the closure returned.

## Result classification

The closure can return any of these shapes; `with_call/3` interprets them as
follows:

| Return value | Status | Recorded result |
|---|---|---|
| `{:ok, payload}` | `"success"` | `payload` |
| `{:error, reason}` | `"error"` | `reason` |
| `payload` (any other) | `"success"` | `payload` |

The original return value is passed through unchanged — wrapping in a span
does not alter the function's contract.

## Manual control

If you need finer control (e.g., custom status strings, mid-call events),
call `Impact.trace` directly and use `attrs_for_call/2` + `attrs_for_result/2`
to build attributes.

## Attribute keys (OTel GenAI semantic conventions)

Request side (`attrs_for_call/2`):

  * `gen_ai.operation.name = "execute_tool"`
  * `gen_ai.tool.name` — tool name
  * `gen_ai.tool.call.id` — the tool-use ID assigned by the model
  * `gen_ai.tool.call.arguments` — JSON-encoded input
  * `gen_ai.tool.type = "function"`
  * `gen_ai.tool.call.position` — 0-based index in the model's batch

Result side (`attrs_for_result/2`):

  * `gen_ai.tool.call.result` — JSON-encoded result (or raw string)
  * `gen_ai.tool.call.result.status` — `"success" | "error"` (or any string)

# `attrs_for_call`

```elixir
@spec attrs_for_call(map(), non_neg_integer()) :: map()
```

Build request-side attributes for a `tool.<name>` span.

`tool_call` is a map with `:name`, `:id`, and `:arguments`. `position` is
the 0-based batch index.

# `attrs_for_result`

```elixir
@spec attrs_for_result(any(), String.t()) :: map()
```

Build result-side attributes for a `tool.<name>` span. `status` is typically
`"success"` or `"error"`, but any string is allowed.

# `with_call`

```elixir
@spec with_call(map(), non_neg_integer(), (-&gt; any())) :: any()
```

Wrap a tool execution in a `tool.<name>` span.

`tool_call` must be a map with `:name`, `:id`, and `:arguments`. `position`
is the 0-based index of this call within the model's batch for a single
turn. `fun` is the 0-arity closure that actually runs the tool.

Returns whatever `fun` returned, unchanged.

---

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