# `Jido.AI.Reasoning.ReAct.Config`
[🔗](https://github.com/agentjido/jido_ai/blob/v2.4.0/lib/jido_ai/reasoning/react/config.ex#L1)

Canonical configuration for the Task-based ReAct runtime.

# `t`

```elixir
@type t() :: %Jido.AI.Reasoning.ReAct.Config{
  effect_policy: any(),
  llm: %{
    :max_tokens =&gt; integer(),
    :temperature =&gt; number(),
    :req_http_options =&gt; [any()],
    :llm_opts =&gt; any(),
    :tool_choice =&gt; any(),
    optional(:timeout_ms) =&gt; nil | integer()
  },
  max_iterations: integer(),
  model: any(),
  observability: %{
    emit_signals?: boolean(),
    emit_telemetry?: boolean(),
    redact_tool_args?: boolean()
  },
  output: nil | nil | any(),
  pending_input_server: nil | nil | any(),
  request_transformer: nil | nil | atom(),
  stream_timeout_ms: integer(),
  streaming: boolean(),
  system_prompt: nil | nil | binary(),
  token: %{
    :secret =&gt; binary(),
    optional(:ttl_ms) =&gt; nil | integer(),
    compress?: boolean()
  },
  tool_exec: %{
    max_retries: integer(),
    timeout_ms: integer(),
    retry_backoff_ms: integer(),
    concurrency: integer()
  },
  tool_heartbeat_ms: integer(),
  tools: map(),
  trace: %{
    capture_deltas?: boolean(),
    capture_thinking?: boolean(),
    capture_messages?: boolean()
  },
  version: integer()
}
```

# `fingerprint`

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

Returns a stable config fingerprint used by checkpoint tokens.

# `llm_opts`

```elixir
@spec llm_opts(t()) :: keyword()
```

Convert config to generation options for `ReqLLM.Generation.stream_text/3`
and `ReqLLM.Generation.generate_text/3`.

# `merge_llm_opts`

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

Merge request-scoped LLM option overrides into an existing normalized option list.

The 3-arg form validates `provider_options` overrides against the compile-time
`config.model`'s schema. The 4-arg form takes an explicit `model_override` so
per-turn provider swaps (via a `request_transformer` returning `:model`) can
validate against the *runtime* provider's schema instead.

# `merge_llm_opts`

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

# `new`

```elixir
@spec new(map() | keyword()) :: t()
```

Build a runtime config from options.

# `reqllm_tools`

```elixir
@spec reqllm_tools(t()) :: [ReqLLM.Tool.t()]
```

Convert runtime tools to ReqLLM tool definitions.

# `stream_timeout`

```elixir
@spec stream_timeout(t()) :: pos_integer()
```

Returns the effective stream consumer timeout.

When `stream_timeout_ms` is 0 (default), auto-derives from
`tool_exec.timeout_ms + 60_000` to ensure the stream consumer
outlives the longest possible tool execution plus LLM response time.

# `tool_heartbeat_ms`

```elixir
@spec tool_heartbeat_ms(t()) :: non_neg_integer()
```

Returns the tool-execution heartbeat interval in milliseconds.

When `> 0`, the ReAct runner emits a `:keepalive` event every interval while
tools are executing, so a consumer that sets a short
`stream_event_timeout_ms` on `Jido.AI.Request.Stream.events/2` does not time
out during a long-running tool call. `0` (default) disables heartbeats.

---

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