# `LangChain.Chains.LLMChain.Mode.Steps`
[🔗](https://github.com/brainlid/langchain/blob/v0.8.0/lib/chains/llm_chain/mode/steps.ex#L1)

Pipe-friendly building blocks for composing custom execution modes.

Every step function follows the pipeline convention:

- Input/output: `{:continue, chain}` means keep processing
- Any other tuple (`:ok`, `:pause`, `:error`) is a terminal — passed through unchanged
- Step functions take the pipeline result as first arg, optional config as second

## Example: Custom Mode

    defmodule MyApp.Modes.Simple do
      @behaviour LangChain.Chains.LLMChain.Mode
      import LangChain.Chains.LLMChain.Mode.Steps

      @impl true
      def run(chain, opts) do
        chain = ensure_mode_state(chain)

        {:continue, chain}
        |> call_llm()
        |> execute_tools()
        |> check_max_runs(opts)
        |> continue_or_done(&run/2, opts)
      end
    end

# `pipeline_result`
[🔗](https://github.com/brainlid/langchain/blob/v0.8.0/lib/chains/llm_chain/mode/steps.ex#L32)

```elixir
@type pipeline_result() ::
  {:continue, LangChain.Chains.LLMChain.t()}
  | {:ok, LangChain.Chains.LLMChain.t()}
  | {:ok, LangChain.Chains.LLMChain.t(), term()}
  | {:pause, LangChain.Chains.LLMChain.t()}
  | {:error, LangChain.Chains.LLMChain.t(), term()}
  | {:interrupt, LangChain.Chains.LLMChain.t(), term()}
```

# `call_llm`
[🔗](https://github.com/brainlid/langchain/blob/v0.8.0/lib/chains/llm_chain/mode/steps.ex#L47)

Call the LLM (single step). Wraps `LLMChain.execute_step/1`.

On success, increments `mode_state.run_count` in `custom_context`.

# `check_max_runs`
[🔗](https://github.com/brainlid/langchain/blob/v0.8.0/lib/chains/llm_chain/mode/steps.ex#L76)

Check if max runs have been exceeded.

Reads `run_count` from `custom_context.mode_state` and compares against
`:max_runs` in opts (default: 25).

# `check_pause`
[🔗](https://github.com/brainlid/langchain/blob/v0.8.0/lib/chains/llm_chain/mode/steps.ex#L100)

Check if execution should pause (e.g., node draining).

Reads `:should_pause?` from opts — a zero-arity function that returns boolean.

# `check_tool_interrupts`
[🔗](https://github.com/brainlid/langchain/blob/v0.8.0/lib/chains/llm_chain/mode/steps.ex#L124)

Check if any tool results in the most recent tool message are interrupts.

Returns `{:interrupt, chain, interrupt_data}` if any tool results have
`is_interrupt: true`. The `interrupt_data` is extracted from the first
interrupted result (for single interrupts) or aggregated (for multiple).

This step is generic — it doesn't know *why* a tool interrupted. The
consumer (e.g., Sagents) interprets the interrupt data.

# `check_until_tool`
[🔗](https://github.com/brainlid/langchain/blob/v0.8.0/lib/chains/llm_chain/mode/steps.ex#L172)

Check if a target tool was called in the most recent tool results.

Reads `:tool_names` from opts — a list of tool name strings.
If a matching tool result is found, returns `{:ok, chain, tool_result}`.

# `continue_or_done`
[🔗](https://github.com/brainlid/langchain/blob/v0.8.0/lib/chains/llm_chain/mode/steps.ex#L196)

Decide whether to loop or return.

- `{:continue, chain}` with `needs_response: true` → call `run_fn.(chain, opts)` (loop)
- `{:continue, chain}` with `needs_response: false` → `{:ok, chain}` (done)
- Any terminal result → pass through as-is

# `ensure_mode_state`
[🔗](https://github.com/brainlid/langchain/blob/v0.8.0/lib/chains/llm_chain/mode/steps.ex#L217)

Initialize mode_state in custom_context if not already present.

Call this at the top of your mode's `run/2` to set up run_count tracking.
On the first call, creates `mode_state: %{run_count: 0}`.
On recursive calls (mode_state already exists), returns chain unchanged.

# `execute_tools`
[🔗](https://github.com/brainlid/langchain/blob/v0.8.0/lib/chains/llm_chain/mode/steps.ex#L62)

Execute pending tool calls. Wraps `LLMChain.execute_tool_calls/1`.

# `get_run_count`
[🔗](https://github.com/brainlid/langchain/blob/v0.8.0/lib/chains/llm_chain/mode/steps.ex#L230)

Get the current run count from mode_state.

---

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