Catalog PyPI
PACKAGE EXPLORERView in registry

9router-python

PyPI

Python SDK + CLI for the 9Router AI gateway (OpenAI-compatible chat, images, TTS, STT, embeddings, web search/fetch)

9routeraiembeddingsgatewayllmopenaistttts
Versions collected1
Direct dependencies5From release 0.1.0
Last observed20 Oct, 16:14 UTC

README

Version 0.1.0 documentation

PyPI Python versions License Downloads

9router-python demo

9router-python

Python SDK + CLI for the 9Router AI gateway.

One tiny library to talk to an OpenAI-compatible gateway that routes to Gemini, NVIDIA, OpenRouter, Groq, Ollama, Tavily and Exa — chat, images, TTS, STT, embeddings and web search/fetch — all through a single local endpoint, with automatic fallback between providers.

$ pip install 9router-python

✨ Features

CapabilitySDK methodCLI command
💬 Chat (with streaming)client.chat() / chat_stream()ninerouter chat
🌀 Embeddingsclient.embeddings()ninerouter embed
🖼️ Image generationclient.image()ninerouter image
🔊 Text-to-speechclient.tts()ninerouter tts
🎙️ Speech-to-textclient.stt()ninerouter stt
🔎 Web searchclient.web_search()ninerouter web search
📄 Fetch URL → markdownclient.web_fetch()ninerouter web fetch
⚙️ Models & healthclient.models(), health()ninerouter models, health

Everything runs through one base URL. Configure once, use everywhere.


⚡ Quickstart

🚀 30 seconds to first chat

$ pip install 9router-python
$ ninerouter chat "Hello, world!" --stream
Hello! 👋 How can I help you today?

That's it. One gateway, one SDK, every capability.

Chat

from ninerouter import NineRouter

with NineRouter() as client:
    reply = client.chat("Explain a monad in one sentence")
    print(reply.text)

Stream tokens as they arrive:

for chunk in client.chat_stream("Write a haiku about Python"):
    print(chunk.content, end="", flush=True)

Generate an image

image = client.image("a watercolor of mountains at sunrise")
open("out.png", "wb").write(image.content)

Text-to-speech

audio = client.tts("Olá, mundo!", voice="pt-BR-FernandaNeural", model="gemini/gemini-3.1-flash-tts-preview")
open("speech.wav", "wb").write(audio)

Speech-to-text

text = client.stt(file=("recording.wav", open("recording.wav", "rb").read()))
print(text.text)

Embeddings — RAG-ready

vector = client.embeddings("The quick brown fox")[0]
curl_similarity = sum(a * b for a, b in zip(vector, other))

Web search & fetch

results = client.web_search("9Router open source")
for r in results.results:
    print(r.title, "-", r.url)

page = client.web_fetch("https://example.com")
print(page.content.text)

🖥️ CLI

ninerouter                          # help
ninerouter health                   # gateway status
ninerouter models --kind chat       # list chat models
ninerouter chat "Hello" --stream    # chat with streaming
ninerouter embed "text"             # embedding vector
ninerouter image "a red fox" --out fox.png
ninerouter tts "Hello" --voice pt-BR-FernandaNeural
ninerouter stt recording.wav
ninerouter web search "9Router"
ninerouter web fetch https://example.com
ninerouter config                   # show effective config

🔧 Configuration

Resolution order: CLI flags > environment variables > defaults.

SettingEnv varDefault
Base URLNINEROUTER_URLhttp://localhost:20128
API keyNINEROUTER_KEY(optional)
export NINEROUTER_URL="http://localhost:20128"
export NINEROUTER_KEY="sk-..."     # optional if gateway has auth disabled

The key is only sent when non-empty, so a gateway running with requireApiKey=false works out of the box.


⚠️ Gateway quirks handled for you

  • SSE-by-default: the gateway often streams SSE even when stream isn't set — the client parses both JSON and SSE transparently.
  • TTS: some OpenRouter TTS models return 502 upstream errors; prefer a gemini/* TTS model.
  • STT: multipart upload with gemini/* or groq/whisper-* models.
  • Web search/fetch use provider (not model), e.g. tavily, exa, or the search-combo.
  • Combos (owned_by: "combo", like Code) auto-fallback across providers — great defaults for chat.

📦 Install & develop

pip install -e .[dev]
pytest                     # mocked unit tests
pytest -m live             # live tests (needs a running gateway)

Requires Python 3.9+.


🧰 Why 9Router?

9Router gives you keyless access to dozens of AI providers with automatic fallback, so your app keeps working even if one provider's quota or free tier runs out. This SDK removes the friction: you get a typed, tested Python client and a friendly CLI without caring about which endpoint each provider uses.


🔒 Privacy & Security

This SDK is a thin HTTP client — it does not hold AI provider keys, does not upload your prompts anywhere other than the gateway you point it at, and ships no telemetry.

  • No secrets in the client. An optional API key is read from the environment (NINEROUTER_KEY) and sent only to your configured gateway.
  • Nothing leaves your network except to the gateway you configure. The SDK never sends data to the SDK author or any third party.
  • The gateway holds the keys. Provider API keys (Gemini, NVIDIA, Tavily, …) live in your 9Router gateway on your machine/VM — not in this library.
  • Supply-chain hygiene. Only two runtime dependencies (httpx, typer), both widely trusted. CI runs unit tests on every push across Python 3.9/3.11/3.13.
  • No-secrets guardrail. A test in CI scans the repo for committed credentials and fails the build if anything slips in.

See SECURITY.md for the full policy and how to report a vulnerability privately.


📄 License

MIT © (ChristopherDond)


🇧🇷 Português

SDK Python + CLI para o gateway de IA 9Router.

Um único pacote para conversar com um gateway compatível com a API da OpenAI que roteia Gemini, NVIDIA, OpenRouter, Groq, Ollama, Tavily e Exa — chat, imagens, TTS, STT, embeddings e busca web, com fallback automático entre provedores.

pip install 9router-python
ninerouter chat "Olá, mundo!" --stream

Consulte a seção Features e Quickstart acima — a API e o CLI são idênticos. Para configurar, veja Configuration.

Exemplo rápido (PT)

from ninerouter import NineRouter

with NineRouter() as client:
    print(client.chat("Me conta uma piada"))

⬆ back to top

Downloads & popularity

4downloads
1-day window · source-reported counts18 Oct 2026
12361.50
2026-08-04: 123 · observed 2026-10-20T20:41:42.5604690Z · period 2026-08-04–2026-08-042026-08-05: 2 · observed 2026-10-20T20:41:42.5604690Z · period 2026-08-05–2026-08-052026-08-06: 4 · observed 2026-10-20T20:41:42.5604690Z · period 2026-08-06–2026-08-062026-08-07: 5 · observed 2026-10-20T20:41:42.5604690Z · period 2026-08-07–2026-08-072026-08-08: 1 · observed 2026-10-20T20:41:42.5604690Z · period 2026-08-08–2026-08-082026-08-09: 6 · observed 2026-10-20T20:41:42.5604690Z · period 2026-08-09–2026-08-092026-08-10: 3 · observed 2026-10-20T20:41:42.5604690Z · period 2026-08-10–2026-08-102026-08-11: 3 · observed 2026-10-20T20:41:42.5604690Z · period 2026-08-11–2026-08-112026-08-12: 1 · observed 2026-10-20T20:41:42.5604690Z · period 2026-08-12–2026-08-122026-08-13: 4 · observed 2026-10-20T20:41:42.5604690Z · period 2026-08-13–2026-08-132026-08-14: 5 · observed 2026-10-20T20:41:42.5604690Z · period 2026-08-14–2026-08-142026-08-16: 3 · observed 2026-10-20T20:41:42.5604690Z · period 2026-08-16–2026-08-162026-08-17: 5 · observed 2026-10-20T20:41:42.5604690Z · period 2026-08-17–2026-08-172026-08-18: 23 · observed 2026-10-20T20:41:42.5604690Z · period 2026-08-18–2026-08-182026-08-19: 2 · observed 2026-10-20T20:41:42.5604690Z · period 2026-08-19–2026-08-192026-08-20: 2 · observed 2026-10-20T20:41:42.5604690Z · period 2026-08-20–2026-08-202026-08-21: 2 · observed 2026-10-20T20:41:42.5604690Z · period 2026-08-21–2026-08-212026-08-22: 1 · observed 2026-10-20T20:41:42.5604690Z · period 2026-08-22–2026-08-222026-08-23: 6 · observed 2026-10-20T20:41:42.5604690Z · period 2026-08-23–2026-08-232026-08-24: 14 · observed 2026-10-20T20:41:42.5604690Z · period 2026-08-24–2026-08-242026-08-27: 3 · observed 2026-10-20T20:41:42.5604690Z · period 2026-08-27–2026-08-272026-08-28: 7 · observed 2026-10-20T20:41:42.5604690Z · period 2026-08-28–2026-08-282026-08-29: 1 · observed 2026-10-20T20:41:42.5604690Z · period 2026-08-29–2026-08-292026-08-31: 5 · observed 2026-10-20T20:41:42.5604690Z · period 2026-08-31–2026-08-312026-09-01: 1 · observed 2026-10-20T20:41:42.5604690Z · period 2026-09-01–2026-09-012026-09-02: 1 · observed 2026-10-20T20:41:42.5604690Z · period 2026-09-02–2026-09-022026-09-03: 1 · observed 2026-10-20T20:41:42.5604690Z · period 2026-09-03–2026-09-032026-09-04: 2 · observed 2026-10-20T20:41:42.5604690Z · period 2026-09-04–2026-09-042026-09-05: 1 · observed 2026-10-20T20:41:42.5604690Z · period 2026-09-05–2026-09-052026-09-06: 2 · observed 2026-10-20T20:41:42.5604690Z · period 2026-09-06–2026-09-062026-09-07: 4 · observed 2026-10-20T20:41:42.5604690Z · period 2026-09-07–2026-09-072026-09-09: 3 · observed 2026-10-20T20:41:42.5604690Z · period 2026-09-09–2026-09-092026-09-10: 1 · observed 2026-10-20T20:41:42.5604690Z · period 2026-09-10–2026-09-102026-09-12: 4 · observed 2026-10-20T20:41:42.5604690Z · period 2026-09-12–2026-09-122026-09-14: 1 · observed 2026-10-20T20:41:42.5604690Z · period 2026-09-14–2026-09-142026-09-16: 3 · observed 2026-10-20T20:41:42.5604690Z · period 2026-09-16–2026-09-162026-09-17: 1 · observed 2026-10-20T20:41:42.5604690Z · period 2026-09-17–2026-09-172026-09-18: 4 · observed 2026-10-20T20:41:42.5604690Z · period 2026-09-18–2026-09-182026-09-21: 2 · observed 2026-10-20T20:41:42.5604690Z · period 2026-09-21–2026-09-212026-09-25: 1 · observed 2026-10-20T20:41:42.5604690Z · period 2026-09-25–2026-09-252026-09-26: 2 · observed 2026-10-20T20:41:42.5604690Z · period 2026-09-26–2026-09-262026-09-27: 3 · observed 2026-10-20T20:41:42.5604690Z · period 2026-09-27–2026-09-272026-09-28: 2 · observed 2026-10-20T20:41:42.5604690Z · period 2026-09-28–2026-09-282026-09-29: 2 · observed 2026-10-20T20:41:42.5604690Z · period 2026-09-29–2026-09-292026-09-30: 3 · observed 2026-10-20T20:41:42.5604690Z · period 2026-09-30–2026-09-302026-10-01: 1 · observed 2026-10-20T20:41:42.5604690Z · period 2026-10-01–2026-10-012026-10-03: 1 · observed 2026-10-20T20:41:42.5604690Z · period 2026-10-03–2026-10-032026-10-05: 1 · observed 2026-10-20T20:41:42.5604690Z · period 2026-10-05–2026-10-052026-10-06: 1 · observed 2026-10-20T20:41:42.5604690Z · period 2026-10-06–2026-10-062026-10-07: 2 · observed 2026-10-20T20:41:42.5604690Z · period 2026-10-07–2026-10-072026-10-08: 6 · observed 2026-10-20T20:41:42.5604690Z · period 2026-10-08–2026-10-082026-10-09: 4 · observed 2026-10-20T20:41:42.5604690Z · period 2026-10-09–2026-10-092026-10-10: 1 · observed 2026-10-20T20:41:42.5604690Z · period 2026-10-10–2026-10-102026-10-11: 5 · observed 2026-10-20T20:41:42.5604690Z · period 2026-10-11–2026-10-112026-10-12: 1 · observed 2026-10-20T20:41:42.5604690Z · period 2026-10-12–2026-10-122026-10-13: 1 · observed 2026-10-20T20:41:42.5604690Z · period 2026-10-13–2026-10-132026-10-15: 2 · observed 2026-10-20T20:41:42.5604690Z · period 2026-10-15–2026-10-152026-10-16: 3 · observed 2026-10-20T20:41:42.5604690Z · period 2026-10-16–2026-10-162026-10-17: 1 · observed 2026-10-20T20:41:42.5604690Z · period 2026-10-17–2026-10-172026-10-18: 4 · observed 2026-10-20T20:41:42.5604690Z · period 2026-10-18–2026-10-18
4 Aug18 Oct

pypistats · 60 observations shown. Missing days are unknown. Source category: overall: without mirrors.

View observed values
Date / source periodValueObserved at
2026-10-18 – 2026-10-1842026-10-20T20:41:42.5604690Z
2026-10-17 – 2026-10-1712026-10-20T20:41:42.5604690Z
2026-10-16 – 2026-10-1632026-10-20T20:41:42.5604690Z
2026-10-15 – 2026-10-1522026-10-20T20:41:42.5604690Z
2026-10-13 – 2026-10-1312026-10-20T20:41:42.5604690Z
2026-10-12 – 2026-10-1212026-10-20T20:41:42.5604690Z
2026-10-11 – 2026-10-1152026-10-20T20:41:42.5604690Z
2026-10-10 – 2026-10-1012026-10-20T20:41:42.5604690Z
2026-10-09 – 2026-10-0942026-10-20T20:41:42.5604690Z
2026-10-08 – 2026-10-0862026-10-20T20:41:42.5604690Z
2026-10-07 – 2026-10-0722026-10-20T20:41:42.5604690Z
2026-10-06 – 2026-10-0612026-10-20T20:41:42.5604690Z
2026-10-05 – 2026-10-0512026-10-20T20:41:42.5604690Z
2026-10-03 – 2026-10-0312026-10-20T20:41:42.5604690Z
2026-10-01 – 2026-10-0112026-10-20T20:41:42.5604690Z
2026-09-30 – 2026-09-3032026-10-20T20:41:42.5604690Z
2026-09-29 – 2026-09-2922026-10-20T20:41:42.5604690Z
2026-09-28 – 2026-09-2822026-10-20T20:41:42.5604690Z
2026-09-27 – 2026-09-2732026-10-20T20:41:42.5604690Z
2026-09-26 – 2026-09-2622026-10-20T20:41:42.5604690Z
2026-09-25 – 2026-09-2512026-10-20T20:41:42.5604690Z
2026-09-21 – 2026-09-2122026-10-20T20:41:42.5604690Z
2026-09-18 – 2026-09-1842026-10-20T20:41:42.5604690Z
2026-09-17 – 2026-09-1712026-10-20T20:41:42.5604690Z
2026-09-16 – 2026-09-1632026-10-20T20:41:42.5604690Z
2026-09-14 – 2026-09-1412026-10-20T20:41:42.5604690Z
2026-09-12 – 2026-09-1242026-10-20T20:41:42.5604690Z
2026-09-10 – 2026-09-1012026-10-20T20:41:42.5604690Z
2026-09-09 – 2026-09-0932026-10-20T20:41:42.5604690Z
2026-09-07 – 2026-09-0742026-10-20T20:41:42.5604690Z
2026-09-06 – 2026-09-0622026-10-20T20:41:42.5604690Z
2026-09-05 – 2026-09-0512026-10-20T20:41:42.5604690Z
2026-09-04 – 2026-09-0422026-10-20T20:41:42.5604690Z
2026-09-03 – 2026-09-0312026-10-20T20:41:42.5604690Z
2026-09-02 – 2026-09-0212026-10-20T20:41:42.5604690Z
2026-09-01 – 2026-09-0112026-10-20T20:41:42.5604690Z
2026-08-31 – 2026-08-3152026-10-20T20:41:42.5604690Z
2026-08-29 – 2026-08-2912026-10-20T20:41:42.5604690Z
2026-08-28 – 2026-08-2872026-10-20T20:41:42.5604690Z
2026-08-27 – 2026-08-2732026-10-20T20:41:42.5604690Z
2026-08-24 – 2026-08-24142026-10-20T20:41:42.5604690Z
2026-08-23 – 2026-08-2362026-10-20T20:41:42.5604690Z
2026-08-22 – 2026-08-2212026-10-20T20:41:42.5604690Z
2026-08-21 – 2026-08-2122026-10-20T20:41:42.5604690Z
2026-08-20 – 2026-08-2022026-10-20T20:41:42.5604690Z
2026-08-19 – 2026-08-1922026-10-20T20:41:42.5604690Z
2026-08-18 – 2026-08-18232026-10-20T20:41:42.5604690Z
2026-08-17 – 2026-08-1752026-10-20T20:41:42.5604690Z
2026-08-16 – 2026-08-1632026-10-20T20:41:42.5604690Z
2026-08-14 – 2026-08-1452026-10-20T20:41:42.5604690Z
2026-08-13 – 2026-08-1342026-10-20T20:41:42.5604690Z
2026-08-12 – 2026-08-1212026-10-20T20:41:42.5604690Z
2026-08-11 – 2026-08-1132026-10-20T20:41:42.5604690Z
2026-08-10 – 2026-08-1032026-10-20T20:41:42.5604690Z
2026-08-09 – 2026-08-0962026-10-20T20:41:42.5604690Z
2026-08-08 – 2026-08-0812026-10-20T20:41:42.5604690Z
2026-08-07 – 2026-08-0752026-10-20T20:41:42.5604690Z
2026-08-06 – 2026-08-0642026-10-20T20:41:42.5604690Z
2026-08-05 – 2026-08-0522026-10-20T20:41:42.5604690Z
2026-08-04 – 2026-08-041232026-10-20T20:41:42.5604690Z

Versions 1

Collected releases
VersionPublishedDirect dependenciesOpen version
0.1.04 Aug 20265

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Repository

PENDING
christopherdond/9router-python

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 16:14 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:2367554558a8768877b5214e153f3cf0ee00aaba36f4981dbdd44de35b76e368