MingaAgent.Provider behaviour (Minga v0.1.0)

Copy Markdown View Source

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
end

Turn-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_info()

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

Model information returned by the provider.

opts()

@type opts() :: keyword()

Provider configuration options.

provider()

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

Provider state reference (pid or name).

session_state()

@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

abort(provider)

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

Aborts the current agent operation.

compact(provider, list)

(optional)
@callback compact(provider(), [ReqLLM.Message.t()]) ::
  {:ok, [ReqLLM.Message.t()], String.t()} | {:error, term()}

Compacts an immutable continuation and returns its replacement messages.

continue(provider, t)

(optional)
@callback continue(provider(), MingaAgent.Session.Request.t()) :: :ok | {:error, term()}

Continues work from an immutable, versioned request snapshot.

cycle_model(provider)

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

Requests cycling; Session-owned resolvers should normally perform this transition.

cycle_thinking_level(provider)

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

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

get_available_models(provider)

(optional)
@callback get_available_models(provider()) ::
  {:ok, [MingaAgent.ModelCandidate.t()]} | {:error, term()}

Returns exact resolved model route candidates from the provider.

get_commands(provider)

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

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

get_state(provider)

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

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

new_session(provider)

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

Resets provider runtime state for a fresh Session-owned conversation.

send_prompt(provider, t)

@callback send_prompt(provider(), MingaAgent.Session.Request.t()) ::
  :ok | {:error, term()}

Starts work from an immutable, versioned request snapshot.

set_model(provider, t)

(optional)
@callback set_model(provider(), MingaAgent.ModelSelection.t()) :: :ok | {:error, term()}

Installs an already-resolved model selection without resetting conversation context.

set_thinking_level(provider, t)

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

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

start_link(opts)

@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.