Skip to content

Latest commit

 

History

History
238 lines (167 loc) · 6.89 KB

File metadata and controls

238 lines (167 loc) · 6.89 KB
contract_type module_type contract_version last_modified related_files canonical_example
module_specification
provider
1.0.0
2025-01-29
path relationship lines
amplifier_core/interfaces.py#Provider
protocol_definition
54-119
path relationship
amplifier_core/message_models.py
request_response_models
path relationship
amplifier_core/content_models.py
event_content_types
path relationship
amplifier_core/models.py#ProviderInfo
metadata_models
path relationship
../specs/PROVIDER_SPECIFICATION.md
detailed_spec
path relationship
../specs/MOUNT_PLAN_SPECIFICATION.md
configuration
path relationship
../specs/CONTRIBUTION_CHANNELS.md
observability
path relationship
amplifier_core/testing.py
test_utilities

Provider Contract

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 Definition

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)


ModelInfo Extensions (Model Class Routing)

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

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

[project.entry-points."amplifier.modules"]
my-provider = "my_provider:mount"

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 signature in ThinkingBlock)
  • Reports Usage (input/output/total tokens)
  • Returns ChatResponse from complete()

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

# Structural validation
amplifier module validate ./my-provider --type provider

Related: PROVIDER_SPECIFICATION.md | README.md