Every AI system we build talks to more than one model provider. The translation layer underneath is tedious, easy to get subtly wrong, and the same in every project. So we wrote it once, in the open.
Every multi-model system we have shipped for a client had the same unglamorous layer in it. Anthropic, OpenAI and a self-hosted open-weight model each come with their own SDK, their own request shape, their own response shape, and their own way of counting tokens. Application code written against one of them ends up shaped like it. Adding a second provider means a translation layer, and nobody on the team wants to own that layer, because it is pure plumbing and it breaks every time an SDK moves.
The layer matters more than it looks. In one engagement, a YC-backed startup was spending about $230,000 a month across Anthropic, OpenAI and other providers. Routing each task to the cheapest model that passed its evaluations, trimming context, and moving steady workloads onto the startup's own GPUs brought provider spend down 47.7%. None of that is possible when swapping a model means rewriting call sites.
In 2026 we started a toolkit for running our own practice, and the first thing it needed was that layer again. This time we wrote it in the open. The package began life as a router and was renamed within a day of its first commit, once it was clear that translating between providers and choosing between models are different jobs that deserve different code. AI Bridge does the translating. The choosing stays with you, or with whatever you build on top.
Calls OpenAI, Anthropic, Ollama, Ollama Cloud or a provider you write yourself through one canonical request, and returns one canonical response that can be projected into any shape you registered. Providers and dialects are injected at startup, so the return type of a projection is inferred from what you passed in rather than cast.
Use it when your TypeScript code calls models directly and you want the provider to be a parameter instead of an architecture decision.
Version 0.1.0. Builds from source; npm publishing is configured but not yet done.
Puts AI Bridge behind one HTTP endpoint. Named accounts keep API keys on the server, model aliases let you change the model behind a name with a config edit, and the ai-gateway command sends the same requests from the terminal or a shell pipeline.
Use it when several services or languages need the same model access, when credentials should live in exactly one place, or when a model swap should not require a redeploy.
Version 0.1.0. Builds from source alongside AI Bridge; runs as a mountable Hono app or a standalone listener.
The bridge is the foundation and runs inside your process. The gateway is the bridge behind a network boundary. Anything you build for one, a custom provider or a response dialect, works in the other unchanged, because the gateway accepts any bridge instance you hand it.
If you need
Reach for
TypeScript code that calls models directly
AI Bridge
The same model access from Python, Go, or a shell script
AI Gateway over HTTP
API keys kept out of every caller
AI Gateway named accounts
Swap the model behind a name without redeploying callers
AI Gateway model aliases
A provider or response shape nobody else supports
A custom adapter or dialect in AI Bridge; it works in AI Gateway unchanged
Pick the model per task from evaluation results
Neither, yet. See the status section below
How We Build Them
A few decisions run through both projects. They are the reason this is not just another wrapper, and they are the things a contributor is most likely to trip over.
Our own baseline, not OpenAI-compatible
Most universal model layers standardise on OpenAI's Chat Completions format. We considered it and rejected it, because that format cannot carry signed Anthropic thinking blocks and their replay, explicit prompt-cache controls and cache-write accounting, or Ollama's runtime settings and timings. The bridge has its own baseline that covers the union of those features, and the OpenAI shape is one dialect among several. You can still send an OpenAI-shaped request to Anthropic, and you can still ask for an OpenAI-shaped response back. You just do not lose information when the provider is not OpenAI.
Injection, not registration
There is no global registry and no central list of provider names to edit. You pass providers and dialects to createBridge, and their names and native types flow from the objects you passed. Two bridges in one process can carry different registries. Tests pass in fake transports the same way production passes in real ones.
Errors instead of guesses
A request feature the target provider cannot express fails before the network call, with UnsupportedFeatureError. Token counts a provider did not report stay null rather than becoming zero. Several candidate responses are never silently collapsed into one message. Model prices are recorded only when a provider states them and are never inferred. Where a target schema forces a value to be synthesised, such as OpenAI's created timestamp when the source has none, the documentation names it.
The raw response is always there
Every response carries the untouched provider payload next to the canonical one. A projection into another dialect may drop fields that dialect has no slot for, but nothing is lost. When a provider ships a field nobody anticipated, it is already in your logs.
Credentials stay on the server
In the gateway, callers refer to accounts by name and never see a key. The accounts listed in the config file are the complete registry; nothing in the environment is picked up by accident. The endpoint that lists accounts returns no secrets and no environment variable names, and error responses carry a short message and a status code, never an SDK payload or a stack trace. The gateway ships without authentication on purpose: it is a Hono app, so you mount it behind the middleware you already trust, or keep the standalone listener on localhost.
Tests run offline
Both suites run against mocked transports and need no API keys, so a contributor can clone, test and build without an account anywhere. The gateway's smoke tests drive all four built-in providers through a real HTTP listener against mocked upstreams.
Where They Are Today
Both projects are at version 0.1.0 and a few days old. They are developed inside our internal tooling monorepo and published to their own repositories, so each one builds and tests as a standalone checkout. npm publishing is configured and has not happened yet; for now, build from source.
The bridge covers non-streaming chat: text and image input, function tools and tool history, reasoning and thinking controls, prompt-cache accounting, structured output, provider-native extensions, response projections and timings. Streaming, embeddings, batches, retries, fallback orchestration, price calculation and response caching are deferred, not forgotten. Each needs a contract of its own, and we would rather ship a small thing that is right than a large thing that is approximately right.
The piece that chooses models, the half of the original router that was split out, is the thing we are asked about most. It is the technique behind the cost reduction above and it is not released yet. When it is, it will sit on top of the bridge rather than inside it. Follow the GitHub organization if you want to know when.
What open-source software does ProductiveHub publish?
Two MIT-licensed TypeScript projects for building systems on more than one AI model provider. AI Bridge is a library that gives your code one provider-neutral format for OpenAI, Anthropic, Ollama and custom providers. AI Gateway wraps it in an HTTP API and a command-line tool with named accounts and model aliases. Both live on GitHub under the productivehub organization.
What is the difference between AI Bridge and AI Gateway?
AI Bridge runs inside your TypeScript process and translates between provider APIs. AI Gateway is a server and CLI built on AI Bridge, so other languages, services and shell scripts can share the same model access over HTTP, with credentials held on the server. If one TypeScript app calls models, use the bridge. If several things need to call models, or keys must stay in one place, use the gateway.
Which AI providers do AI Bridge and AI Gateway support?
OpenAI, Anthropic, local Ollama and Ollama Cloud are built in. Any OpenAI-compatible server, such as vLLM or LM Studio, works by registering the OpenAI adapter under your own name with that server's base URL. Anything else works through a custom provider, which implements a single complete() method that returns canonical output plus the untouched native response.
Why not use the OpenAI-compatible API as the universal format?
Because it cannot carry everything the other providers return. OpenAI's Chat Completions format has no place for signed Anthropic thinking blocks and their replay, for explicit prompt-cache controls and cache-write accounting, or for Ollama's runtime settings and timings. AI Bridge keeps its own baseline that covers the union of those features, and treats the OpenAI shape as one dialect among several. You can still send and receive OpenAI-shaped payloads; you just do not lose information when the provider is not OpenAI.
Does AI Bridge choose which model to use?
No. You name the provider and model on every call, and the bridge handles the translation. Model selection, for example routing each task to the cheapest model that passes its evaluations, is a separate concern that we keep out of the bridge on purpose. The package was briefly called router before we split the two jobs apart.
What is the current status of these projects?
Both are at version 0.1.0 and are built from source; npm publishing is configured but has not happened yet. AI Bridge covers non-streaming chat with text and image input, tools, reasoning controls, cache accounting and structured output. Streaming, embeddings, batches, retries, fallback orchestration, price calculation and response caching are deliberately deferred because each needs its own contract. The test suites run offline against mocked transports and need no API keys.
Can I use AI Gateway from Python, Go or another language?
Yes. AI Gateway speaks plain HTTP. You POST AI Bridge's canonical input to /{model}, pick the provider, named account and response dialect with query parameters, and get a JSON envelope back whose usage block looks the same whichever provider answered. The gateway ships without authentication; mount it behind your existing middleware or keep the standalone listener on localhost.
What license are they under, and can I contribute?
Both projects are MIT-licensed, created and maintained by Segev Shmueli at ProductiveHub. Each repository has a contributing guide, and issues are open for bugs, provider requests and dialect requests. Architecture notes in the AI Bridge repository explain the design decisions before you start.
Building on More Than One Model?
We design and build multi-model AI systems for clients, and this is the plumbing they run on. If you are planning one and want a second opinion on the architecture, the first conversation is free.