Skip to content

Providers

A provider is the bridge between the SDK and an AI model API. The AIProvider interface has two methods — chat and stream — making it straightforward to add any model backend.

Configuring the global provider

Call configure() once at startup:

ts
import { configure, openrouter } from '@daedalus-ai-dev/ai-sdk';

configure({
  provider: openrouter({
    apiKey: process.env.OPENROUTER_API_KEY!,
  }),
  model: 'openai/gpt-4o-mini',
});

All agent() calls without an explicit provider or model will use these defaults.

OpenRouter

OpenRouter is a unified API that routes to 200+ models. It is OpenAI-compatible.

ts
import { openrouter } from '@daedalus-ai-dev/ai-sdk';

const provider = openrouter({
  apiKey: process.env.OPENROUTER_API_KEY!,
  defaultModel: 'openai/gpt-4o-mini',  // optional
  headers: {
    'HTTP-Referer': 'https://myapp.com',  // recommended for OpenRouter analytics
    'X-Title': 'My App',
  },
});

Selecting a model

Set the model globally via configure(), or per-agent:

ts
// Cheap, fast — good for classification and simple tasks
agent({ model: 'openai/gpt-4o-mini', instructions: '...' })

// Powerful — good for complex reasoning and code
agent({ model: 'anthropic/claude-3-5-sonnet', instructions: '...' })

// Large context — good for document analysis
agent({ model: 'google/gemini-flash-1.5', instructions: '...' })

OpenRouter's model list shows all available models with pricing.

The AIProvider interface

To add a new provider, implement this interface:

ts
interface AIProvider {
  chat(request: ChatRequest): Promise<ChatResponse>;
  stream(request: ChatRequest): AsyncGenerator<StreamChunk>;
}

ChatRequest

ts
interface ChatRequest {
  model: string;
  messages: Message[];
  systemPrompt?: string;
  tools?: ToolDefinition[];
  responseFormat?: {
    type: 'json_schema';
    schema: JsonSchemaObject;
    name: string;
  };
  maxTokens?: number;
  temperature?: number;
}

ChatResponse

ts
interface ChatResponse {
  id: string;
  content: MessageContent[];
  stopReason: 'end_turn' | 'tool_use' | 'max_tokens' | 'stop_sequence';
  usage: { inputTokens: number; outputTokens: number };
}

StreamChunk

ts
interface StreamChunk {
  type: 'text' | 'tool_use_start' | 'tool_use_delta' | 'tool_use_end' | 'message_end';
  text?: string;
  toolUseId?: string;
  toolName?: string;
  toolInputDelta?: string;
  stopReason?: StopReason;
  usage?: Usage;
}

Building a custom provider

Here is a complete example of a custom provider for any OpenAI-compatible API:

ts
import type { AIProvider, ChatRequest, ChatResponse, StreamChunk } from '@daedalus-ai-dev/ai-sdk';

class MyOpenAIProvider implements AIProvider {
  constructor(
    private readonly apiKey: string,
    private readonly baseUrl = 'https://api.openai.com/v1',
  ) {}

  async chat(request: ChatRequest): Promise<ChatResponse> {
    const res = await fetch(`${this.baseUrl}/chat/completions`, {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${this.apiKey}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        model: request.model,
        messages: this.mapMessages(request),
        // ... map other fields
      }),
    });

    const json = await res.json();
    return this.mapResponse(json);
  }

  async *stream(request: ChatRequest): AsyncGenerator<StreamChunk> {
    // Implement SSE streaming
    yield { type: 'text', text: '...' };
    yield { type: 'message_end', stopReason: 'end_turn' };
  }

  private mapMessages(request: ChatRequest) { /* ... */ }
  private mapResponse(json: unknown): ChatResponse { /* ... */ }
}

// Use it
configure({ provider: new MyOpenAIProvider(process.env.OPENAI_API_KEY!) });

Provider per agent

You can override the provider for a single agent, which is useful when mixing providers in one application:

ts
const cheapProvider = openrouter({ apiKey: '...', defaultModel: 'openai/gpt-4o-mini' });
const powerfulProvider = openrouter({ apiKey: '...', defaultModel: 'anthropic/claude-opus' });

// Classification — use cheap model
const classification = await agent({
  instructions: 'Classify the input.',
  provider: cheapProvider,
}).prompt(query);

// Final answer — use powerful model
const answer = await agent({
  instructions: 'Answer the question thoroughly.',
  provider: powerfulProvider,
}).prompt(query);

Released under the MIT License.