LLM API Reference¶
The anchor.llm module provides a unified interface for multiple LLM providers. It defines the LLMProvider protocol, a BaseLLMProvider base class with retry logic, a provider registry with automatic routing, and structured data models for messages, responses, and errors.
All classes are importable from anchor.llm:
from anchor.llm import (
LLMProvider, BaseLLMProvider,
create_provider, register_provider,
FallbackProvider,
Message, Role, LLMResponse, StreamChunk, Usage, StopReason,
ContentBlock, ToolCall, ToolCallDelta, ToolResult, ToolSchema,
ProviderError, AuthenticationError, RateLimitError, ServerError,
LLMTimeoutError, ModelNotFoundError, ContentFilterError,
ProviderNotInstalledError,
MODEL_PRICING, calculate_cost,
)
LLMProvider (Protocol)¶
A runtime-checkable protocol that all LLM providers must satisfy. Use this as the type hint when accepting any provider.
@runtime_checkable
class LLMProvider(Protocol):
@property
def model_id(self) -> str: ...
@property
def provider_name(self) -> str: ...
def invoke(self, messages, *, tools=None, max_tokens=None, temperature=None, stop=None, **kwargs) -> LLMResponse: ...
def stream(self, messages, *, tools=None, max_tokens=None, temperature=None, stop=None, **kwargs) -> Iterator[StreamChunk]: ...
async def ainvoke(self, messages, *, tools=None, max_tokens=None, temperature=None, stop=None, **kwargs) -> LLMResponse: ...
def astream(self, messages, *, tools=None, max_tokens=None, temperature=None, stop=None, **kwargs) -> AsyncIterator[StreamChunk]: ...
Properties¶
| Property | Type | Description |
|---|---|---|
model_id | str | Fully qualified model identifier (e.g. "openai/gpt-4o") |
provider_name | str | Provider name (e.g. "anthropic", "openai") |
Methods¶
invoke¶
def invoke(
self,
messages: list[Message],
*,
tools: list[ToolSchema] | None = None,
max_tokens: int | None = None,
temperature: float | None = None,
stop: list[str] | None = None,
**kwargs: Any,
) -> LLMResponse
Send messages and return a complete response synchronously.
stream¶
def stream(
self,
messages: list[Message],
*,
tools: list[ToolSchema] | None = None,
max_tokens: int | None = None,
temperature: float | None = None,
stop: list[str] | None = None,
**kwargs: Any,
) -> Iterator[StreamChunk]
Send messages and yield response chunks as they arrive.
ainvoke¶
async def ainvoke(
self,
messages: list[Message],
*,
tools: list[ToolSchema] | None = None,
max_tokens: int | None = None,
temperature: float | None = None,
stop: list[str] | None = None,
**kwargs: Any,
) -> LLMResponse
Async variant of invoke().
astream¶
def astream(
self,
messages: list[Message],
*,
tools: list[ToolSchema] | None = None,
max_tokens: int | None = None,
temperature: float | None = None,
stop: list[str] | None = None,
**kwargs: Any,
) -> AsyncIterator[StreamChunk]
Async variant of stream().
Common Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
messages | list[Message] | required | Conversation messages |
tools | list[ToolSchema] \| None | None | Tool definitions available to the model |
max_tokens | int \| None | None | Maximum tokens in the response |
temperature | float \| None | None | Sampling temperature |
stop | list[str] \| None | None | Stop sequences |
BaseLLMProvider¶
Abstract base class that implements retry logic, error mapping, and the LLMProvider protocol. Subclass this to add a new provider.
Constructor¶
class BaseLLMProvider(ABC):
def __init__(
self,
model: str,
*,
api_key: str | None = None,
base_url: str | None = None,
max_retries: int = 2,
timeout: float = 60.0,
**kwargs: Any,
) -> None
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
model | str | required | Model name within the provider |
api_key | str \| None | None | API key (resolved by _resolve_api_key if not set) |
base_url | str \| None | None | Override the provider's default base URL |
max_retries | int | 2 | Number of retries on transient errors |
timeout | float | 60.0 | Request timeout in seconds |
Properties¶
| Property | Type | Description |
|---|---|---|
model_id | str | Returns "{provider_name}/{model}" |
provider_name | str | Set by each subclass (e.g. "anthropic") |
Public Methods¶
The public methods invoke, stream, ainvoke, and astream wrap the abstract _do_* methods with retry logic for transient errors.
Abstract Methods (for subclasses)¶
| Method | Description |
|---|---|
_resolve_api_key() -> str | Resolve the API key from environment or config |
_do_invoke(messages, **kwargs) -> LLMResponse | Provider-specific invoke |
_do_stream(messages, **kwargs) -> Iterator[StreamChunk] | Provider-specific stream |
_do_ainvoke(messages, **kwargs) -> LLMResponse | Provider-specific async invoke |
_do_astream(messages, **kwargs) -> AsyncIterator[StreamChunk] | Provider-specific async stream |
create_provider¶
Factory function that creates a provider from a "provider/model" string.
Signature¶
def create_provider(
model: str,
*,
api_key: str | None = None,
fallbacks: list[str] | None = None,
**kwargs: Any,
) -> LLMProvider
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
model | str | required | Provider-prefixed model string (e.g. "openai/gpt-4o") |
api_key | str \| None | None | API key passed to the provider |
fallbacks | list[str] \| None | None | Fallback model strings; wraps result in FallbackProvider |
A model string without a prefix defaults to "anthropic" for backward compatibility.
Example¶
from anchor.llm import create_provider
# Single provider
provider = create_provider("openai/gpt-4o")
response = provider.invoke(messages)
# With fallbacks
provider = create_provider(
"anthropic/claude-sonnet-4-20250514",
fallbacks=["openai/gpt-4o"],
)
register_provider¶
Register a custom provider class in the global registry.
Signature¶
Parameters
| Parameter | Type | Description |
|---|---|---|
name | str | Prefix used in model strings (e.g. "mycloud") |
cls | type[BaseLLMProvider] | Provider class to instantiate |
Example¶
from anchor.llm import register_provider, BaseLLMProvider
class MyProvider(BaseLLMProvider):
provider_name = "mycloud"
...
register_provider("mycloud", MyProvider)
provider = create_provider("mycloud/my-model")
FallbackProvider¶
Wraps a primary provider with one or more fallback providers. On transient errors, automatically retries with the next provider in the chain.
Constructor¶
class FallbackProvider:
def __init__(
self,
primary: LLMProvider,
fallbacks: list[LLMProvider],
) -> None
Parameters
| Parameter | Type | Description |
|---|---|---|
primary | LLMProvider | The preferred provider tried first |
fallbacks | list[LLMProvider] | Providers tried in order on transient failure |
Properties¶
| Property | Type | Description |
|---|---|---|
model_id | str | Delegates to the primary provider |
provider_name | str | Delegates to the primary provider |
Fallback Behavior¶
invoke/ainvoke: On a transientProviderError, tries each fallback in order until one succeeds.stream/astream: Fallback is attempted only before the first chunk is yielded. Mid-stream errors propagate to the caller.
Supported Providers¶
| Provider | Model Prefix | SDK Package | Install Extra |
|---|---|---|---|
| Anthropic | anthropic/ | anthropic | pip install astro-anchor[anthropic] |
| Claude Code CLI | claude_cli/ | claude-agent-sdk | pip install astro-anchor[claude-cli] |
| OpenAI | openai/ | openai | pip install astro-anchor[openai] |
| Google Gemini | gemini/ | google-genai | pip install astro-anchor[gemini] |
| Grok (xAI) | grok/ | openai | pip install astro-anchor[openai] |
| Ollama | ollama/ | ollama | pip install astro-anchor[ollama] |
| OpenRouter | openrouter/ | openai | pip install astro-anchor[openai] |
| LiteLLM | litellm/ | litellm | pip install astro-anchor[litellm] |
Data Models¶
All models are frozen Pydantic BaseModel instances unless otherwise noted.
Role¶
Message¶
class Message(BaseModel):
role: Role
content: str | list[ContentBlock] | None = None
tool_calls: list[ToolCall] | None = None
tool_result: ToolResult | None = None
name: str | None = None
| Field | Type | Default | Description |
|---|---|---|---|
role | Role | required | Message role |
content | str \| list[ContentBlock] \| None | None | Text or multimodal content |
tool_calls | list[ToolCall] \| None | None | Tool calls requested by the assistant |
tool_result | ToolResult \| None | None | Result of a tool invocation |
name | str \| None | None | Optional participant name |
ContentBlock¶
class ContentBlock(BaseModel):
type: str
text: str | None = None
image_url: str | None = None
image_base64: str | None = None
media_type: str | None = None
ToolCall¶
ToolCallDelta¶
class ToolCallDelta(BaseModel):
index: int
id: str | None = None
name: str | None = None
arguments_fragment: str | None = None
ToolResult¶
ToolSchema¶
Usage¶
class Usage(BaseModel):
prompt_tokens: int
completion_tokens: int
total_tokens: int
total_cost: float | None = None
StopReason¶
LLMResponse¶
class LLMResponse(BaseModel):
content: str | None = None
tool_calls: list[ToolCall] | None = None
usage: Usage | None = None
model: str | None = None
provider: str | None = None
stop_reason: StopReason | None = None
StreamChunk¶
class StreamChunk(BaseModel):
content: str | None = None
tool_call_delta: ToolCallDelta | None = None
usage: Usage | None = None
stop_reason: StopReason | None = None
Pricing¶
MODEL_PRICING¶
A dictionary mapping model name patterns to per-token costs. Used by calculate_cost to estimate request costs.
calculate_cost¶
Returns the estimated cost in USD for the given model and token usage, or None if the model is not in MODEL_PRICING.
Errors¶
All runtime provider errors inherit from ProviderError. Each error carries a provider string and an is_transient flag that controls retry behavior.
ProviderError¶
Base class for all provider errors.
Error Subclasses¶
| Error | is_transient | Description |
|---|---|---|
AuthenticationError | False | Invalid or missing API key |
RateLimitError | True | Rate limit exceeded; has optional retry_after: float \| None |
ServerError | True | Provider returned a 5xx error |
LLMTimeoutError | True | Request timed out |
ModelNotFoundError | False | Requested model does not exist |
ContentFilterError | False | Content blocked by the provider's safety filter |
ProviderNotInstalledError¶
Raised at setup time when a required SDK package is not installed. This is not a subclass of ProviderError since it is a configuration issue, not a runtime error.
See Also¶
- Agent API Reference -- the Agent that consumes LLM providers
- Exceptions Reference -- other framework exceptions
- Protocols Reference -- extension point protocols