CouncilEx.Provider behaviour (CouncilEx v0.1.0)

Copy Markdown View Source

Behaviour implemented by provider adapters.

An adapter receives a normalized CouncilEx.Request.t() and must return either {:ok, CouncilEx.Response.t()} or {:error, CouncilEx.Error.t()}.

M2a contract: errors MUST be returned as %CouncilEx.Error{} structs with a classified :kind so the Runner can decide whether to retry. Legacy {:error, term()} returns from M1-era adapters are auto-classified by the Runner as :permanent for backwards compatibility, but new adapters should return %Error{} directly.

Per-call options are passed through opts. Adapter-specific options (api_key, base_url, instructor adapter, etc.) live there.

Summary

Functions

Resolves a provider configuration tuple from application config.

Callbacks

complete(t, keyword)

@callback complete(
  CouncilEx.Request.t(),
  keyword()
) :: {:ok, CouncilEx.Response.t()} | {:error, CouncilEx.Error.t() | term()}

stream(t, keyword, function)

(optional)
@callback stream(
  CouncilEx.Request.t(),
  keyword(),
  (CouncilEx.StreamChunk.t() -> :ok)
) :: {:ok, CouncilEx.Response.t()} | {:error, CouncilEx.Error.t()}

Functions

resolve(provider_id)

@spec resolve(atom()) :: {:ok, {module(), keyword()}} | {:error, :unknown_provider}

Resolves a provider configuration tuple from application config.

Returns {dispatcher, opts}. The dispatcher is the module that implements request dispatching (handling structured output, tool-loops, streaming normalization). Defaults to CouncilEx.Providers.Instructor — the dispatcher used by every shipped real-provider adapter.

The remaining opts keep the :adapter key (the concrete CouncilEx.Provider.Adapter module) plus auth + per-provider settings, and are passed verbatim to the dispatcher.

Test / custom dispatchers (e.g. CouncilEx.Providers.Mock, recording proxies) pass :dispatcher explicitly. The Mock dispatcher does not require an :adapter key.