How Instatic's AI Agent Integrates with External Providers Without SDKs

Instatic's AI subsystem uses a provider-agnostic runtime that communicates with LLM services through plain HTTP calls and shared adapters, completely eliminating vendor SDK dependencies while maintaining type safety through schema validation.

Instatic, an open-source project by CoreBunch, implements a lightweight AI agent that integrates with external LLM providers like OpenAI and OpenRouter without relying on official SDKs. This architectural approach reduces bundle size, maintains sandbox compatibility, and enables rapid provider expansion through native fetch calls and modular driver implementations. The system allows Instatic's AI agent to integrate with external providers without SDKs by delegating all transport logic to a shared HTTP tool loop and Responses Adapter layer.

The Three-Layer Provider Architecture

The integration strategy centers on three distinct layers that abstract away vendor specifics while preserving full functionality.

Common HTTP & Tool Loop

At the heart of the system sits the shared execution layer. The server/ai/drivers/http/toolLoop.ts module owns the agentic loop, handling Server-Sent Events (SSE) parsing, multi-turn tool execution, and error classification. All providers delegate their streaming work to this shared loop via the runToolLoop function, ensuring consistent behavior across different LLM backends.

Responses Adapter

The server/ai/drivers/responses-shared.ts module functions as the translation layer between vendor-specific wire protocols and Instatic's internal event system. This Responses Adapter isolates provider-specific details such as endpoint URLs, authentication headers, and request payload fields, converting external "Responses" formats (used by OpenAI and OpenRouter) into the internal AiStreamEvent shape defined in server/ai/runtime/types.ts.

Provider Drivers

Each LLM service implements a minimal driver that specifies only transport details and model catalogue handling. These drivers never import vendor SDKs, instead relying on native fetch for HTTP communication and TypeBox schemas (parseValue) for runtime validation. Because the drivers avoid heavyweight dependencies entirely, the runtime remains sandbox-friendly and bundle-efficient.

Provider Implementation Examples

The actual integration code demonstrates how lightweight these drivers remain without SDK dependencies.

OpenAI Driver Implementation

Located in server/ai/drivers/openai.ts, the OpenAI driver defines the transport layer using raw HTTP requests to https://api.openai.com/v1/responses:

// server/ai/drivers/openai.ts
export const openaiDriver: AiProvider = {
  id: 'openai' as AiProviderId,
  label: 'OpenAI',
  supportedAuthModes: ['apiKey'],
  capabilities(_modelId) {
    return {
      toolCalling: true,
      visionInput: true,
      toolResultImages: false,
      promptCache: false,
      streaming: true,
    }
  },
  async listModels(creds, signal) {
    return fetchOpenAiModels(creds, signal)   // live catalogue
  },
  async *stream(req) {
    if (req.credentials.authMode !== 'apiKey' || !req.credentials.apiKey) {
      yield { type: 'error', message: 'OpenAI requires an API key …' }
      return
    }
    // Delegate to shared tool loop
    yield* runToolLoop(openaiAdapter, req)
  },
}

The driver builds required headers manually, defines a stable-hash prompt-cache key, and retrieves the model list from https://api.openai.com/v1/models via fetchOpenAiModels.

OpenRouter Driver Implementation

Similarly, server/ai/drivers/openrouter.ts communicates with https://openrouter.ai/api/v1/responses and retrieves the catalogue from https://openrouter.ai/api/v1/models:

// server/ai/drivers/openrouter.ts
async function fetchOpenRouterModels(
  creds: AiResolvedCredential,
  signal?: AbortSignal,
): Promise<AiProviderModel[]> {
  const headers: Record<string, string> = {}
  if (creds.apiKey) headers.Authorization = `Bearer ${creds.apiKey}`

  const res = await fetch(`${OPENROUTER_BASE_URL}/models`, { headers, signal })
  const parsed = parseValue(OpenRouterModelsResponseSchema, await res.json())
  // Build AiProviderModel objects with capabilities, pricing, etc.
  return parsed.data.map(model => ({
    id: model.id,
    label: model.name ?? model.id,
    capabilities: { … },
    pricing: …,
    contextWindow: …,
  }))
}

This driver adds the bearer token to public catalogue requests when present, then delegates streaming to the shared tool loop exactly like the OpenAI implementation.

Shared Tool Loop Execution

The runToolLoop function in server/ai/drivers/http/toolLoop.ts orchestrates the actual HTTP communication and event translation without SDK intermediaries:

// server/ai/drivers/http/toolLoop.ts (simplified)
export async function* runToolLoop(
  adapter: ResponsesAdapter,
  req: AiStreamRequest,
): AsyncIterable<AiStreamEvent> {
  // 1️⃣ POST request → SSE stream
  const response = await fetch(adapter.endpoint, {
    method: 'POST',
    headers: adapter.buildHeaders(req),
    body: JSON.stringify(req),
  })
  // 2️⃣ Parse SSE, translate with `adapter.translate` into AiStreamEvent
  for await (const raw of parseSse(response.body)) {
    yield adapter.translate(raw)
  }
}

This function leverages the low-level SSE parser in server/ai/drivers/http/sse.ts to handle streaming responses, maintaining backpressure and cancellation support through AsyncIterable patterns.

Live Model Catalogue Management

Rather than relying on static fallback lists, Instatic fetches model catalogues dynamically. For OpenAI, the driver filters the raw list to include only chat and reasoning models, applying heuristic functions like deriveLabel and deriveTier to generate user-friendly metadata. OpenRouter's implementation parses capabilities, pricing tiers, and context windows directly from the API response, constructing AiProviderModel objects without intermediate SDK transformation layers. Validation occurs at the boundary via parseValue TypeBox schemas, ensuring type safety without "as …" casts.

Summary

Instatic's SDK-free integration strategy delivers several architectural advantages:

  • Zero SDK Dependencies: Drivers use native fetch and manual header construction, avoiding heavyweight vendor libraries
  • Minimal Bundle Size: Eliminating SDKs reduces deployment footprint and improves load times
  • Sandbox Compatibility: Pure HTTP implementations avoid native module dependencies that complicate sandboxed environments
  • Rapid Provider Expansion: New LLM services require only a thin driver implementing the AiProvider interface and plugging into runToolLoop
  • Runtime Type Safety: TypeBox schemas (parseValue) validate all external data at system boundaries without TypeScript casting

Frequently Asked Questions

Why does Instatic avoid official SDKs for LLM integrations?

Official SDKs introduce significant bundle overhead and often require native dependencies that complicate deployment in sandboxed or edge environments. By using native fetch and manual protocol handling, Instatic maintains a lightweight runtime that communicates directly with provider HTTP endpoints while retaining full control over request and response transformation via the Responses Adapter.

How does Instatic maintain type safety without SDK type definitions?

The codebase uses TypeBox schemas accessed via the parseValue function to validate all external API responses at runtime. This approach, combined with the strongly-typed AiProvider interface defined in server/ai/runtime/types.ts, ensures that vendor-specific payloads conform to internal AiStreamEvent shapes without relying on SDK-generated types or unsafe casting.

What is required to add a new LLM provider to Instatic?

Developers must create a driver file similar to server/ai/drivers/openai.ts that implements the AiProvider interface, specifying the base endpoint, authentication header construction, and model catalogue fetching logic. The driver then delegates streaming requests to the shared runToolLoop function with an appropriate adapter from server/ai/drivers/responses-shared.ts, enabling immediate integration without installing additional dependencies.

How does streaming work without SDK abstractions?

Streaming relies on the runToolLoop generator function in server/ai/drivers/http/toolLoop.ts, which POSTs requests to provider endpoints and consumes responses using the native fetch API. The function pipes the response body through parseSse from server/ai/drivers/http/sse.ts to handle Server-Sent Events, then translates raw chunks into internal events using the provider-specific adapter, maintaining full control over the byte stream without SDK buffering layers.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →