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, request), do: GenServer.call(pid, {:prompt, request})
# ... other callbacks
endTurn-scoped events are delivered to the subscriber (typically Agent.Session)
as {:agent_provider_event, request_id, event}. Session rejects events whose
request identity is no longer active.
Summary
Types
Model information returned by the provider.
Provider configuration options.
Provider state reference (pid or name).
Session state returned by the provider.
Callbacks
Aborts the current agent operation.
Compacts an immutable continuation and returns its replacement messages.
Continues work from an immutable, versioned request snapshot.
Requests cycling; Session-owned resolvers should normally perform this transition.
Cycles to the next thinking level and returns the new level.
Returns exact resolved model route candidates from the provider.
Returns available commands (extensions, skills, prompts) from the provider.
Returns the current session state (model info, streaming status, etc.).
Resets provider runtime state for a fresh Session-owned conversation.
Starts work from an immutable, versioned request snapshot.
Installs an already-resolved model selection without resetting conversation context.
Sets the thinking level (e.g. "low", "medium", "high").
Starts the provider process.
Types
Model information returned by the provider.
@type opts() :: keyword()
Provider configuration options.
@type provider() :: GenServer.server()
Provider state reference (pid or name).
@type session_state() :: %{ optional(:system_prompt) => String.t() | nil, optional(:thinking_level) => String.t() | nil, optional(:active_skill_names) => [String.t()], optional(:project_root) => String.t() | nil, optional(:mcp_status) => [map()], optional(:model_selection) => MingaAgent.ModelSelection.t(), model: model_info() | String.t() | nil, is_streaming: boolean(), token_usage: MingaAgent.Event.token_usage() | nil }
Session state returned by the provider.
Callbacks
@callback abort(provider()) :: :ok
Aborts the current agent operation.
@callback compact(provider(), [ReqLLM.Message.t()]) :: {:ok, [ReqLLM.Message.t()], String.t()} | {:error, term()}
Compacts an immutable continuation and returns its replacement messages.
@callback continue(provider(), MingaAgent.Session.Request.t()) :: :ok | {:error, term()}
Continues work from an immutable, versioned request snapshot.
Requests cycling; Session-owned resolvers should normally perform this transition.
Cycles to the next thinking level and returns the new level.
@callback get_available_models(provider()) :: {:ok, [MingaAgent.ModelCandidate.t()]} | {:error, term()}
Returns exact resolved model route candidates from the provider.
Returns available commands (extensions, skills, prompts) from the provider.
@callback get_state(provider()) :: {:ok, session_state()} | {:error, term()}
Returns the current session state (model info, streaming status, etc.).
Resets provider runtime state for a fresh Session-owned conversation.
@callback send_prompt(provider(), MingaAgent.Session.Request.t()) :: :ok | {:error, term()}
Starts work from an immutable, versioned request snapshot.
@callback set_model(provider(), MingaAgent.ModelSelection.t()) :: :ok | {:error, term()}
Installs an already-resolved model selection without resetting conversation context.
Sets the thinking level (e.g. "low", "medium", "high").
@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.