Behaviour for LLM providers.
Each provider translates between its native wire format and Alloy's
normalized Alloy.Message structs. The agent loop only sees normalized
messages - adding a new provider means implementing this behaviour.
Completion Response
Providers return a map with:
:stop_reason-:tool_use(continue looping) or:end_turn(done):messages- list ofAlloy.Messagestructs from the response:usage- map with:input_tokensand:output_tokens
Summary
Callbacks
Send messages to the provider and get a completion response.
Stream a completion, calling on_chunk for each text delta.
Functions
Decode a JSON binary response body, passing through maps unchanged.
Recursively convert atom keys to strings in maps.
Types
@type completion_response() :: %{ stop_reason: stop_reason(), messages: [Alloy.Message.t()], usage: map() }
@type stop_reason() :: :tool_use | :end_turn
Callbacks
@callback complete( messages :: [Alloy.Message.t()], tool_defs :: [tool_def()], config :: map() ) :: {:ok, completion_response()} | {:error, term()}
Send messages to the provider and get a completion response.
Parameters
messages- Conversation history as normalizedAlloy.Messagestructstool_defs- Tool definitions (JSON Schema format)config- Provider-specific configuration (API keys, model, etc.)
Returns
{:ok, completion_response()}on success{:error, term()}on failure
@callback stream( messages :: [Alloy.Message.t()], tool_defs :: [tool_def()], config :: map(), on_chunk :: (String.t() -> :ok) ) :: {:ok, completion_response()} | {:error, term()}
Stream a completion, calling on_chunk for each text delta.
Returns the same {:ok, completion_response()} as complete/3 once
the stream finishes -- the full accumulated response.
Functions
Decode a JSON binary response body, passing through maps unchanged.
Returns {:ok, decoded_map} or {:error, reason}.
Recursively convert atom keys to strings in maps.
Used by providers to prepare JSON-compatible request bodies.