# `ReqLLM.ToolCall`
[🔗](https://github.com/agentjido/req_llm/blob/main/lib/req_llm/tool_call.ex#L1)

Represents a single tool call from an assistant message.

This struct matches the OpenAI Chat Completions API wire format:

    {
      "id": "call_abc123",
      "type": "function",
      "function": {
        "name": "get_weather",
        "arguments": "{"location":"Paris"}"
      }
    }

## Fields

- `id` - Unique call identifier (auto-generated if nil)
- `type` - Always "function" (reserved for future extensibility)
- `function` - Map with `name` (string) and `arguments` (JSON string)

`ToolCall` is a struct, not an `Access`-compatible map. Read fields with
`call.id`, `call.function.name`, and `call.function.arguments`, or use
`to_map/1` when a plain map with decoded arguments is more convenient.

Use `resolve/3` to inspect a call against application tools without invoking
a callback. `execute/3` is the explicit single-call execution boundary and
only runs calls whose resolution state is `:valid`.

## Examples

    iex> ToolCall.new("call_abc", "get_weather", ~s({"location":"Paris"}))
    %ReqLLM.ToolCall{
      id: "call_abc",
      type: "function",
      function: %{name: "get_weather", arguments: ~s({"location":"Paris"})}
    }

    iex> ToolCall.new(nil, "get_time", "{}")
    %ReqLLM.ToolCall{
      id: "call_..." # auto-generated
      type: "function",
      function: %{name: "get_time", arguments: "{}"}
    }

# `resolution`

```elixir
@type resolution() :: %{
  state: resolution_state(),
  call: t(),
  id: String.t(),
  name: String.t(),
  tool: ReqLLM.Tool.t() | nil,
  raw_arguments: String.t(),
  arguments: map() | nil,
  validated_arguments: map() | nil,
  metadata: map(),
  error: term() | nil
}
```

Provider-independent inspection of a tool call

# `resolution_state`

```elixir
@type resolution_state() ::
  :valid | :invalid | :unknown | :provider_executed | :provider_native
```

Resolution state for a tool call

# `t`

```elixir
@type t() :: %ReqLLM.ToolCall{function: map(), id: binary(), type: binary()}
```

# `args_json`

```elixir
@spec args_json(t()) :: String.t()
```

Extract the arguments JSON string from a ToolCall.

# `args_map`

```elixir
@spec args_map(t(), keyword()) :: map() | nil
```

Extract and decode the arguments as a map from a ToolCall.
Returns nil if decoding fails.

# `async?`

```elixir
@spec async?(t() | map()) :: boolean()
```

Returns whether the application can return this tool result in a later turn.

Async calls still require application execution. Preserve their original call
IDs and use `to_map/1` to retain metadata when storing conversation history.

# `builtin?`

```elixir
@spec builtin?(t() | map()) :: boolean()
```

Returns true when the ToolCall (or tool-call-shaped map) represents a
server-side builtin invocation. Handles both OpenAI-shaped wrappers and
bare maps: unwraps a nested `:function` map when present.

Prefer this over `flagged_builtin?/1` whenever you have a `%ToolCall{}`
or a map that may carry the OpenAI `function:` nesting.

# `builtin_flag?`

> This function is deprecated. Use flagged_builtin?/1 instead — the rename makes the flag-only semantics explicit.

```elixir
@spec builtin_flag?(any()) :: boolean()
```

# `execute`

```elixir
@spec execute(t(), [ReqLLM.Tool.t()], keyword()) ::
  {:ok, term()} | {:error, term() | resolution()}
```

Executes one resolved application tool call.

The callback is invoked only when `resolve/3` returns `:valid`. Invalid,
unknown, provider-executed, and provider-native calls return
`{:error, resolution}` without invoking any callback. Successful and failed
callback values retain the existing `ReqLLM.Tool.execute/2` contract.

# `find_args`

```elixir
@spec find_args([t()], String.t(), keyword()) :: map() | nil
```

Find the first tool call matching the given name and return its decoded arguments.
Returns nil if no match found or if arguments cannot be decoded.

# `flagged_builtin?`

```elixir
@spec flagged_builtin?(any()) :: boolean()
```

Returns true when the given map carries a truthy `:builtin?` (or
`"builtin?"`) flag **directly on it**. Does not unwrap a nested
`:function` map — use it for chunk metadata or raw tool-call shapes
that don't have the OpenAI `function` nesting.

For structured `%ToolCall{}` or OpenAI-wrapped maps, prefer `builtin?/1`.

# `from_map`

```elixir
@spec from_map(t() | map(), keyword()) :: %{
  id: String.t(),
  name: String.t(),
  arguments: map()
}
```

Normalize a map or ToolCall to the standard `%{id, name, arguments}` format.

Accepts ToolCall structs or plain maps with atom/string keys.
Arguments are decoded from JSON if provided as a string.

## Examples

    iex> ToolCall.from_map(%{"id" => "call_123", "name" => "get_weather", "arguments" => ~s({"location":"Paris"})})
    %{id: "call_123", name: "get_weather", arguments: %{"location" => "Paris"}}

    iex> tc = ToolCall.new("call_456", "get_time", "{}")
    iex> ToolCall.from_map(tc)
    %{id: "call_456", name: "get_time", arguments: %{}}

# `matches_name?`

```elixir
@spec matches_name?(t(), String.t()) :: boolean()
```

Check if a ToolCall matches the given function name.

# `metadata`

```elixir
@spec metadata(term()) :: map()
```

Returns metadata attached to a tool call or tool-call-shaped map.

# `name`

```elixir
@spec name(t()) :: String.t()
```

Extract the function name from a ToolCall.

# `new`

```elixir
@spec new(String.t() | nil, String.t(), String.t()) :: t()
```

Create a new ToolCall with OpenAI-compatible structure.

## Parameters

- `id` - Unique identifier (generates "call_<uuid>" if nil)
- `name` - Function name
- `arguments_json` - Arguments as JSON-encoded string

## Examples

    ToolCall.new("call_123", "get_weather", ~s({"location":"SF"}))
    ToolCall.new(nil, "get_time", "{}")

# `new_builtin`

```elixir
@spec new_builtin(String.t() | nil, String.t(), String.t()) :: t()
```

Create a ToolCall representing a server-side builtin invocation that the
provider executed on the model's behalf (e.g. OpenAI Responses API
`web_search_call`, `file_search_call`).

These calls are exposed in `message.tool_calls` for inspection and
observability — the OTel GenAI bridge surfaces them as `tool_call` parts
in `gen_ai.output.messages`. They are **not replayable**: the provider
already executed them, and the OpenAI Responses request schema rejects
them in `input`. Request encoders, `finish_reason` derivation, and tool
call ID sanitisers must skip entries where `builtin?(tc)` is true.

`arguments_json` should be a JSON-encoded string capturing whatever
per-call payload the provider returned (action, query, result URLs, etc.).

# `provider_native?`

```elixir
@spec provider_native?(t() | map()) :: boolean()
```

Returns true when local tool-call metadata marks a call as provider-native.

Provider adapters can attach the non-wire marker with
`put_metadata(call, %{provider_native: provider})`, where `provider` may be
an atom, string, map, or `true`. A false or nil marker is ignored.

Provider-executed builtins use the separate `builtin?/1` marker.

# `put_builtin_flag`

```elixir
@spec put_builtin_flag(map(), boolean()) :: map()
```

Sets `:builtin? => true` on `map` when `flag` is `true`; otherwise returns
`map` unchanged. Used by stream/response builders that propagate the
builtin marker onto plain tool-call maps before they reach `new_builtin/3`.

# `put_metadata`

```elixir
@spec put_metadata(t(), map()) :: t()
```

Attaches metadata to a ToolCall without changing provider wire encoding.

# `resolve`

```elixir
@spec resolve(t(), [ReqLLM.Tool.t()], keyword()) :: resolution()
```

Resolves a tool call against application tools without invoking a callback.

The returned map always preserves the original call, raw JSON arguments, and
metadata. Application calls are `:valid`, `:invalid`, or `:unknown`.
Provider-executed builtins and calls carrying provider-native metadata are
returned as `:provider_executed` or `:provider_native` and are never treated
as application callbacks.

JSON repair follows `args_map/2` and can be disabled with
`json_repair: false`.

Calls carrying an OpenAI namespace match the tool's `openai.namespace`
provider option. Deferred functions without an explicit namespace use the
function name as their namespace. Calls without namespace metadata retain
name-only matching.

# `schema`

Returns the Zoi schema for this module

# `to_map`

```elixir
@spec to_map(t(), keyword()) :: %{id: String.t(), name: String.t(), arguments: map()}
```

Convert a ToolCall to a flat map with decoded arguments.

Returns a map with `:id`, `:name`, and `:arguments` keys.
Arguments are decoded from JSON; returns empty map if decoding fails.

## Examples

    iex> tc = ToolCall.new("call_123", "get_weather", ~s({"location":"Paris"}))
    iex> ToolCall.to_map(tc)
    %{id: "call_123", name: "get_weather", arguments: %{"location" => "Paris"}}

    iex> tc = ToolCall.new("call_456", "get_time", "{}")
    iex> ToolCall.to_map(tc)
    %{id: "call_456", name: "get_time", arguments: %{}}

---

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