Migration
Put Cursor or Aider behind the Gateway
Route Cursor, Aider, Continue or any OpenAI-compatible tool through the Lobstack Gateway with a local proxy, and see a cost line per request.
Migration · For developers · MIT
Move existing OpenAI or Anthropic SDK code onto the Lobstack Gateway by changing the base URL and the key, and verify it actually routed.
Use when asked to put an app behind Lobstack, consolidate providers behind one endpoint, or add per-call cost data to code that already calls a model API.
# In Lobstack: Skills › Add a skill, then paste the file or drop the folder # In Claude Code: mkdir -p .claude/skills/lobstack-gateway-migration # paste SKILL.md into .claude/skills/lobstack-gateway-migration/SKILL.md
---name: lobstack-gateway-migrationdescription: "Move existing OpenAI or Anthropic SDK code onto the Lobstack Gateway by changing the base URL and the key, and verify it actually routed. Use when asked to put an app behind Lobstack, consolidate providers behind one endpoint, or add per-call cost data to code that already calls a model API."license: MITmetadata: title: "Migrate an SDK call to the Gateway" version: 1.0.0 author: lobstack category: migration tags: [migration, openai, anthropic, sdk, gateway]--- # Migrate an SDK call to the Lobstack Gateway The Gateway is OpenAI-compatible: POST /v1/chat/completions, same requestbody, same response body, streaming included. A migration is two lines, and thenone verification step that people skip. ## The two lines ```tsimport OpenAI from "openai"; const client = new OpenAI({ apiKey: process.env.LOBSTACK_API_KEY, // lsk_live_… or lsk_test_… baseURL: "https://www.lobstack.ai/api/gateway/v1",}); // Unchanged from here down.const res = await client.chat.completions.create({ model: "auto", // or a specific Lobstack key messages: [{ role: "user", content: "hello" }],});``` ```pythonfrom openai import OpenAI client = OpenAI( api_key=os.environ["LOBSTACK_API_KEY"], base_url="https://www.lobstack.ai/api/gateway/v1",)``` ```bashcurl https://www.lobstack.ai/api/gateway/v1/chat/completions \ -H "Authorization: Bearer $LOBSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"model":"auto","messages":[{"role":"user","content":"hello"}]}'``` ## The trap that costs an afternoon Use the host with the www. The bare apex 307s to it, and[RFC 9110](https://www.rfc-editor.org/rfc/rfc9110#name-redirection-3xx) requiresevery HTTP client to drop the `Authorization` header when a redirect changeshost. curl, requests, httpx (so the OpenAI Python SDK), Go, Java and PowerShellall honour it. So an apex base URL answers a caller holding a perfectly valid key with a 401reading *missing credentials*, and the obvious conclusion to draw is that the keyis bad. It is not. The host is. ## Coming from the Anthropic SDK The Gateway exposes the OpenAI shape only. There is no /v1/messages on it, so@anthropic-ai/sdk and anthropic cannot be pointed at it by changing a baseURL. Switch the call site to the OpenAI SDK (or plain fetch) and keep askingfor the Anthropic model by its Lobstack key — the Gateway translates toAnthropic's native Messages API on the way out, including streaming. | Anthropic SDK | Gateway equivalent || --- | --- || `messages.create({ system, messages })` | one `{ role: "system" }` message at the head of `messages` || `max_tokens` (required) | `max_tokens` (optional) || `content: [{type:"text"}]` blocks | a plain string, or OpenAI content parts || `tools[].input_schema` | `tools[].function.parameters` || `stop_reason: "tool_use"` | `finish_reason: "tool_calls"` | ## What changes, and what does not Does not change: the request body, the response body, streaming, tool calling,system messages, multi-turn history, your error handling for 4xx and 5xx. Changes: - The model string. Ask GET /api/gateway/v1/models for the keys this deployment serves rather than guessing. "auto" hands model selection to the router; a specific key pins it. An unknown key is a 400, including after alias resolution.- You get a receipt. Cost, the tier, the model actually served, and the request id come back on every call. See the lobstack-receipts skill; the point of the migration is largely this.- `temperature` is only forwarded when you set it. The Gateway does not invent a sampling default, because doing so silently changes the character of the output. And it is not forwarded to models that reject it — Anthropic deprecated the sampling parameters on Opus 4.7 and everything after, and those models return a hard 400 rather than ignoring the field. When one is dropped the response says x-lobstack-dropped-params: temperature.- Other OpenAI parameters go where the provider accepts them. user, response_format, tool_choice, parallel_tool_calls, top_p, stop, seed and the two penalties are forwarded per provider; any the serving provider will not receive is named in x-lobstack-dropped-params. The matrix is on /docs/gateway/chat. n and logprobs are ignored with no header.- `stream_options.include_usage` is ignored. The final chunk carries usage and cost regardless. ## Verify it actually routed This is the step people skip, and skipping it is how a migration "succeeds"while every call still goes direct to a provider. ```bashcurl -sD /dev/stderr https://www.lobstack.ai/api/gateway/v1/chat/completions \ -H "Authorization: Bearer $LOBSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"model":"auto","messages":[{"role":"user","content":"2+2"}]}' \ -o /dev/null 2>&1 | grep -i x-lobstack``` Three things must be true: 1. x-lobstack-request-id is present. If it is not, you are not talking to the Gateway at all.2. x-lobstack-priced: true. If it is false, the model key is outside the registry and this traffic is invisible on the bill.3. x-lobstack-mode says what you expect — managed on Lobstack keys, byok on your own. Then grep the repository for the provider hostnames to find the call sites themigration missed. See the audit-unmetered-model-calls skill; on any codebasewith more than one team in it, there is always at least one. ## Rolling back Reverse the two lines. Nothing else changed, no data was migrated, and noprovider-side state exists on the Lobstack side to unwind. Treat that as thereason to migrate incrementally: one service, verified, then the next.
Migration
Route Cursor, Aider, Continue or any OpenAI-compatible tool through the Lobstack Gateway with a local proxy, and see a cost line per request.
Cost
Read the receipt Lobstack returns on every model call — cost_usd, savings_usd, baseline_reason — and report cost from it instead of estimating.
Cost
Choose the cheapest model tier that can actually do the task instead of defaulting to a flagship, and verify the choice before spending on it.
Cost
Hold an agent, job or run inside a hard dollar budget using the per-call cost the Gateway returns, and handle the 402 when an allowance runs out.
Cost
Write or review a system prompt that does not quietly multiply the bill — bounded output, no re-sent bulk, tool schemas counted as the input tokens they are.