# `Jido.AI.Reasoning.ChainOfThought.Machine`
[🔗](https://github.com/agentjido/jido_ai/blob/v2.2.0/lib/jido_ai/reasoning/chain_of_thought/machine.ex#L1)

Pure state machine for the Chain-of-Thought (CoT) reasoning pattern.

This module implements state transitions for a CoT agent without any side effects.
It uses Fsmx for state machine management and returns directives that describe
what external effects should be performed.

## Overview

Chain-of-Thought prompting encourages LLMs to break down complex problems into
intermediate steps before providing a final answer. This leads to better reasoning
on multi-step problems like math, logic, and common sense reasoning.

## States

- `:idle` - Initial state, waiting for a prompt
- `:reasoning` - Waiting for LLM response with reasoning
- `:completed` - Final state, reasoning complete
- `:error` - Error state

## Usage

The machine is used by the CoT strategy:

    machine = Machine.new()
    {machine, directives} = Machine.update(machine, {:start, prompt, call_id}, env)

All state transitions are pure - side effects are described in directives.

## Status Type Boundary

**Internal (Machine struct):** Status is stored as strings (`"idle"`, `"completed"`)
due to Fsmx library requirements.

**External (Strategy state, Snapshots):** Status is converted to atoms (`:idle`,
`:completed`) via `to_map/1` before storage in agent state.

Never compare `machine.status` directly with atoms - use `Machine.to_map/1` first.

# `directive`

```elixir
@type directive() :: {:call_llm_stream, id :: String.t(), context :: list()}
```

# `external_status`

```elixir
@type external_status() :: :idle | :reasoning | :completed | :error
```

External status (atom) - used in strategy state after to_map/1 conversion

# `internal_status`

```elixir
@type internal_status() :: String.t()
```

Internal machine status (string) - required by Fsmx library

# `msg`

```elixir
@type msg() ::
  {:start, prompt :: String.t(), call_id :: String.t()}
  | {:llm_result, call_id :: String.t(), result :: term()}
  | {:llm_partial, call_id :: String.t(), delta :: String.t(),
     chunk_type :: atom()}
```

# `step`

```elixir
@type step() :: %{number: pos_integer(), content: String.t()}
```

# `t`

```elixir
@type t() :: %Jido.AI.Reasoning.ChainOfThought.Machine{
  conclusion: String.t() | nil,
  current_call_id: String.t() | nil,
  prompt: String.t() | nil,
  raw_response: String.t() | nil,
  result: term(),
  started_at: integer() | nil,
  status: internal_status(),
  steps: [step()],
  streaming_text: String.t(),
  termination_reason: termination_reason(),
  usage: usage()
}
```

# `termination_reason`

```elixir
@type termination_reason() :: :success | :error | nil
```

# `usage`

```elixir
@type usage() :: %{
  optional(:input_tokens) =&gt; non_neg_integer(),
  optional(:output_tokens) =&gt; non_neg_integer(),
  optional(:total_tokens) =&gt; non_neg_integer()
}
```

# `before_transition`

# `default_system_prompt`

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

Returns the default CoT system prompt.

# `extract_steps_and_conclusion`

```elixir
@spec extract_steps_and_conclusion(String.t()) :: {[step()], String.t() | nil}
```

Extracts reasoning steps and conclusion from LLM response text.

Supports multiple formats:
- Numbered steps: "Step 1:", "1.", "1)"
- Bullet points: "- ", "* ", "• "
- Conclusion markers: "Conclusion:", "Answer:", "Therefore:", "Final Answer:"

Returns `{steps, conclusion}` where steps is a list of step maps and
conclusion is the final answer string or nil.

# `from_map`

```elixir
@spec from_map(map()) :: t()
```

Creates a machine from a map (e.g., from strategy state storage).

# `generate_call_id`

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

Generates a unique call ID for LLM requests.

# `new`

```elixir
@spec new() :: t()
```

Creates a new machine in the idle state.

# `to_map`

```elixir
@spec to_map(t()) :: map()
```

Converts the machine state to a map suitable for strategy state storage.

# `update`

```elixir
@spec update(t(), msg(), map()) :: {t(), [directive()]}
```

Updates the machine state based on a message.

Returns the updated machine and a list of directives describing
external effects to be performed.

## Messages

- `{:start, prompt, call_id}` - Start CoT reasoning
- `{:llm_result, call_id, result}` - Handle LLM response
- `{:llm_partial, call_id, delta, chunk_type}` - Handle streaming chunk

## Directives

- `{:call_llm_stream, id, context}` - Request LLM call with CoT prompt

---

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