Skip to content

Providers & models

A provider is a one-method object: complete(messages, tools) -> ModelResponse. That's the entire contract the kernel depends on. An optional stream(...) adds token streaming.

from spine_core import Provider, Message, ModelResponse

class MyProvider:
    async def complete(self, messages, tools=None, **kw) -> ModelResponse:
        ...

Because the contract is this small, nothing in the kernel knows about any specific vendor — you can target any model.

The registry

Providers register under a scheme so a string resolves to one:

from spine_core import register_provider

register_provider("myllm", lambda model: MyProvider(model))
agent = Agent("myllm:some-model")

Installed adapters self-register on import. spine-providers registers openai: and anthropic:.

Streaming

If a provider implements stream, agent.stream() emits a token trace event per delta and assembles the final response:

async for event in agent.stream("write a haiku"):
    if event.type == "token":
        print(event.data["delta"], end="")

run() stays non-streaming. See Tracing, streaming & replay.

The router

A router is itself a provider that wraps an ordered list and applies fallback policies — so the kernel is oblivious to whether it's talking to one model or many. Use ModelFallback middleware for error-driven failover.

For the full list of supported and reachable models, see Models & any provider.