Skip to content

Model Providers & Fallback

ArchadiAgent never talks to a vendor SDK directly — everything goes through the ModelProvider interface (providers/ModelProvider.ts):

ts
interface ModelProvider {
  readonly name: string;
  generate(request: ModelRequest): Promise<ModelResponse>;
  stream(request: ModelRequest): AsyncIterable<ModelStreamEvent>;
}

Three adapters ship out of the box, each translating to/from the vendor's real wire format:

ts
import { OpenAIProvider, ClaudeProvider, GeminiProvider, ProviderRegistry } from "archadi-agent";

const registry = ProviderRegistry.instance(); // singleton — register once, use everywhere
registry.register(new OpenAIProvider({ apiKey: process.env.OPENAI_API_KEY! }));
registry.register(new ClaudeProvider({ apiKey: process.env.ANTHROPIC_API_KEY! }));
registry.register(new GeminiProvider({ apiKey: process.env.GEMINI_API_KEY! }));

An agent references a provider by name, decoupling "which model" from "which agent":

ts
Agent.builder().model({ provider: "claude", model: "claude-sonnet-5" })

Writing your own provider

Implement the interface and register it — the Runner doesn't care:

ts
class MyLocalLlamaProvider implements ModelProvider {
  readonly name = "local-llama";
  async generate(request) { /* call your local server */ }
  async *stream(request) { /* yield text_delta / tool_call / done */ }
}
registry.register(new MyLocalLlamaProvider());

Retries, timeouts, fallback chains

ts
Agent.builder()
  .model({ provider: "openai", model: "gpt-4o-mini", timeoutMs: 20_000 })
  .fallbackModel({ provider: "claude", model: "claude-sonnet-5" })
  .fallbackModel({ provider: "gemini", model: "gemini-2.0-flash" })
  .build();

Each turn tries the primary target first, with exponential-backoff retries (DEFAULT_RETRY: 3 attempts, 300ms base delay, jittered). If it still fails, the Runner moves to the next fallback target and repeats — see generateWithFallback in providers/resilience.ts. Every retry emits a retry event and a retry trace span.

Override the retry budget per target:

ts
.model({ provider: "openai", model: "gpt-4o-mini", retry: { maxAttempts: 5, baseDelayMs: 500, maxDelayMs: 8000 } })