# `MingaAgent.Provider`
[🔗](https://github.com/jsmestad/minga/blob/main/lib/minga_agent/provider.ex#L1)

Behaviour for AI agent provider backends.

A provider manages the connection to an AI agent (LLM API, subprocess,
etc.) and translates between the provider's native protocol and Minga's
internal `Agent.Event` structs. The provider process runs under the
agent supervisor and is crash-isolated from the editor.

## Implementing a provider

    defmodule MyProvider do
      @behaviour MingaAgent.Provider

      use GenServer

      @impl MingaAgent.Provider
      def start_link(opts), do: GenServer.start_link(__MODULE__, opts)

      @impl MingaAgent.Provider
      def send_prompt(pid, text), do: GenServer.cast(pid, {:prompt, text})

      # ... other callbacks
    end

Events are delivered to the subscriber (typically `Agent.Session`) as
`{:agent_provider_event, event}` messages where `event` is an
`Agent.Event` struct.

# `model_info`

```elixir
@type model_info() :: %{id: String.t(), name: String.t(), provider: String.t()}
```

Model information returned by the provider.

# `opts`

```elixir
@type opts() :: keyword()
```

Provider configuration options.

# `provider`

```elixir
@type provider() :: GenServer.server()
```

Provider state reference (pid or name).

# `session_state`

```elixir
@type session_state() :: %{
  optional(:system_prompt) =&gt; String.t() | nil,
  optional(:thinking_level) =&gt; String.t() | nil,
  optional(:active_skill_names) =&gt; [String.t()],
  optional(:project_root) =&gt; String.t() | nil,
  optional(:mcp_status) =&gt; [map()],
  model: model_info() | String.t() | nil,
  is_streaming: boolean(),
  token_usage: MingaAgent.Event.token_usage() | nil
}
```

Session state returned by the provider.

# `abort`

```elixir
@callback abort(provider()) :: :ok
```

Aborts the current agent operation.

# `cycle_model`
*optional* 

```elixir
@callback cycle_model(provider()) :: {:ok, map()} | {:error, term()}
```

Cycles to the next model in the configured model rotation.

# `cycle_thinking_level`
*optional* 

```elixir
@callback cycle_thinking_level(provider()) :: {:ok, term()} | {:error, term()}
```

Cycles to the next thinking level and returns the new level.

# `get_available_models`
*optional* 

```elixir
@callback get_available_models(provider()) :: {:ok, [map()]} | {:error, term()}
```

Returns available models from the provider.

# `get_commands`
*optional* 

```elixir
@callback get_commands(provider()) :: {:ok, [map()]} | {:error, term()}
```

Returns available commands (extensions, skills, prompts) from the provider.

# `get_state`

```elixir
@callback get_state(provider()) :: {:ok, session_state()} | {:error, term()}
```

Returns the current session state (model info, streaming status, etc.).

# `new_session`

```elixir
@callback new_session(provider()) :: :ok | {:error, term()}
```

Starts a fresh agent session, clearing conversation history.

# `seed_messages`

```elixir
@callback seed_messages(provider(), [MingaAgent.Message.t()]) :: :ok | {:error, term()}
```

Seeds conversation history without sending a prompt.

# `send_prompt`

```elixir
@callback send_prompt(provider(), String.t()) :: :ok | {:error, term()}
```

Sends a user prompt to the agent. Returns immediately; responses arrive as events.

# `set_model`
*optional* 

```elixir
@callback set_model(provider(), String.t()) :: :ok | {:error, term()}
```

Sets the model without resetting conversation context.

# `set_thinking_level`
*optional* 

```elixir
@callback set_thinking_level(provider(), String.t()) :: :ok | {:error, term()}
```

Sets the thinking level (e.g. "low", "medium", "high").

# `start_link`

```elixir
@callback start_link(opts()) :: GenServer.on_start()
```

Starts the provider process.

Options must include `:subscriber` (the pid that receives events).
Provider-specific options (model, binary path, etc.) are also passed here.

---

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