Hasna Gateway is the open-source AI gateway core for Hasna apps and self-hosted teams. It exposes one stable OpenAI-compatible API while routing requests across providers, including OpenAI, Google Gemini, OpenRouter, Vercel AI Gateway, LiteLLM Proxy, Portkey, Cloudflare AI Gateway, Helicone AI Gateway, Kong AI Gateway, DeepSeek, Qwen/DashScope, Kimi/Moonshot, Z.AI/GLM, and SiliconFlow.
The open-source package is useful on its own. Anyone can run it locally or on their own server, bring their own provider keys, define routing policy, and point applications at one endpoint. The hosted Hasna gateway can build on the same core while keeping accounts, billing, pooled provider contracts, discounts, tenant policy, and hosted observability private.
- OpenAI-compatible chat completions and embeddings APIs.
- One gateway key for clients, many provider keys behind the gateway.
- Bring-your-own-key mode for self-hosted users.
- Routing by model alias, provider allowlist/blocklist, region policy, price ceilings, fallback, capability, and smart cost/quality/latency hints.
- Explicit China/provider policy so requests are never silently routed to a region or provider class the caller did not allow.
- Usage normalization, estimated cost hooks, route decision metadata, and optional local JSONL usage ledger.
- Hard or soft budgets by gateway key, tenant, and model alias across USD plus input/output/total tokens.
- Local-first defaults: no hosted Hasna calls unless explicitly configured.
Install the published CLI when you want to run the gateway without a source checkout:
bun install -g @hasna/gateway
gateway --helpFor source development:
bun install
cp .env.example .env
cp gateway.config.example.json gateway.config.jsonSet GATEWAY_API_KEY and at least one provider key in your environment, then run:
bun run build
bun dist/cli/index.js serve --config gateway.config.jsonCall the gateway with any OpenAI-compatible client or curl:
curl http://127.0.0.1:8787/v1/chat/completions \
-H "authorization: Bearer $GATEWAY_API_KEY" \
-H "content-type: application/json" \
-d '{"model":"fast","messages":[{"role":"user","content":"Say hello."}]}'bun run typecheck
bun test
bun run build
bun dist/cli/index.js validate --config gateway.config.example.json
bun dist/cli/index.js validate --config gateway.config.production-cloud.example.json
bun dist/cli/index.js smoke --config gateway.config.example.json --model fast
bun dist/cli/index.js smoke --config gateway.config.example.json --all
bun dist/cli/index.js budget-add --config gateway.config.json --id team-daily --window daily --tenant acme --model fast --max-usd 5 --max-total-tokens 100000
bun dist/cli/index.js budget-remaining --config gateway.config.json --id team-daily --jsonAfter installation as a package, the CLI binary is gateway:
gateway serve --config gateway.config.json
gateway-serve --config gateway.config.json
gateway-mcp --config gateway.config.jsongateway-serve is the package-level service binary for local and self-hosted
HTTP runtime smoke checks. It exposes public GET /health and GET /version,
plus GET /ready, GET /v1/models, POST /v1/chat/completions, and
POST /v1/embeddings. The latter endpoints enforce gateway auth when required.
gateway-mcp is a stdio MCP server for local agents. It validates and inspects config, explains route choices without provider calls, manages budget definitions, checks remaining budgets, and summarizes the configured usage ledger. Long-running serve and live smoke checks stay CLI-only. See Gateway MCP server.
Required config examples:
gateway.config.example.json: mixed provider routes with explicit China-allowed aliases.gateway.config.production-cloud.example.json: production cloud runtime with non-loopback binding, fail-closed health, gateway auth, HTTPS provider endpoints, and explicit provider endpoint allowlist.gateway.config.no-china.example.json: OpenAI/OpenRouter-only policy withcnblocked.gateway.config.china.example.json: Chinese provider routes with explicitcn/sgallowance.
Built-in provider credentials are loaded from environment variables. Custom static headers can contain arbitrary values, but provider secrets should not be stored in config files.
Providers can use baseUrl, baseUrlEnv, apiKeyEnv, custom auth, and static or env-derived headers. This keeps OpenAI-compatible gateways on the generic adapter instead of adding hardcoded adapter forks. The built-in presets include:
- Direct/provider presets:
openai,openrouter,deepseek,qwen,kimi,zai,siliconflow. - Gateway presets:
vercel-ai-gateway,litellm-proxy,portkey,cloudflare-ai-gateway,helicone-ai-gateway,kong-ai-gateway.
Smart routing is available with route mode smart or request gateway.routing: "smart". It filters by policy first, then scores eligible candidates using configured prices, context, capabilities, quality/latency/success/throughput hints, and deterministic fallback ordering when metrics are missing.
Optional non-streaming chat response caching is configured under server.responseCache. Cache entries are in-memory and process-local, only successful responses are cached, and clients can bypass lookup with the configured bypassHeader. Streaming and embeddings requests are never cached. A cache hit still runs the budget preflight check and still consumes the per-gateway-key request rate limit, but it does not append a usage ledger record and does not consume budget or token rate limit quota.
{
"model": "coding",
"messages": [{ "role": "user", "content": "Refactor this function." }],
"gateway": {
"routing": "smart",
"priority": "quality",
"cost_quality_tradeoff": 3,
"required_capabilities": ["tools", "json"],
"min_context_tokens": 128000,
"sticky_session_id": "thread-123"
}
}Budgets live in the same JSON config and spend is calculated from the usage ledger. JSONL append through storage.usageLedgerPath is the local-first default. Daily, monthly, and lifetime budgets require either storage.usageLedgerPath or an explicit storage.cloud backend; per-request budgets can run without cumulative storage. Use mode: "hard" to block exhausted budgets with an OpenAI-compatible 402 error, or mode: "soft" to keep serving while exposing warnings in gateway metadata and ledger records.
The default runtime mode is local. It preserves local-first behavior: the server binds to 127.0.0.1, provider discovery is driven by the local JSON config, and /health stays a lightweight liveness check that does not require secrets.
Set runtime.mode to production-cloud when running the gateway behind a cloud load balancer, API gateway, or Hasna-hosted wrapper. Production cloud mode makes the cloud path explicit and fail-closed:
auth.requiredmust betrue.server.hostmust not be a loopback host; use0.0.0.0for container ingress.runtime.health.requireRuntimeSecretsmust betrue, so/healthreturns503until the gateway key is present and every configured route has an eligible provider with its key present.- enabled providers must declare
apiKeyEnv. - enabled provider
baseUrlvalues must be HTTPS and must not be local/private endpoints unless an explicit local endpoint allowlist is configured. This is a static URL check; DNS and network egress controls remain operator responsibilities. runtime.serviceDiscovery.allowedProviderBaseUrlscan restrict enabled providers to exact provider URL origins.
Production cloud mode does not create DNS, ACM, API Gateway, secrets, provider keys, or cloud infrastructure. Those deployment steps require an operator-owned deployment workflow outside this package.
The companion open-router repo is currently documented as the future extraction point for prompt-aware routing and eval harnesses. The deterministic routing implementation lives in this package today because it is tightly coupled to gateway policy, provider config, budgets, attempts, and ledger metadata.
- CLI reference
- Configuration reference
- Product requirements
- Architecture
- API contract
- Provider adapters
- 2026 provider references
- Routing and policy
- Gateway MCP server
- Open-core boundary
- Security and compliance
- Implementation plan
- Publishing and release
- Hasna app migration plan
- Agent handoff prompt
The gateway core is implemented and locally verified for the current release surface: CLI and standalone HTTP servers, MCP server, health/readiness/version/models/chat/embeddings endpoints, OpenAI-compatible and Anthropic adapters, provider presets, routing policy, fallbacks, streaming, response caching, rate limits, budgets, usage normalization, local and cloud ledgers, examples, tests, build, and package dry-run.
Publication is gated on a passing live smoke check with valid provider credentials.