Get Orchid
Back to Blog

Migrating from Helicone to Orchid. A Complete Guide

Mario Guerra8 min read
Migrating from Helicone to Orchid. A Complete Guide

Helicone earned its user base honestly. It proved that a proxy is the simplest way to get LLM observability, often with nothing more than a one line base URL change. If you built on it, you made a reasonable bet.

Then 2026 happened. Helicone was acquired by Mintlify in March, and their own docs now label the classic proxy integrations as maintained but no longer actively developed. Bug fixes and new model support continue, but the roadmap has narrowed. If your team depends on request logging and cost visibility, that's a hard place to build a future on.

Here's the good news. The proxy pattern you already use is exactly how Orchid works. Your application code barely changes. You keep everything you liked about the proxy approach, your data moves from someone else's cloud to your own disk, and you gain a capability Helicone never had. Let's walk through it.

What You're Moving To

Orchid is a local-first recording proxy for LLM traffic. It ships as a single Rust binary in a Docker container with a SQLite database. There is no ClickHouse, no Kafka, no cloud account, and no ingestion meter. Your prompts and responses are recorded on your own infrastructure and never leave it.

The mental model transfers directly from Helicone.

  • Your app points at the proxy instead of the provider.
  • The proxy forwards the request, records the exchange, and returns the response.
  • A dashboard, an API, and cost tracking sit on top of the recordings.

If you want the deeper architectural picture, Record, Inspect, Replay covers it. For this guide, we'll stay focused on the move itself.

Step 1. Run the Proxy

Two commands. First generate an API key, then start the container.

docker run --rm ghcr.io/mario-guerra/orchid-proxy:latest generate-api-key

docker run -d \
  --name orchid-proxy \
  -p 4320:4320 \
  -p 4321:4321 \
  -v orchid-data:/data \
  -e ORCHID_API_KEY=your-generated-key \
  -e ORCHID_DB_PATH=/data/orchid.db \
  ghcr.io/mario-guerra/orchid-proxy:latest

Port 4320 is the proxy your app talks to. Port 4321 serves the embedded visualizer dashboard and the query API. That's the whole deployment. When you ran Helicone self-hosted, you managed a considerably larger stack for the same job.

Step 2. Translate Your Headers

This is the heart of the migration. Every Helicone concept you use daily has a direct Orchid equivalent.

What it does Helicone Orchid
Base URL https://oai.helicone.ai/v1 http://localhost:4320/v1
Authenticate to the proxy Helicone-Auth: Bearer sk-helicone-... X-Orchid-Api-Key: your-key
Group related calls Helicone-Session-Id + Helicone-Session-Path + Helicone-Session-Name, all three required X-Orchid-Session-Id, just the one
Route to a non-default target Gateway target URL header X-Orchid-Target-Url
Provider API key Authorization header, forwarded Authorization header, forwarded untouched, never stored

A few things deserve a callout.

First, your provider API key handling doesn't change at all. Just like Helicone's classic proxy, Orchid forwards your Authorization header to the upstream provider as is. No re-keying, no secrets migration. If you're on Helicone's newer AI Gateway instead, where your Helicone key doubles as the client API key, the move is the same base URL swap. You put your provider key back in Authorization and your Orchid key in X-Orchid-Api-Key.

Second, session grouping gets simpler. Helicone requires three session headers on every request. Orchid needs one.

Third, notice there's one Orchid header with no Helicone equivalent in that table. We'll get to X-Orchid-Mode in a moment, because it's the reason this migration gives you something back instead of just parity.

Step 3. Update Your Code

Here's what the change looks like in practice. The before and after are deliberately boring.

Python

# Before, with Helicone
client = OpenAI(
    base_url="https://oai.helicone.ai/v1",
    default_headers={
        "Helicone-Auth": f"Bearer {HELICONE_API_KEY}",
        "Helicone-Session-Id": session_id,
        "Helicone-Session-Path": "/checkout",
        "Helicone-Session-Name": "Checkout Flow",
    },
)

# After, with Orchid
client = OpenAI(
    base_url="http://localhost:4320/v1",
    default_headers={
        "X-Orchid-Api-Key": ORCHID_API_KEY,
        "X-Orchid-Session-Id": "checkout-flow",
        "X-Orchid-Mode": "capture",
    },
)

TypeScript

// Before, with Helicone
const client = new OpenAI({
  baseURL: "https://oai.helicone.ai/v1",
  defaultHeaders: {
    "Helicone-Auth": `Bearer ${process.env.HELICONE_API_KEY}`,
    "Helicone-Session-Id": sessionId,
    "Helicone-Session-Path": "/checkout",
    "Helicone-Session-Name": "Checkout Flow",
  },
});

// After, with Orchid
const client = new OpenAI({
  baseURL: "http://localhost:4320/v1",
  defaultHeaders: {
    "X-Orchid-Api-Key": process.env.ORCHID_API_KEY,
    "X-Orchid-Session-Id": "checkout-flow",
    "X-Orchid-Mode": "capture",
  },
});

Anything Else

Orchid is entirely header-driven, so any language with an HTTP client gets the same first-class integration. Go, Java, Ruby, Elixir, shell scripts, all of it. The patterns are covered in No SDK Required.

If you'd rather not manage headers by hand, the Python and TypeScript SDKs patch your HTTP layer at init time and handle routing automatically. They also fail soft. If the proxy is down, your requests go straight to the provider and your app keeps working.

Step 4. Verify the Capture

Send one request through the proxy, then open the visualizer at http://localhost:4321. You should see your session, the full request and response payloads, token counts, and a computed USD cost for the exchange.

That last part matters if cost tracking was your main reason for using Helicone. Orchid computes real dollar costs at capture time using a pricing schema you control and can update without a restart. If a rate changes or you add a custom model, you push new pricing and can recompute costs for exchanges you've already recorded. Your history is never permanently wrong. The details are in Know What Every Agent Run Costs.

What You Gain That Helicone Never Had

Remember X-Orchid-Mode? Set it to capture and Orchid records your traffic. Set it to replay and something happens that has no Helicone equivalent at all.

client = OpenAI(
    base_url="http://localhost:4320/v1",
    default_headers={
        "X-Orchid-Api-Key": ORCHID_API_KEY,
        "X-Orchid-Session-Id": "checkout-flow",
        "X-Orchid-Mode": "replay",
    },
)

In replay mode, the proxy matches each request against your recorded session and serves the stored response. No network call, no API cost, no non-determinism. Record a session once, then run your entire test suite against it forever, offline, for free. Flip one header or one environment variable and your CI stops burning tokens.

This is the difference between a logging proxy and a recording proxy. Helicone showed you what your agent did. Orchid lets you re-run it. For teams testing agent logic, this alone tends to justify the migration. Zero-Cost AI Testing walks through the full workflow.

You also gain an MCP server built into the proxy. Point Claude Code, Cursor, or any MCP client at it and your AI assistant can search your sessions, inspect failures, profile latency and cost, and debug your agent using its own recorded traffic. We wrote about that pattern in Let Your AI Debug Your AI.

What Doesn't Map

An honest migration guide tells you what you're giving up, so here it is.

  • Custom properties. Helicone's Helicone-Property-* headers for arbitrary request tagging have no direct Orchid equivalent today. Sessions are the primary grouping mechanism.
  • Session path hierarchies. Helicone's Helicone-Session-Path builds parent and child trace trees. Orchid groups exchanges by session and pipeline step, but does not reproduce arbitrary path nesting.
  • Response caching. Helicone can serve cached responses to save costs in production. Orchid's replay mode covers the testing use case, but it is not a production cache.
  • Prompt experiments and hosted evals. These were Helicone cloud features. Orchid is a recording and replay tool, not an eval platform.
  • The multi-provider gateway. Helicone's AI Gateway routes one OpenAI-style API to 100+ models. Orchid records whatever provider you call, but it does not translate between provider APIs.

If any of those are load-bearing for your team, factor that into your timeline. For most teams we've talked to, the daily drivers are request logging, session grouping, and cost visibility, and all three move over cleanly.

Your Data Stays Home Now

One more difference worth sitting with. On Helicone's hosted platform, your prompts, your responses, and your agent's behavior lived on their servers. That was the trade for convenience, and after the acquisition, the long-term stewardship of that data is a question you no longer control.

With Orchid there is nothing to trust because there is nothing to send. Recordings live in a SQLite file on your own disk, with retention rules you configure. Delete the volume and the data is gone. We covered why this matters in Local-First Observability.

The Whole Migration, Summarized

  1. Start the Orchid container. Two commands.
  2. Change your base URL to http://localhost:4320/v1.
  3. Swap Helicone-Auth for X-Orchid-Api-Key, and the three session headers for a single X-Orchid-Session-Id.
  4. Add X-Orchid-Mode: capture.
  5. Send a request and check the visualizer on port 4321.

For most codebases that's a small pull request, reviewed and merged in an afternoon. Your observability keeps working, your data comes home, and your test suite gets a replay button.

Ready to try it? Pull the container, point one service at it, and see your first recorded session in the next ten minutes. If you hit a rough edge during your migration, reach out. We'd genuinely like to hear what Helicone did well that you want Orchid to do better.