Skip to main content

Overview

Providers are selected via the model field on each agent definition using a provider:model URI:
agents:
  assistant:
    model: "openai:gpt-4o-mini"
SirenSpec resolves the provider at runtime, instantiates the appropriate client, and calls the model’s chat completions API asynchronously.

OpenAI

Uses the official OpenAI Python SDK. URI format: openai:<model-name>
agents:
  assistant:
    model: "openai:gpt-4o-mini"
    system: "You are a helpful assistant."
Authentication:
export OPENAI_API_KEY=sk-...
Examples:
URIModel
openai:gpt-4o-miniGPT-4o mini
openai:gpt-4oGPT-4o
openai:gpt-4-turboGPT-4 Turbo
Any model name supported by the OpenAI chat completions API can be used.

Anthropic

Uses the official Anthropic Python SDK. URI format: anthropic:<model-name>
agents:
  assistant:
    model: "anthropic:claude-haiku-4-5-20251001"
    system: "You are a helpful assistant."
Authentication:
export ANTHROPIC_API_KEY=sk-ant-...
Examples:
URIModel
anthropic:claude-haiku-4-5-20251001Claude Haiku
anthropic:claude-sonnet-4-6Claude Sonnet
anthropic:claude-opus-4-7Claude Opus
The Anthropic provider extracts any system-role message and passes it as the top-level system parameter, as required by the Anthropic Messages API. max_tokens defaults to 4096 but is overridden per node by max_tokens_per_call.

Ollama

Uses Ollama’s OpenAI-compatible API via the OpenAI Python SDK. URI format: ollama:<model-name>
agents:
  assistant:
    model: "ollama:llama3.2"
    system: "You are a helpful assistant."
Configuration:
Environment variableDefaultDescription
OLLAMA_BASE_URLhttp://localhost:11434/v1Ollama server URL.
OLLAMA_API_KEYollamaAPI key (for auth-protected deployments; most local setups don’t need this).
Start Ollama locally:
ollama serve
ollama pull llama3.2
Then run your workflow:
sirenspec run workflow.yaml
Ollama must be running and the model must be pulled locally before running a workflow that references it.

Mixing Providers

You can use different providers in a single workflow. Each agent independently resolves its own provider:
agents:
  classifier:
    model: "openai:gpt-4o-mini"
    system: "Classify the user's intent as 'question' or 'complaint'."

  responder:
    model: "anthropic:claude-haiku-4-5-20251001"
    system: "You are a customer support agent. Compose a helpful reply."

nodes:
  classify:
    agent: classifier
    writes: working.intent

  reply:
    agent: responder
    writes: output.reply

edges:
  - from: classify
    to: reply
This workflow calls OpenAI for classification and Anthropic for the final response.

Error Handling

Provider URIs are validated when the workflow is executed. An invalid URI raises sirenspec.exceptions.ProviderError (a subclass of SirenSpecError):
import asyncio
from sirenspec import execute
from sirenspec.exceptions import ProviderError

try:
    asyncio.run(execute(workflow, user_input="hello"))
except ProviderError as exc:
    print(exc)  # e.g. "Unknown provider 'vertex'; supported: ['anthropic', 'ollama', 'openai']"
Common reasons a ProviderError is raised:
CauseExample URIError message
Missing colon separatoropenai-gpt4oMalformed provider URI '...'; expected 'provider:model' format
Empty model nameopenai:Malformed provider URI '...'; expected 'provider:model' format
Unknown providervertex:gemini-proUnknown provider 'vertex'; supported: [...]

Token Tracking

Each provider records prompt and completion token counts from every call. This usage data is surfaced in the execution trace under the usage field:
{
  "nodes": [
    {
      "id": "answer",
      "type": "agent",
      "tokens": 42,
      "usage": {
        "prompt_tokens": 30,
        "completion_tokens": 12,
        "estimated_usd": null
      },
      ...
    }
  ],
  "summary": {
    "total_tokens": 42,
    "total_usage": {
      "prompt_tokens": 30,
      "completion_tokens": 12,
      "total_tokens": 42,
      "estimated_usd": null
    },
    ...
  }
}
The tokens field is the sum of prompt and completion tokens; the usage field provides the detailed breakdown. estimated_usd is computed from a bundled LiteLLM pricing snapshot — it is null for models without a pricing entry (Ollama and other local backends), so the examples above show null. See Budget & Cost Control for details.