| contract_type | module_type | contract_version | last_modified | related_files | canonical_example | ||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
module_specification |
provider |
1.0.0 |
2025-01-29 |
|
Providers translate between Amplifier's unified message format and vendor-specific LLM APIs.
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.
Source: amplifier_core/interfaces.py lines 54-119
@runtime_checkable
class Provider(Protocol):
@property
def name(self) -> str: ...
def get_info(self) -> ProviderInfo: ...
async def list_models(self) -> list[ModelInfo]: ...
async def complete(self, request: ChatRequest, **kwargs) -> ChatResponse: ...
def parse_tool_calls(self, response: ChatResponse) -> list[ToolCall]: ...Note: ToolCall is from amplifier_core.message_models (see REQUEST_ENVELOPE_V1 for details)
The list_models() method returns list[ModelInfo]. Beyond the required fields (id, display_name, context_window, max_output_tokens), 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 |
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.
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) |
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.
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.
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[project.entry-points."amplifier.modules"]
my-provider = "my_provider:mount"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: trueSee MOUNT_PLAN_SPECIFICATION.md for full schema.
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.
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
- 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()
- 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
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()# Structural validation
amplifier module validate ./my-provider --type providerRelated: PROVIDER_SPECIFICATION.md | README.md