Skip to main content

model sdk built by the 9th ditrict at tooig

Project description

nineth

nineth is the Python SDK for the 1984 model API, built by the 9th District at Tooig.


Install

pip install nineth
export NINETH_API_KEY="your-api-key"

How it works

Every request goes through client.model.request(...).

  • Pass a task. Get a response.
  • Set stream=True to receive text as it arrives, word by word.
  • Per request, you can opt into persistent sessions, built-in services, external service paths, and debug telemetry.
  • The server still runs the worker loop and manages the actual task state.

Models

Name Description
1984-m3-0317 Most capable. Best for research and complex tasks.
1984-m2-preview Fast and powerful. Good for most tasks.
1984-m2-light Lightweight, quick general tasks.
1984-m1-unified High-throughput unified model.
1984-m0-brute Compact efficient model.
1984-m0-sm Smallest model, fastest responses.

Set a default at client creation or pass model= per call.


Cookbook

1 — Get a response

The simplest case. Ask something, get the answer.

from nineth import NinethClient

with NinethClient(default_model="1984-m3-0317") as client:
    response = client.model.request("Give me a tight BTC market brief.")
    print(response["final_response"])

response is a plain dict. The text is always in response["final_response"].


2 — Stream the response live

Set stream=True to print text as it arrives.

from nineth import NinethClient

with NinethClient(default_model="1984-m3-0317") as client:
    for event in client.model.request("Summarise crude oil today.", stream=True):
        if event["type"] == "model_delta":
            print(event["data"]["text"], end="", flush=True)

The last event in the stream is type: result and contains the full final_response alongside iterations.


3 — Choose a different model per request

from nineth import NinethClient

with NinethClient() as client:
    response = client.model.request(
        "What happened with Nvidia earnings?",
        model="1984-m2-light",
    )
    print(response["final_response"])

4 — Control reasoning depth

Use reasoning to hint at how deeply the model should think before answering. Valid values: "low", "medium", "high". Leave it out to use the model default.

from nineth import NinethClient

with NinethClient(default_model="1984-m3-0317") as client:
    response = client.model.request(
        "Analyse the macro impact of a Fed rate pause.",
        reasoning="high",
    )
    print(response["final_response"])

5 — Show the model's reasoning

Set show_reasoning=True to include the model's internal chain-of-thought. This is off by default.

from nineth import NinethClient

with NinethClient(default_model="1984-m3-0317") as client:
    response = client.model.request(
        "Walk me through whether gold is trending or ranging.",
        reasoning="medium",
        show_reasoning=True,
    )
    for block in response.get("thinking", []):
        print("[thinking]", block)
    print(response["final_response"])

6 — Limit how many turns the model takes

max_iterations controls how many model turns the server runs. The default is 10. Most tasks finish in 1–3 turns.

from nineth import NinethClient

with NinethClient(default_model="1984-m3-0317") as client:
    response = client.model.request(
        "Give me a one-paragraph ETH brief.",
        max_iterations=2,
    )
    print(response["final_response"])

7 — Async usage

import asyncio
from nineth import AsyncNinethClient

async def main():
    async with AsyncNinethClient(default_model="1984-m3-0317") as client:
        response = await client.model.request(
            "Summarise macro risk factors this week.",
        )
        print(response["final_response"])

asyncio.run(main())

Async streaming works the same way:

import asyncio
from nineth import AsyncNinethClient

async def main():
    async with AsyncNinethClient(default_model="1984-m3-0317") as client:
        async for event in await client.model.request(
            "Research BTC ETF flows.", stream=True
        ):
            if event["type"] == "model_delta":
                print(event["data"]["text"], end="", flush=True)

asyncio.run(main())

8 — Health check

No API key needed. Use this to verify the endpoint is reachable.

from nineth import NinethClient

with NinethClient() as client:
    print(client.health())
# {'status': 'ok', 'timestamp': '2026-04-04T00:00:00+00:00'}

9 — Point the SDK at a different endpoint

from nineth import NinethClient

with NinethClient(
    base_url="https://your-deployment.modal.run",
    api_key="your-key",
    default_model="1984-m3-0317",
) as client:
    response = client.model.request("Hello.")
    print(response["final_response"])

Or use environment variables:

export NINETH_BASE_URL="https://your-deployment.modal.run"
export NINETH_MODEL="1984-m3-0317"

10 — Persist and reuse a session

Set cache=True to persist the task session and receive a reusable session_id. Pass that session_id back into later requests to continue the same task memory.

from nineth import NinethClient

with NinethClient(default_model="1984-m3-0317") as client:
    first = client.model.request(
        "Start a running research notebook for crude oil.",
        cache=True,
    )
    session_id = first["session_id"]

    second = client.model.request(
        "Continue from the last note and add today's macro drivers.",
        cache=True,
        session_id=session_id,
    )
    print(second["final_response"])

If cache=False, the task is treated as one-shot and no session_id is exposed.


11 — Opt into built-in services

Built-in services are off by default.

  • default_service=False: no built-in services
  • default_service=True: all built-in services
  • default_service=[...]: only the named built-in services
from nineth import NinethClient

with NinethClient(default_model="1984-m3-0317") as client:
    response = client.model.request(
        "Research OPEC headlines and summarise the impact.",
        default_service=["search_news", "search_web"],
    )
    print(response["final_response"])

12 — Load external service paths and enable debug telemetry

Use include_service to point the server-side composer at extra schema.py service paths. Those paths must exist in the server runtime environment.

Set debug=True to keep the worker's structured telemetry in the response or event stream.

from nineth import NinethClient

with NinethClient(default_model="1984-m3-0317") as client:
    response = client.model.request(
        "Use the custom weather service and compare it with market risk sentiment.",
        default_service=["search_web"],
        include_service=["/srv/app/services/weather/schema.py"],
        debug=True,
    )
    print(response["final_response"])
    print(response.get("events", []))

Response shape

Buffered (stream=False)

{
    "final_response": "Bitcoin is trading near...",
    "iterations": 2,
    "usage": {"prompt_tokens": 412, "completion_tokens": 88, "total_tokens": 500},
    "thinking": [],          # only populated when show_reasoning=True
    "service_calls": [...],
    "service_responses": [...],
    "events": [...],
}

Only final_response and iterations are guaranteed to be present on every response.

Streaming (stream=True)

Each loop iteration yields a dict:

# Text arriving live
{"type": "model_delta", "data": {"text": "Bitcoin is trading..."}}

# Tool calls the model made
{"type": "service_call",     "data": {"service_name": "search_web", "params": {...}}}
{"type": "service_response", "data": {"service_name": "search_web", "success": True, "summary": {...}}}

# Final summary — always the last event
{"type": "result", "data": {"final_response": "...", "iterations": 2}}

Error handling

from nineth import NinethClient, NinethAPIError

with NinethClient(default_model="1984-m3-0317") as client:
    try:
        response = client.model.request("Analyse ETH.")
    except NinethAPIError as exc:
        print("API error:", exc)
    except ValueError as exc:
        print("Configuration error:", exc)

Authentication

Set NINETH_API_KEY in your environment or pass api_key= to the client constructor. The health check endpoint does not require a key.

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nineth-0.5.0.tar.gz (11.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nineth-0.5.0-py3-none-any.whl (11.3 kB view details)

Uploaded Python 3

File details

Details for the file nineth-0.5.0.tar.gz.

File metadata

  • Download URL: nineth-0.5.0.tar.gz
  • Upload date:
  • Size: 11.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for nineth-0.5.0.tar.gz
Algorithm Hash digest
SHA256 6492ca89e14c276118e6738c2e86ceb36e05a37ba54910e5d9fc79d7a8cd4358
MD5 15a8b425fbf04c4440ab8ab7747a3e7b
BLAKE2b-256 0ab395141b716e2d8b22b140e9a306d738b45f94c13ba0291c4e71ff33c0201b

See more details on using hashes here.

File details

Details for the file nineth-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: nineth-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 11.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for nineth-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 583d74667b5bdc9250ed023ec4eb80ebd19bd1c2a763271d921a68a872544870
MD5 38fb8d603c5ff5ea115614af3d1d4ad8
BLAKE2b-256 b2263db77183daf24e88f43a4dd282752168cb940c710453771a4f03155318fa

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page