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

Behaviour for LLMChain execution modes.

A mode controls the execution loop of an LLMChain - how many times the LLM
is called, when tools are executed, and under what conditions the loop
terminates.

## Built-in Modes

- `LangChain.Chains.LLMChain.Modes.WhileNeedsResponse` - loop while `needs_response` is true
- `LangChain.Chains.LLMChain.Modes.UntilSuccess` - loop until successful tool execution or assistant response
- `LangChain.Chains.LLMChain.Modes.Step` - single step with optional continuation
- `LangChain.Chains.LLMChain.Modes.UntilToolUsed` - loop until a specific tool is called

## Custom Modes

Implement this behaviour to define custom execution loops. The simplest
approach is to import `LangChain.Chains.LLMChain.Mode.Steps` and compose
the provided step functions into a pipeline. Each step follows a consistent
contract:

- `{:continue, chain}` - keep processing, pipe into the next step
- Any other tuple (`:ok`, `:pause`, `:error`) — terminal result, passed through unchanged

This means a pipeline short-circuits automatically when any step returns a
terminal value.

### Minimal Example

    defmodule MyApp.Modes.Custom do
      @behaviour LangChain.Chains.LLMChain.Mode

      @impl true
      def run(chain, opts) do
        case LLMChain.execute_step(chain) do
          {:ok, updated} ->
            updated = LLMChain.execute_tool_calls(updated)
            if updated.needs_response, do: run(updated, opts), else: {:ok, updated}
          error -> error
        end
      end
    end

### Composable Example Using Steps

The built-in modes are all composed from `Steps` functions. You can do the
same to build a mode that adds custom logic at any point in the pipeline.

For example, a mode that loops like `WhileNeedsResponse` but adds a custom
check after each tool execution round:

    defmodule MyApp.Modes.WithAudit 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}
        |> execute_tools()
        |> call_llm()
        |> check_max_runs(opts)
        |> audit_step(opts)
        |> continue_or_done(&run/2, opts)
      end

      # A custom step - same contract as the built-in steps:
      # accept {:continue, chain} and return {:continue, chain} or a terminal.
      defp audit_step({:continue, chain}, _opts) do
        run_count = get_run_count(chain)
        Logger.info("LLM call ##{run_count} completed")
        {:continue, chain}
      end

      defp audit_step(terminal, _opts), do: terminal
    end

The pattern is always the same: start with `{:continue, chain}`, pipe
through as many steps as needed, and end with `continue_or_done/3` to
decide whether to loop.

See `LangChain.Chains.LLMChain.Mode.Steps` for the full list of available
step functions. The built-in modes (`WhileNeedsResponse`, `UntilSuccess`,
`Step`, `UntilToolUsed`) also serve as practical examples to reference.

## Return Types

- `{:ok, chain}` - normal completion
- `{:ok, chain, extra}` - completion with additional data
- `{:pause, chain}` - execution paused at a clean checkpoint; resumable
- `{:error, chain, reason}` - execution failed

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

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

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

```elixir
@callback run(chain :: LangChain.Chains.LLMChain.t(), opts :: Keyword.t()) :: run_result()
```

Execute the chain according to this mode's logic.

The `opts` keyword list contains all options passed to `LLMChain.run/2`,
allowing modes to define their own options.

---

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