Skip to content

Zeroth

The economic debugger for production AI workflows.

Zeroth explains cost and breakage by outcome, workflow version, step, subject/cohort, and time, then backtests a cost-saving change before rollout.

Understand the product boundary →

Source · Releases · PyPI · Issues · Changelog

Current availability

The economic-debugger API is self-hostable from this repository. It accepts tenant-scoped evidence, exposes timeline/cohort/breakage queries, compares exact workflow versions, and runs bounded model-change backtests. Managed hosting, production provider credentials, merchant checkout/webhook integration, organization rollups, and signed proof-of-savings are not implemented product claims. The internal subscription projection exists but is not yet a way to buy the service.

Run the economic debugger API →

Standalone SDK release is blocked

packaging/sdk now has matching authenticated routes, retrieval, and real end-to-end coverage. Do not publish or recommend pip install zeroth-sdk until a supported hosted endpoint and production provider credentials exist.

PyPI

The published zeroth-core package is a stale 0.1.0 placeholder (verified 2026-08-24). It is also the preserved local platform, not the lean customer SDK. Do not install it for the current source tree.

Docs for the current source tree

This site is built from the repository's main branch, which can be ahead of PyPI. To run the exact code documented here, clone rrrozhd/zeroth and run uv sync.

Use the Getting Started tutorial for a guided first graph, or jump to local development to run the API and web console.

Primary product flow

  1. Attribute cost and outcome to version, run, step, attempt, and subject.
  2. Debug timelines, cohorts, and the groups that break the pipeline.
  3. Backtest a cheaper model or workflow candidate against recorded cases.
  4. Govern rollout with explicit economic and evidence thresholds.

zeroth.optimization remains the local façade over existing analytics. The headless service API is now the primary product surface. The existing console remains an optional open-source UI.

Preserved platform paths

Import Zeroth directly into your Python application. Build a graph with one agent, one tool, and one LLM call, then drive it to completion inside your own process — no HTTP hop.

Start: First graph tutorial →

Boot Zeroth as a standalone FastAPI service, POST runs over HTTP, and exercise the governance surface (human approval gate, policy block, audit trail) through the real service API.

Start: Service mode & approval tutorial →

The Getting Started tutorial documents the preserved graph runtime and service paths.

Hello, Zeroth

The smallest possible smoke test — install the package, set OPENAI_API_KEY, and run the script below. You should see a one-line LLM greeting in under 5 minutes.

examples/00_hello.py
"""00 — Hello, Zeroth: a single agent node, run through the real runtime.

What this shows
---------------
The smallest possible end-to-end invocation. One :class:`AgentNode`, one
real :class:`AgentRunner` backed by the real :class:`LiteLLMProviderAdapter`,
run through the real :class:`RuntimeOrchestrator`. No stubs, no hacks, no
``litellm.completion`` calls in user code — this file is what the library
wants you to write.

Requirements
------------
* ``OPENAI_API_KEY`` in the environment (uses ``openai/gpt-4o-mini``).
  Set ``ZEROTH_EXAMPLE_MODEL`` to override the model name.

Run
---
    uv run python examples/00_hello.py
"""

from __future__ import annotations

# Allow python examples/NN_name.py to find the sibling examples/_common.py helper.
import sys as _sys
from pathlib import Path as _Path

_sys.path.insert(0, str(_Path(__file__).resolve().parents[1]))

import asyncio
import os
import sys

from examples._common import (
    DEMO_GRAPH_ID,
    print_run_summary,
    require_env,
    running_service,
)
from examples._contracts import Answer, Question
from zeroth.contracts.graph import (
    AgentNode,
    AgentNodeData,
    DisplayMetadata,
    ExecutionSettings,
    Graph,
)
from zeroth.runtime.agents import (
    AgentConfig,
    AgentRunner,
    LiteLLMProviderAdapter,
)


def build_graph(model_name: str) -> Graph:
    """A one-node graph whose only step is a Q&A :class:`AgentNode`."""
    graph_version_ref = f"{DEMO_GRAPH_ID}@1"
    return Graph(
        graph_id=DEMO_GRAPH_ID,
        name="Hello, Zeroth",
        version=1,
        entry_step="qa",
        execution_settings=ExecutionSettings(max_total_steps=5),
        nodes=[
            AgentNode(
                node_id="qa",
                graph_version_ref=graph_version_ref,
                display=DisplayMetadata(title="Q&A"),
                input_contract_ref="contract://question",
                output_contract_ref="contract://answer",
                agent=AgentNodeData(
                    instruction=(
                        "You are a helpful assistant. Answer the user's question in one "
                        "short sentence. Return JSON matching the output schema."
                    ),
                    model_provider=model_name,
                    model_params={"temperature": 0.2, "max_tokens": 120},
                ),
            ),
        ],
        edges=[],
    )


async def main() -> int:
    if not require_env("OPENAI_API_KEY"):
        return 0

    model_name = os.environ.get("ZEROTH_EXAMPLE_MODEL", "openai/gpt-4o-mini")

    # Build one real AgentRunner for the one node in the graph. The
    # LiteLLMProviderAdapter reads OPENAI_API_KEY from the environment.
    runner = AgentRunner(
        AgentConfig(
            name="qa",
            description="Answers a user question in one sentence.",
            instruction="Answer the user in one short sentence.",
            model_name=model_name,
            input_model=Question,
            output_model=Answer,
        ),
        LiteLLMProviderAdapter(),
    )

    async with running_service(
        build_graph(model_name),
        contracts={
            "contract://question": Question,
            "contract://answer": Answer,
        },
        agent_runners={"qa": runner},
    ) as demo:
        run = await demo.service.orchestrator.run_graph(
            demo.service.graph,
            {"question": "What is Zeroth in one sentence?"},
            deployment_ref=demo.deployment_ref,
        )
        print_run_summary(run, label="hello")
    return 0


if __name__ == "__main__":
    sys.exit(asyncio.run(main()))