ORXA: LLM-SDK vs the Official Provider SDKs

Comparing @combycode/llm-sdk with the official TypeScript SDKs: openai, @anthropic-ai/sdk, @google/genai, and xai-sdk.

The thesis

The official SDKs are excellent at what they do: give you a fully-typed, up-to-the-day client for ONE vendor. The cost of that focus is fragmentation. Add a second provider and you immediately deal with three incompatible API shapes, three client construction patterns, three ways to extract text, and zero shared cost or observability primitives.

ORXA: LLM-SDK is the adapter layer that hides this fragmentation without adding a network hop or a runtime dependency. Some of these capabilities do exist elsewhere — OpenAI's Agents SDK has guardrails and human-in-the-loop, Google's ADK has agent tooling, and OpenAI and Google each ship their own retrieval — but always provider-locked, in a separate framework. ORXA unifies all of it (RAG, guardrails, HITL approval, permission policies, pre-flight cost estimation) across every provider, direct, in one zero-dependency package.

The API shape problem

Each provider chose a different request/response contract:

Provider Request shape How to read text out
OpenAI (Responses API)input: string | ResponseInputItem[]r.output_text
Anthropic (Messages API)messages: [{role, content}]r.content.filter(b => b.type==='text').map(b => b.text).join('')
Google (generateContent)contents: string | Content[]r.text
xAI (native)client.chat.create(...).sample()r.message
ORXA: LLM-SDK (any provider)prompt: stringresult.text

Capability table

Capability ORXA: LLM-SDK OpenAI SDK Anthropic SDK Google SDK
Multi-provider, one interface yes no no no
Per-call $-cost + budgets yes tokens tokens tokens
Observability (OTel), all providers yes Agents SDK no no
Rate-limit queue + retry queue + retry retry only retry only retry only
Runtime dependencies 0 0 2 4
Unified media gen (image/audio/video) yes per-provider no per-provider
Built-in MCP client (no extra dep) yes hosted only hosted only extra dep
Unified RAG across providers yes OpenAI only no Google only
Agent guardrails yes Agents SDK no ADK
HITL approval (pause/resume) yes Agents SDK no ADK
Pre-flight cost estimate yes no no no

Notes: "tokens" = the completion response returns token usage; computing per-call $ is on you (ORXA does it automatically — provider cost field for xAI/OpenRouter, else a bundled catalog). "Agents SDK" / "ADK" = present only in OpenAI's Agents SDK / Google's ADK — provider-locked, separate frameworks. "retry only" = automatic retries, but no per-provider rate-limit queue. Dependency counts are exact. Browser support is omitted deliberately: all of these run client-side (OpenAI/Anthropic via dangerouslyAllowBrowser, Google has a documented browser path), with the same key-exposure caveat — so it is not a differentiator.

MCP: four stories vs one (scenario 29)

Provider Approach Extra dependency
OpenAI Hosted: hand a URL in tools — their servers call the MCP server none
Anthropic Hosted: mcp_servers + tools + beta header none
Google Client-side: install @modelcontextprotocol/sdk, build transport + Client @modelcontextprotocol/sdk
ORXA Client-side: connectMcp() built-in, works with stdio + private servers none (built in)

The hosted approach (OpenAI, Anthropic) works for public URLs only. It cannot reach a local stdio server, a company-internal server, or any server requiring custom transport. ORXA: LLM-SDK is client-side with zero extra deps.

When to choose the official SDKs instead

  • You will only ever call one provider, now and forever.
  • You need the absolute bleeding edge of a provider's API on the day it ships — the official SDK may expose a new parameter before we do.
  • You need Python or Rust today (our ports are planned, not yet shipped).
  • You are deeply integrated with provider-platform features (OpenAI Assistants object storage, Anthropic Workspaces, Google Vertex agents) that have no cross-provider equivalent to abstract.

Migration

See the getting started guide and the migration guides (shipping with full docs in Phase 2). The pattern is the same in every case: replace the provider client construction and the call site with complete() or createLLM(); the rest of your code stays the same.

Get started