Provider-neutral LLM adapter boundary used by trusted Kernel provider builders.
callback/2 binds a configured full model identifier into a one-argument
provider callback. Kernel policy, retries, prompt construction, and protocol
recovery live in shipped Lisp libraries rather than this transport adapter.
Summary
Types
Provider-reported token usage. :total_cost is absent when pricing is
unavailable; a present zero is a measured zero-cost response.
Callbacks
Make an LLM call.
Preload adapter-owned model metadata into a shared, process-independent store
(e.g. a :persistent_term/ETS catalog) so the first per-request provider
worker does not pay a large one-time load inside its bounded heap.
Prepares an adapter-owned request target and reports its catalog status.
Names the OTP application this adapter needs running to serve model.
Attests that the exact adapter target is safe to publish in canonical traces.
Stream an LLM response.
Functions
Returns the configured LLM adapter module.
Make a direct LLM call using the configured adapter.
Creates a normalized requester for a configured or prepared model.
Resolves a configured selector into an immutable adapter-owned request target.
Types
@type catalog_status() :: :cataloged | :uncataloged | :unavailable
@type message() :: %{role: :system | :user | :assistant | :tool, content: String.t()}
@type output_limit() :: %{ name: :max_tokens, value: pos_integer(), bindings: [output_limit_binding()] }
@type output_limit_binding() ::
:configured | :adapter_default | :model_output_limit | :remaining_context
@type tokens() :: %{ optional(:input) => non_neg_integer(), optional(:output) => non_neg_integer(), optional(:cache_creation) => non_neg_integer(), optional(:cache_read) => non_neg_integer(), optional(:total_cost) => float() }
Provider-reported token usage. :total_cost is absent when pricing is
unavailable; a present zero is a measured zero-cost response.
@type tool_call_response() :: %{ :tool_calls => [map()], :content => String.t() | nil, :tokens => tokens(), optional(:finish_reason) => atom(), optional(:output_limit) => output_limit() }
Callbacks
Make an LLM call.
The request map contains:
:system- System prompt string:messages- List of message maps:schema- JSON Schema map (triggers structured output):tools- Tool definitions (triggers tool calling):cache- Boolean for prompt caching
Returns {:ok, response} or {:error, reason}.
@callback ensure_ready() :: :ok
Preload adapter-owned model metadata into a shared, process-independent store
(e.g. a :persistent_term/ETS catalog) so the first per-request provider
worker does not pay a large one-time load inside its bounded heap.
Optional. Invoked during selected provider-application admission and again at capability-build time for direct embedding paths; implementations must be idempotent.
@callback prepare_model(model :: String.t()) :: {:ok, target :: term(), catalog_status()} | {:error, term()}
Prepares an adapter-owned request target and reports its catalog status.
Optional. Adapters without an external model catalog may omit this callback;
PtcRunner then passes the original selector to requests and records the status
as :unavailable.
@callback provider_application(model :: String.t()) :: :req_llm | nil
Names the OTP application this adapter needs running to serve model.
Optional. An adapter backed by a dependency the core does not start returns
that application's name so a host can report an unstarted provider
application as a host misconfiguration rather than as a retryable transport
failure. The answer is per model, because one adapter may route some models
through a dependency and others straight over HTTP. Adapters with no such
dependency omit the callback or return nil.
Constrained to :req_llm because that is the only backing application the
installation catalog validates and the CLI's ownership selection understands.
Admitting arbitrary applications means widening those two consumers as well,
which is a deliberate change rather than a side effect of this callback.
Attests that the exact adapter target is safe to publish in canonical traces.
Optional. Return {:ok, model} only when the complete value is public model
identity. Return :private for local, endpoint-bearing, deployment-private,
or otherwise sensitive targets. PtcRunner rejects altered, malformed, or
oversized values and treats a missing or raising callback as private.
@callback stream(model :: term(), request :: map()) :: {:ok, Enumerable.t()} | {:error, term()}
Stream an LLM response.
Returns {:ok, stream} where stream is an Enumerable of chunk maps:
%{delta: "text"}for content chunks%{done: true, tokens: %{...}}for the final chunk
Functions
@spec adapter!() :: module()
Returns the configured LLM adapter module.
Resolution order:
config :ptc_runner, :llm_adapter, MyAdapterPtcRunner.LLM.ReqLLMAdapterifreq_llmis available- Raises if no adapter found
Make a direct LLM call using the configured adapter.
Examples
{:ok, response} = PtcRunner.LLM.call("amazon_bedrock:anthropic.claude-haiku-4-5-20251001-v1:0", %{
system: "You are helpful.",
messages: [%{role: :user, content: "Hello"}]
})
@spec callback( String.t() | PtcRunner.LLM.PreparedModel.t(), keyword() ) :: {:ok, (map() -> {:ok, map()} | {:error, term()})} | {:error, term()}
Creates a normalized requester for a configured or prepared model.
A selector is prepared once while this function constructs the requester. A
prepared value is bound directly. The optional :adapter setting selects a
transport explicitly; other options are merged into every request.
Returns {:ok, requester} or an error before any request can run. An
uncataloged selector emits one concise warning while the requester is built.
@spec prepare(String.t(), module()) :: {:ok, PtcRunner.LLM.PreparedModel.t()} | {:error, term()}
Resolves a configured selector into an immutable adapter-owned request target.
Preparation runs adapter warmup and model resolution once. It returns a typed error immediately when either operation cannot produce a valid prepared value.