Provider Contract¶
Providers integrate LLM backends into Amplifier.
Purpose¶
Providers translate between Amplifier's unified message format and vendor-specific LLM APIs.
Detailed Specification¶
See PROVIDER_SPECIFICATION.md for complete implementation guidance including:
- Protocol summary and method signatures
- Content block preservation requirements
- Role conversion patterns
- Auto-continuation handling
- Debug levels and observability
This contract document provides the quick-reference essentials. The specification contains the full details.
Protocol¶
Source: amplifier_core/interfaces.py lines 65-128
from typing import Protocol, runtime_checkable
from amplifier_core.models import ProviderInfo, ModelInfo
from amplifier_core.message_models import ChatRequest, ChatResponse, ToolCall
@runtime_checkable
class Provider(Protocol):
@property
def name(self) -> str:
"""Provider name."""
...
def get_info(self) -> ProviderInfo:
"""Get provider metadata."""
...
async def list_models(self) -> list[ModelInfo]:
"""List available models."""
...
async def complete(
self,
request: ChatRequest,
**kwargs
) -> ChatResponse:
"""Generate completion from ChatRequest."""
...
def parse_tool_calls(
self,
response: ChatResponse
) -> list[ToolCall]:
"""Parse tool calls from response."""
...
Note: ToolCall is from amplifier_core.message_models (see REQUEST_ENVELOPE_V1 for details)
ModelInfo Extensions (Model Class Routing)¶
The list_models() method returns list[ModelInfo]. Beyond the required fields, ModelInfo supports optional extension fields for model class routing and cost-aware selection:
| Field | Type | Default | Description |
|---|---|---|---|
cost_per_input_token | float \| None | None | Cost per input token in USD (e.g., 3e-6 for $3/MTok) |
cost_per_output_token | float \| None | None | Cost per output token in USD |
metadata | dict[str, Any] | {} | Extensible metadata bag for cost tier, model class, provider-specific tags |
Cost Fields¶
Providers SHOULD populate cost_per_input_token and cost_per_output_token when pricing information is available. These enable cost-aware model selection and budget tracking.
Metadata: cost_tier¶
Providers SHOULD set metadata["cost_tier"] to one of the well-known cost tier strings:
| Tier | Description |
|---|---|
free | No-cost models (local, free-tier) |
low | Budget-friendly models (e.g., Haiku-class) |
medium | Standard pricing (e.g., Sonnet-class) |
high | Premium pricing (e.g., Opus-class) |
extreme | Highest-cost models (e.g., deep research) |
Capabilities¶
Providers SHOULD populate the capabilities list using well-known constants from amplifier_core.capabilities. See the Capabilities Taxonomy in the Provider Specification for the full list.
Backward Compatibility¶
All extension fields are optional with sensible defaults. Existing providers that do not populate these fields continue to work unchanged — they simply won't participate in cost-aware or capability-based routing.
Entry Point Pattern¶
mount() Function¶
async def mount(coordinator: ModuleCoordinator, config: dict) -> Provider | Callable | None:
"""
Initialize and return provider instance.
Returns:
- Provider instance (registered automatically)
- Cleanup callable (for resource cleanup on unmount)
- None for graceful degradation (e.g., missing API key)
"""
api_key = config.get("api_key") or os.environ.get("MY_API_KEY")
if not api_key:
logger.warning("No API key - provider not mounted")
return None
provider = MyProvider(api_key=api_key, config=config)
await coordinator.mount("providers", provider, name="my-provider")
async def cleanup():
await provider.client.close()
return cleanup
pyproject.toml¶
Configuration¶
Providers receive configuration via Mount Plan:
providers:
- module: my-provider
source: git+https://github.com/org/my-provider@main
config:
api_key: "${MY_API_KEY}"
default_model: model-v1
debug: true
See MOUNT_PLAN_SPECIFICATION.md for full schema.
Observability¶
Register custom events via contribution channels:
coordinator.register_contributor(
"observability.events",
"my-provider",
lambda: ["my-provider:rate_limit", "my-provider:retry"]
)
See CONTRIBUTION_CHANNELS.md for the pattern.
Canonical Example¶
Reference implementation: amplifier-module-provider-anthropic
Study this module for: - Complete Provider protocol implementation - Content block handling patterns - Configuration and credential management - Debug logging integration
Validation Checklist¶
Required¶
- Implements all 5 Provider protocol methods
-
mount()function with entry point in pyproject.toml - Preserves all content block types (especially
signaturein ThinkingBlock) - Reports
Usage(input/output/total tokens) - Returns
ChatResponsefromcomplete()
Recommended¶
- Graceful degradation on missing config (return None from mount)
- Validates tool call/result sequences
- Supports debug configuration flags
- Registers cleanup function for resource management
- Registers observability events via contribution channels
Testing¶
Use test utilities from amplifier_core/testing.py:
from amplifier_core.testing import TestCoordinator, create_test_coordinator
@pytest.mark.asyncio
async def test_provider_mount():
coordinator = create_test_coordinator()
cleanup = await mount(coordinator, {"api_key": "test-key"})
assert "my-provider" in coordinator.get_mounted("providers")
if cleanup:
await cleanup()
Quick Validation Command¶
Related¶
- PROVIDER_SPECIFICATION.md - Detailed specification
- README.md - Module contracts overview