llm-gateway/docs/subscription-bridges.md
2026-07-17 22:10:34 +02:00

5.4 KiB

Subscription Bridges

Subscription bridges let the gateway route requests to user-owned AI subscription tools through a local HTTP interface.

The bridge pattern is:

gateway
  -> local bridge
  -> installed CLI or local adapter
  -> subscription-backed response

The gateway does not need direct access to the subscription account material. The CLI or adapter keeps its own authentication state.

Why Bridges Exist

Many subscription tools are designed for interactive use, not direct API access. A bridge gives the gateway a small, testable HTTP surface around those tools:

  • GET /health
  • POST /api/generate
  • POST /v1/chat/completions

This makes subscription tools easier to test, monitor, and route alongside other providers.

Discovery

Discovery checks:

  • CLI binary availability
  • version probe result
  • authentication status when a safe probe exists
  • default bridge health
  • configured bridge URL

Run discovery:

curl -X POST http://localhost:3100/api/subscriptions/scan \
  -H "Authorization: Bearer <key>"

List subscriptions:

curl http://localhost:3100/api/subscriptions \
  -H "Authorization: Bearer <key>"

Search:

curl "http://localhost:3100/api/subscriptions?search=claude" \
  -H "Authorization: Bearer <key>"

Join

Join records that the operator wants to use a subscription.

curl -X POST http://localhost:3100/api/subscriptions/join \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <key>" \
  -d '{ "subscription_id": "chatgpt", "auto_spawn": true }'

Joining does not expose OAuth state or account credentials. The subscription summary returned by the list endpoint contains the generated access card, including the direct gateway API URL for that subscription.

Spawn

Spawn one bridge:

curl -X POST http://localhost:3100/api/subscriptions/bridges \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <key>" \
  -d '{ "subscription_id": "chatgpt" }'

Spawn all eligible bridges:

curl -X POST http://localhost:3100/api/subscriptions/bridges \
  -H "Authorization: Bearer <key>"

Test

curl -X POST http://localhost:3100/api/subscriptions/test \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <key>" \
  -d '{
    "subscription_id": "chatgpt",
    "message": "Reply with a bridge smoke test."
  }'

The test response should include:

  • subscription ID
  • model
  • bridge URL
  • HTTP status
  • latency
  • response snippet

Call A Joined Subscription

Every joined subscription can be called through its own OpenAI-compatible gateway URL:

curl -X POST http://localhost:3100/api/subscriptions/chatgpt/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <key>" \
  -d '{
    "model": "gpt-4-turbo",
    "messages": [
      { "role": "user", "content": "Reply through the ChatGPT subscription bridge." }
    ]
  }'

The unified endpoint can also target a specific subscription:

curl -X POST http://localhost:3100/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <key>" \
  -H "X-LLM-Gateway-Subscription: chatgpt" \
  -d '{
    "model": "gpt-4-turbo",
    "messages": [
      { "role": "user", "content": "Reply through the ChatGPT subscription bridge." }
    ]
  }'

For ambiguous model IDs, prefer the direct subscription URL or the X-LLM-Gateway-Subscription header. This keeps routing explicit when several subscription tools expose similar model names.

Chat messages are compressed before bridge dispatch when compression can reduce the request. Responses include gateway compression metadata where available.

Access Card

Each subscription summary includes an access card with:

  • gateway base URL
  • chat completions URL
  • per-subscription chat completions URL
  • model list
  • default model
  • required headers
  • X-LLM-Gateway-Subscription header value
  • bridge URL
  • bridge env var
  • curl example

Use the gateway endpoint from the access card in client applications, not the subscription credentials.

Adding A Bridge Implementation

Add or update:

  • packages/gateway/src/modules/subscription-discovery.ts
  • packages/gateway/src/modules/bridge-spawner.ts
  • packages/gateway/src/routes/subscriptions.ts
  • packages/gateway/src/pipeline/external-providers.ts

Minimum checklist:

  1. Add a catalog entry.
  2. Add a version probe.
  3. Add an auth probe if the CLI supports one safely.
  4. Pick a localhost bridge port.
  5. Add one or more model IDs.
  6. Implement the CLI invocation.
  7. Return OpenAI-compatible chat output where possible.
  8. Add health behavior.
  9. Add tests or a documented smoke test.

Security Rules

  • Bind local bridges to localhost.
  • Do not print OAuth artifacts.
  • Do not return subscription account data in API responses.
  • Avoid logging full prompts by default.
  • Treat bridge errors as operational state, not as successful routing.
  • Prefer explicit join before auto-spawn in shared environments.

Troubleshooting

Installed But Not Authenticated

Log in through the CLI directly, then run scan again.

Bridge Port Already In Use

Check whether a previous bridge process is still running or configure a different bridge URL.

Unified Chat Returns Provider Missing

Check whether the selected model ID belongs to a discovered, joined, and running subscription.

CLI Works But Bridge Fails

Run the gateway with a verbose log level and test the bridge endpoint directly.