← all writing

freeport 1.1.0: toward LiteLLM parity

A release about fidelity, not features. Multi-provider routing that preserves tools, vision and JSON mode — plus an OpenAI-compatible passthrough and Anthropic-native ingress.

@reallyartificial/freeport@1.1.0 is published. This release is not about adding surface area. It is about making the surface we already have faithful — so that switching providers behind the gateway changes who answers, and nothing else.

The benchmark in our heads for this work is LiteLLM: the bar for “a request that works against OpenAI works against everyone.” 1.1.0 is a step toward that parity. We are not there on every edge, and this post is specific about where the line currently is.

The problem: routing is the easy 80%

Routing a chat completion across providers is straightforward until the request stops being plain text. The moment a request carries tools, an image, or a JSON-mode constraint, every provider has its own dialect:

  • OpenAI expects tools with a function envelope and returns tool_calls.
  • Anthropic speaks input_schema and returns tool_use content blocks.
  • Vision payloads differ in how images are attached and encoded.
  • “Give me valid JSON” is response_format in one place and a different mechanism elsewhere.

A gateway that only forwards the simple case is a gateway that breaks the instant your application gets interesting. So 1.1.0 focused on the translation layer: a request shaped like an OpenAI request should keep its tools, its image, and its JSON constraint when it is routed to a different provider, and the response should come back in the shape the caller expects.

What shipped

Multi-provider fidelity. Tool/function calling, vision inputs, and JSON-mode requests now survive the trip across providers instead of being silently dropped at the boundary. The translation runs in both directions: request in the caller’s dialect, response normalized back to it.

An OpenAI-compatible provider. Not just “we speak the OpenAI API to clients” — freeport can now treat any OpenAI-compatible endpoint as an upstream provider. Local servers, alternative hosts, OpenAI-shaped APIs you run yourself: register them as a provider and route to them like anything else. This is the unlock that makes self-hosted and proxied models first-class instead of special cases.

Anthropic-native ingress. freeport now accepts requests on the Anthropic Messages format at /v1/messages, in addition to the OpenAI-style /v1/chat/completions. If your client already speaks Anthropic, you do not have to rewrite it to put a gateway in front of it. The request comes in as Messages, gets normalized internally, and can still be routed to whichever provider you have configured.

Two ingress dialects, a normalized core, many possible upstreams — including OpenAI-compatible ones. That is the shape of the thing now.

Where the line honestly is

Parity is a direction, not a checkbox, and it would be dishonest to imply 1.1.0 closed the gap. The OpenAI and Anthropic paths are the ones we exercise most and trust most. Newer or more exotic provider features land unevenly, and streaming semantics around tool calls are an area we are still hardening. If you hit a request shape that does not translate cleanly, that is a bug, and the right place to put it is the issue tracker — not a footnote we hope you do not read.

We are saying this plainly because the alternative is the thing this org refuses to do: claim coverage we have not verified.

Why it matters

The promise of a gateway is that the provider becomes a configuration detail. That promise is empty if “switch provider” also means “lose tool calling” or “JSON mode stops working.” 1.1.0 is the release where switching providers starts to mean only what it should mean — a different model answers, and your application does not notice.

$ npm i -g @reallyartificial/freeport

It is MIT licensed and the translation layer is right there in src/. If you think a mapping is wrong, you can see exactly how we did it and tell us why.