Launch HN: Respan (YC W24) – Open-source Rust AI gateway built around plugins

2 points by Andydy25 ↗ HN
Hey HN, this is Andy from Respan (https://www.respan.ai). We are building an open-source Rust AI gateway. It is a decoupled gateway, so everything is a plugin, including different providers, protocols (MCP, voice), modalities (images, videos), and gateway features (fallbacks, PII redaction, smart routing).

Instead of packaging tons of providers and features into one gateway, Respan provides a small core and public interfaces that teams can use to assemble the AI infrastructure their application needs. That way, users can build their own features as additional plugins without having to change the gateway's core.

Here’s a video demo: https://www.youtube.com/watch?v=pVv2ibXiTXM

There are countless LLM gateways and most of them solve a common problem: calling different providers from a single endpoint. However, adding new features can become prohibitively difficult. So developers can end up building another gateway to solve a specific problem.

We've been building our gateway based on LiteLLM since 2024, and now it's providing services for thousands of orgs. Each org needs different API key settings, routes, and limits. To support that, we kept wrapping LiteLLM, adding more features to it, and at one stage, our wrapper code exceeded 100,000 lines.

This January, a routine LiteLLM upgrade caused intermittent connection errors, and we had to roll back. We still haven't figured out the cause, but since then, we no longer upgrade LiteLLM directly and instead manually backport upstream fixes. These experiences made us realize that continuing to patch LiteLLM is not a sustainable long-term solution, and we had to redesign the gateway ourselves.

While redesigning our gateway, we wanted to make it easier to add features without breaking existing ones. Inspired by Nginx, we think an AI gateway should have a really small core, only responsible for dispatching events.

We believe that everything should be a plugin in our gateway, including providers (OpenAI, Anthropic, Gemini), protocols (chat, realtime voice, MCP), modalities (images, videos), and gateway features for reliability and security (smart routing, fallbacks, and PII redaction through example plugins). Beyond that, we want developers to be able to easily extend the gateway's capabilities by adding their own plugins, without touching the core. Adding a provider, even your own, is dead simple, because quirks are plugins too and there’s nothing magical about them. A provider is a short file, Mistral’s is 22 lines, and each quirk, like Groq putting token usage in its own field, gets its own test.

Respan Gateway does more than let you call Claude or Gemini models from the OpenAI SDK. It handles tools, images, and reasoning protocols automatically: an application based on the OpenAI Realtime API can also use Gemini Live through the gateway, though not every feature translates. A simple chat app can use MCP tools configured in the gateway, without implementing MCP itself.

We also parse requests into a shared structure. When the client and provider use the same API, we preserve provider-specific fields in their native format, even if our shared structure doesn't have a field for them. That way, the gateway can write them back instead of dropping them.

Here’s how it works:

An adapter hands each HTTP or WebSocket connection to the first client format that recognizes it. The format exposes the request as a two-way stream of typed input and output events. The core runs plugins in registration order, allowing them to choose a provider, filter or wrap either stream, make additional calls, return a response, or refuse the request. A provider format then opens the upstream connection.

If the client and provider use the same format and no plugin changes the payload, the original bytes and protocol-specific fields can pass through unchanged. When formats differ, they translat...

24 comments

[ 0.41 ms ] story [ 37.9 ms ] thread
Why are plugins a desirable feature for core features?

Today I use GoModel, and in example, all providers are built in. Having recently given Pi a try, the plugin ecosystem is a mess and I have more security worries.

Can you explain why you think a plugin based system is preferable to a competent team building a complete, curated product?

Plugins seems like a great way to expose yourself to supply chain security events.

Hi, I hear your concerns, and we can clarify how this works.

In Respan, plugins are not arbitrary executables that you download from a random repository. They are modular crates that you compile into your application.

The benefit of this system is that it provides explicit processing boundaries. For example, a PII filter can register for relevant events without requiring changes across tangled client, provider, logging, and translation paths. This also makes it easier to compose features.

So we cannot just run a docker image for a gateway, we will also need an entire CI process to use this paradigm? Generally, when we use the term "plugin" in industry, this means we do not have to run a compiler.

Crates are still an avenue for supply chain compromise, they come from random developers. We've seen it before and I expect we will see in more frequently for a while, until out industry gets really serious about all the things around this.

We had a Docker image, but pulled it before launch because some APIs might still change. For now, you need to build from source.

We have configurable template plugins for common things like adding vendors and formats. No rebuild needed for config changes, but if you want custom logic beyond those templates, you need to compile it in.

And yes, crates still have supply-chain risks. I just meant you can review the source you’re adding, unlike a binary you don’t know.

Yeah, ours are more like GStreamer’s statically compiled plugins. We might consider WebAssembly in the future if there’s a need for it.
What's your plugin model for Rust? Are they compiletime or interpreted?
Thanks for the question! The plugins are natively compiled Rust crates, not interpreted or dynamically loaded.

We considered WASM and libloading. For WASM, plugins often need access to infrastructure such as databases, which would require additional host interfaces and runtime support.

Dynamic loading with libloading didn’t offer enough benefit for this design, so we chose modular crates compiled into the application.

The compile-time choice makes sense for a gateway: plugins sit in the hot path and often need database or queue access, which is awkward to expose through a WASM sandbox. The cost is the workflow verdverm points out: there is no prebuilt image to just pull and run. Do you plan to publish an official build with the default plugin set, for people who don't need custom plugins?
Good luck with the launch!

Quick question: do you personally understand the Rust code in your project, or was the whole thing AI-assisted ?

"do you personally understand the code"

classic hackernews comments

Yes, we used Claude to generate code, but we reviewed every line ourselves. For MCP, we considered rmcp, but our gateway needs hooks at each processing stage, so we would still have needed substantial custom logic. We ultimately implemented the MCP support ourselves.
The plugin boundary matters more than the number of plugins. I’d limit the core to request normalization, ordered middleware execution, cancellation, and observability. Each plugin would have a versioned manifest with declared capabilities and compatibility ranges.

Run third-party plugins out of process or in WASM so a panic, timeout, or dependency conflict can’t take down the gateway. A small conformance suite using recorded provider responses would also make API changes safer.

For prompt-facing plugins, Wordfully can tighten the wording and remove ambiguity before requests enter the gateway.

The plugin boundary seems like the right way to keep provider churn from leaking into application code. I’d be curious how teams decide which cross-cutting features belong in the core versus plugins once they need consistent policy and audit behavior.
Does the gateway give you token accounting you can trust across providers? You mention Groq putting usage in its own field, and that’s the kind of quirk that quietly breaks cost attribution. Once you’re routing across providers, cost per request is the number most teams actually want out of a gateway, and it’s only as good as the worst provider’s usage reporting.
Replying since this one didn’t get an answer. I’ve been building a gateway too and usage reporting is the annoying part. Groq only gives you usage on streamed responses if you ask for it with stream_options, otherwise you’re guessing. Mistral has no equivalent at all, so for streams you end up estimating from response length. Curious how Respan handles that, or if the plugin just trusts whatever the provider sends back.
The point about plugin boundaries and safety is spot on. In Rust, choosing between compile-time static dispatch (like trait objects / generics) vs. runtime dynamic loading is always the hardest architectural trade-off for a gateway.

Compile-time is blazing fast and gives you strong safety guarantees, but forces users to recompile the binary for custom plugins. Runtime/WASM gives you isolation and hot-reloading, but introduces serialization overhead on the hot path. Curious how Respan handles that split for third-party extensions.

Aren't high-level compilers passé? Don't see why LLMs couldn't output machine code directly.
Operating a Go gateway in production (single machine, ~20B tokens/month across several upstreams), usage-reporting quirks are exactly where our pain concentrated too. What survived for us:

- Treat every upstream try as an attempt with its own usage record, and let request cost be whatever the attempts sum to. Without attempt-level accounting, retries make your per-request numbers lie: you count the first attempt's tokens but pay for the retry. - Vendor-reported usage is advisory, not gospel. Some providers emit usage only on the final SSE chunk, some want stream_options, some never report it for streams at all. The parser zoo is unavoidable, but the damage is contained if the rest of the system treats usage as best-effort telemetry. - The sneaky case is disconnects, not usage: a client disconnect storm once looked identical to backend failures and put every healthy backend into cooldown until the pool was empty. Disconnects are network, not backend health - classifying them separately bought us more than any routing policy change.

How does Respan handle the retry-accounting side - do plugins see per-attempt records, or is usage aggregated at the request level after middleware runs?

How do you settle ordering when two plugins both want to rewrite the same stream?
Nice to see an open-source Rust gateway built entirely on plugins. A few areas I’d like to see clarified in the docs or repo, since “everything is a plugin” can easily become complex to manage:

- *Plugin interface/versioning*: How do you ensure compatibility across plugin updates? Is there a defined ABI with semantic versioning or just best-effort contracts? - *Capability declaration*: How do plugins specify what they support (modalities, streaming, tool-calling formats, limits)? Without this, smart routing risks falling back on ad-hoc heuristics. - *Fallback behavior and streaming*: What are the exact fallback rules? Do you buffer or stream and then switch? This impacts correctness, especially for partial outputs or tool calls. - *PII redaction approach*: Are you using structured methods (regex, entity extraction) or LLM rewriting? How do you measure false positives/negatives or avoid introducing new leakage paths? - *Observability/audit trails*: Do you log detailed metadata for each request—like routing decisions, models used, token counts, redaction actions—to enable proper audit and debugging? - *Security boundaries*: How do you prevent prompt injection or escalation through plugins or tool payloads? Is there sandboxing or permission controls? - *Evaluation and testing*: Do you provide a way to replay requests and compare outcomes (cost, latency, safety) for meaningful smart routing evaluation, beyond manual testing?

If these design considerations were documented, it would help teams adopt and contribute with more confidence.