AI Relay Gateway (oridecon-ai-relay-gateway)
Protocol-facing relay gateway for the Oridecon AI relay — channel selection, orchestration, upstream I/O, and SSE handling
Overview
Section titled “Overview”Protocol-facing relay gateway for the Oridecon AI relay. Composes the gateway service from a channel registry, payload codec, upstream HTTP adapter, and the conversion engine, and exposes it behind RelayGatewayProtocol through RelayGatewayModule / RelayGatewayProvider.
One request is orchestrated end to end: authorization, channel selection, billing admission, request conversion, the protected upstream call, response conversion, billing settlement, and result metadata assembly. Streaming requests run the same preflight and then consume the upstream SSE stream lazily.
Full documentation: docs.oridecon.dev
Install
Section titled “Install”uv add oridecon-ai-relay-gatewayQuick Start
Section titled “Quick Start”from oridecon import Applicationfrom oridecon.di.module import Module, module
from oridecon.ai.relay.gateway import RelayGatewayConfig, RelayGatewayModule
@module( imports=[ RelayGatewayModule.configure( RelayGatewayConfig.from_mapping( { "channels": [ { "name": "primary", "upstream_base_url": "https://api.anthropic.com", "target_format": "CLAUDE", "models": ["claude-3-5-sonnet"], } ], } ) ) ])class AppModule(Module): pass
async with Application.boot(modules=[AppModule]) as app: # use app.container to resolve services ...The gateway registers its inbound routes automatically through the oridecon.web.contributors entry point; bind it through a web-enabled Application to serve /v1/chat/completions, /v1/responses, /v1/messages, and the Gemini /v1beta surface.
Configuration
Section titled “Configuration”Explicit-only configuration: the gateway is not bound to a
OrideconConfigsection — it declares noconfig_key/config_modeland reads no environment variables. Configuration is supplied toRelayGatewayModule.configure()as aRelayGatewayConfig.
Option 1 — Python
Section titled “Option 1 — Python”from oridecon.ai.relay.gateway import RelayGatewayConfig
config = RelayGatewayConfig.from_mapping( { "channels": [...], "auto_test_channels": True, "auto_test_interval_seconds": 300, "require_auth": True, })When a host binds a RelayChannelStoreProtocol, the DurableChannelLoader reconciles every durable row over the static table by name at boot; an empty store leaves the static table untouched.
Config reference
Section titled “Config reference”| Field | Default | Description |
|---|---|---|
channels | () | Ordered channel table (name, upstream URL, target format, models) |
model_suffix | {} | Channel-name to outbound model-suffix map (e.g. ":thinking") |
provider_options | {} | Channel-name to provider options merged at conversion time |
auto_test_channels | False | Background sweep probing channels, disabling failures |
auto_test_interval_seconds | 600 | Delay between auto-test sweeps |
max_upstream_retries | 0 | Retries across other channels after a retryable upstream failure |
load_balancing | "deterministic" | "deterministic" or "weighted" channel tie-breaking |
job_ttl_seconds | 3600 | Eviction age for job-relay records on next poll |
require_auth | True | Require a bound RelayAuthVerifierProtocol on relay routes; when no config is registered (or no container is available) the guard fails closed with 503 AUTH_REQUIRED_BUT_UNBOUND rather than passing through |
rate_limits | {} | Per-model {"max", "window_seconds"} budgets |
auto_disable_on_failures | False | Take a channel out of service on consecutive failures |
failover_failure_threshold | 3 | Consecutive failures that disable a channel |
Module Factory Methods
Section titled “Module Factory Methods”| Method | Description |
|---|---|
RelayGatewayModule.configure(config=None) | Gateway with the built-in relay routes; empty config = no channels |
Key Features
Section titled “Key Features”- Inbound relay routes: OpenAI Chat (
/v1/chat/completions), OpenAI Responses (/v1/responses), Anthropic (/v1/messages), Gemini (/v1beta/models/{model}:generateContent) plus model list/detail surfaces - Channel selection: deterministic priority + weight resolution over a runtime override table, with weighted load balancing
- Full request lifecycle: auth, channel selection, billing admission, conversion, upstream call, settlement, metadata
- SSE streaming: lazy upstream stream consumption through a stream session; billing settles exactly once
- Credential injection: per-channel credential providers behind an injecting HTTP client
- Passthrough routes:
/v1/embeddings,/v1/rerank,/v1/moderations,/v1/audio/*,/v1/images/* - Job relay: submit-then-poll routes (
POST /v1/videos,GET /v1/videos/{job_id}) with eviction TTL - Operations: channel health probing, background auto-tester, route metrics, operator controls, failover tracking
- Governance: per-model rate limiting and an optional auth guard on inbound routes
- Durable channels: store-backed channel reconciliation at boot via
DurableChannelLoader - Admin surface: channel CRUD pages and actions for the admin UI
Testing
Section titled “Testing”async with Application.boot(modules=[RelayGatewayModule.configure()]) as app: # your test code ...Key Source Files
Section titled “Key Source Files”| File | What it contains |
|---|---|
src/oridecon/ai/relay/gateway/module.py | RelayGatewayModule.configure() |
src/oridecon/ai/relay/gateway/config.py | RelayGatewayConfig and channel-table validation |
src/oridecon/ai/relay/gateway/channels.py | RelayChannelRegistry — deterministic channel selection |
src/oridecon/ai/relay/gateway/service.py | RelayGatewayService — request lifecycle orchestration |
src/oridecon/ai/relay/gateway/upstream.py | HTTPUpstreamAdapter and upstream I/O |
src/oridecon/ai/relay/gateway/codec.py | RelayPayloadCodec — payload encode/decode |
src/oridecon/ai/relay/gateway/stream.py | relay_stream and UpstreamEventParser for SSE |
src/oridecon/ai/relay/gateway/loader.py | DurableChannelLoader — store reconciliation at boot |
src/oridecon/ai/relay/gateway/operations/ | Health, metrics, controls, auto-test, failover, stream registry |
src/oridecon/ai/relay/gateway/web/ | Relay routes, SSE, audio and image endpoints |
src/oridecon/ai/relay/gateway/ratelimit.py | Per-model rate-limit guard (Redis-backed variant alongside) |
src/oridecon/ai/relay/gateway/admin/ | Admin pages and actions for channel CRUD |