Skip to main content

Zeus Client Python Library

Python client library for Zeus AI data servers. Orchestrates LLM agents that call Zeus tools — catalog sync, auth, contracts, durable sessions, and the full agent loop — without any web UI.

2.4.1 — default import zeus_client is the journaled hexagonal ZeusRuntime tree. Temporary import zeus_client_v2 alias (deprecated). Claim remains candidate until human MATRIX. multi_agent is docs (CHECKLIST F). See docs/V2/, MIGRATION.md, CHANGELOG.md, MULTI_AGENT.md.

Claim (family honesty)

Field Value
package kotenai-zeus-client 2.4.1
claim_level candidate (not supported)
client_floor client-floor-5
modes agent, direct (optional Mode 3 jobs/units seam)
multi_agent docs
semantic_cache flag (CHECKLIST E2; default session.semantic_cache.enabled=false)
plugins no
suite conformance-0.2-dev (offline)
BASE packs tested mock base-5-mock; fixtures base-5.3; pin-shaped base-1 (not a COMPAT triple)
Zeus versions tested 0.6.x offline (Detective tapes sample 0.6.64; live_smoke=false). Semantic cache HTTP is Zeus ≥ 0.7.6; older engines fail-open.

Pins file: sdk_bootstrap.pins.json (HOW_TO G0). Never invent production contract_hash / Hub stamps.

Family law and ship bar:

Note on ai_process_result: package default is false (cheap path). Use profile hub or ClientSettings(ai_process_result=True) for Hub Debug insight.

Note on session.semantic_cache: capability ships (CHECKLIST E2) with master enabled=false. Opt in via config; recall injects bag B semantic_memory; writes are explicit-only by default (rt.session.semantic_cache.write(...)). Zeus owns store/recall (POST /v2/agent_memory/*). Direct typeahead is never included. Requires a Zeus build that exposes agent_memory; older engines fail-open (no inject). MATRIX honesty: flag, not supported.

Install

pip install kotenai-zeus-client

Development install:

git clone https://github.com/koten-ai/zeus_client_python.git
cd zeus_client_python
pip install -e ".[dev]"

Optional OpenTelemetry Logs export:

pip install -e ".[otel]"
Env Meaning
ZEUS_CLIENT_LOG_LEVEL error | info | debug | trace (prod default info)
ZEUS_CLIENT_LOG_REDACT true (prod default) / false (lab; secrets still hard-denied)
ZEUS_CLIENT_OTEL_ENABLED OTLP Logs when an endpoint is also set
ZEUS_CLIENT_OTEL_ENDPOINT Collector URL (e.g. http://localhost:4318/v1/logs)
ZEUS_CLIENT_SERVICE_NAME OTel service.name (default zeus_client)
ZEUS_CLIENT_IP Optional host IPv4/IPv6 for session/report stamps; omit when unknown
ZEUS_CLIENT_SEMANTIC_CACHE Master session.semantic_cache.enabled (true/false; default off)

Product sinks stamp user=zeus_client (never Hub admin). Chat/turn ids are UUID v4 when the client mints them; Zeus mints X-Zeus-Req-Id unless a test pre-mints v4.

Version 0.3.0 — direct V2 verbs + run_<verb> naming

  • run_verb / run_<verb> — direct V2 verb POSTs (no LLM) for every Zeus verb except pipeline (see docs/VERBS.md). Helpers: run_find, run_get, run_project, …; raw search body via run_search_verb / run_verb("search", …).
  • run_search / run_search_from_config — no-LLM typeahead over V2 search (FTS) + optional N1QL hydrate + find→project (see docs/FAST_SUGGEST.md). Named after the primary Zeus verb (run_<verb>). Deprecated nicknames run_fast_suggest* were removed for GA (use run_search*).
  • ai_process_result=false after Zeus tool data: no second LLM hop — prefer tool-arg summary, else a static thin line (UI shows Zeus rows).

Version 0.2.2 — fast suggest + thinner cheap path

  • Typeahead + cheap path first land (API names later normalized in 0.3.0).

Version 0.2.1 — ai_process_result (Hub parity)

Client setting ai_process_result (default true) mirrors Zeus Hub Debug “AI on Zeus result”: after terminating Zeus tools, run a no-tools insight turn; set false for the cheap path (tables/UI without a second billable hop). See docs/BASE5_CLIENT.md.

Version 0.2.0 — base-5 control plane

Optional base-5 Client floor (object rules, Layer A policy table, base_id catalog load). See docs/BASE5_CLIENT.md. Legacy *_v2.json paths remain the default when base_id is omitted. Never invent production contract_hash values — Hub stamp only.

Agent flow

One run_agent call executes a single user turn through these phases:

flowchart LR
  A[Auth] --> B[Load catalog]
  B --> C[Contract + session]
  C --> D[LLM rounds]
  D --> E[Commit turn]
  E --> F[Audit]
  1. Auth — resolve_zeus_auth mints or reuses Zeus session headers (per scope when configured).
  2. Load catalog — rt.catalog.load(mode, base_id=...) resolves a stamped chat_request (scope dir → general → bundled; lineage files chat_request_{mode}_{base_id}.json). Brief / mini-schema inject is hash-excluded.
  3. Contract + session — rt.catalog.contract.bind uses the published stamp (never invents a hash). Durable sessions create or rehydrate /v2/session; a mode switch starts a new session.
  4. LLM rounds — multi-round tool loop: provider chat completion → Zeus dispatch (V2 verbs) → SecurityHooks + tool_trail inject. Force-return when the round budget is nearly exhausted.
  5. Commit turn — multi-hop session-trace aggregate via post_session_trace (same rich body per tool req_id so every hop joins Detective; preferred hop last) plus a turn shard via continue_session_turn. Agent dispatches stamp X-Zeus-Mode (and optional X-Zeus-Trace: 1).
  6. Audit — runtime contract checks appended to trace["notes"].

Pass zeus_session_id and zeus_round from the prior turn's session_meta to continue a durable session across questions.

Fast-tier search (typeahead, no LLM)

Google-like dropdowns should not call run_agent. Use the V2 data plane via run_search (named after the Zeus search verb):

from zeus_client import ZeusClient, run_search, SuggestOptions

async with ZeusClient():
    result = await run_search(
        "sushi",
        zeus_url="http://127.0.0.1:8080",
        bucket="yelp-data",
        scope="_default",
        collection="_default",
        zcfg={"auth_mode": "basic", "username": "…", "password": "…"},
        # Optional: hydrate FTS src_keys via Couchbase Query (USE KEYS)
        couchbase={
            "query_url": "http://127.0.0.1:8093",
            "username": "Administrator",
            "password": "password",
        },
        options=SuggestOptions(entity_type="Business", limit=8, fts_timeout_ms=2000),
    )
    for hit in result.hits:
        print(hit.name, hit.subtitle, hit.id)

What it calls:

Step Endpoint / path
FTS POST /v2/{bucket}/{scope}/{collection}/search · strategy=fts
Hydrate (optional) Couchbase POST {query_url}/query/service · USE KEYS […]
Exact name / city POST …/pipeline · find → project

Do not project / get FTS biz:… keys as graph node ids — they come back missing. Prefer N1QL hydrate or find→project.

Config helper: run_search_from_config(q, cfg) reads samples + zeus + optional couchbase. CLI sketch: examples/run_search.py. Module: zeus_client.zeus.suggest.

UI: debounce ~280ms, min query length 2; on Enter without a highlight, call run_agent for full NL search.

Direct V2 verbs (no LLM, no pipeline)

For BFF paths that need a single Zeus verb without the agent loop:

from zeus_client import ZeusClient, run_find, run_get, run_verb

async with ZeusClient():
    found = await run_find(
        {"entity_type": "Business", "where": {"name": "Pathmark"}, "limit": 5},
        zeus_url="http://127.0.0.1:8080",
        bucket="yelp-data",
        scope="_default",
        zcfg={"auth_mode": "basic", "username": "…", "password": "…"},
    )
    ids = [i.get("id") for i in (found.body or {}).get("items") or [] if isinstance(i, dict)]
    if ids:
        got = await run_get(
            {"ids": ids[:10], "include": ["body"]},
            zeus_url="http://127.0.0.1:8080",
            bucket="yelp-data",
            scope="_default",
            zeus_headers=…,  # or zcfg=
        )
Helper Notes
run_verb(name, args, …) Generic entry; rejects pipeline
run_find / run_get / run_project / … One helper per exposed verb
run_search_verb Raw POST …/search body (not typeahead)
run_search Typeahead product path (see above)
pipeline Not exposed — use run_agent or dispatch_zeus_v2_verb

Full list + auth: docs/VERBS.md. Module: zeus_client.zeus.verbs.

Quick start

Sync catalogs from your Zeus server once (recommended before the first agent run):

import asyncio
from zeus_client import (
    ZeusClient,
    load_config,
    resolve_llm_provider_config,
    resolve_zeus_config,
    run_agent,
    sync_chat_requests,
)


async def main():
    async with ZeusClient():
        cfg = await load_config()
        zcfg = resolve_zeus_config(cfg)

        # Pull stamped chat_request snapshots into ~/.config/zeus_client/chat_requests/
        result = await sync_chat_requests(cfg)
        print(f"Synced {len(result.synced)} catalog(s)")

        provider = resolve_llm_provider_config(cfg)
        sample = cfg["samples"][cfg["default_sample"]]

        answer, trace, turns, session_meta = await run_agent(
            zcfg["url"], zcfg,
            provider["base_url"], provider["api_key"], provider["models"][0],
            cfg.get("default_api_version", "v2"),
            cfg.get("default_mode", "analytics"),
            sample["bucket"], sample["scope"], sample["collection"],
            "How many breweries are in the dataset?",
            prior_turns=[],
        )
        print(answer)
        print("Session:", session_meta.get("session_id"))


asyncio.run(main())

See examples/minimal_agent.py for a shorter variant that skips sync (uses bundled catalogs).

Configuration

On first run, load_config() creates ~/.config/zeus_client/config.json from the bundled example template (src/data/config.example.json).

Override the config directory:

export ZEUS_CLIENT_CONFIG_DIR=/path/to/my/config

Zeus connection

Zeus settings live under a single top-level zeus object. Use resolve_zeus_config(cfg) in code to read it (applies runtime overrides such as ZEUS_URL).

"zeus": {
  "url": "http://localhost:8080",
  "auth_mode": "none",
  "username": "",
  "password": "",
  "bearer_token": "",
  "session_id": "",
  "notes": "",
  "scope_credentials": {
    "beer-sample/_default": { "username": "", "password": "" }
  },
  "scope_contracts": {
    "beer-sample/_default": {
      "contract_id": "",
      "contract_hash": ""
    }
  },
  "enable_durable_sessions": true
}
Key Purpose
url Zeus server base URL
auth_mode none, basic, bearer, or session
username / password Global basic auth (overridden per scope when scope_credentials is set)
bearer_token Static bearer token when auth_mode is bearer
session_id Reuse an existing Zeus session when auth_mode is session
scope_credentials Per-scope basic auth, keyed by bucket/scope
scope_contracts Per-scope contract bindings (contract_id, contract_hash, mode keys)
enable_durable_sessions Create/rehydrate /v2/session across agent turns

Runtime URL override (not written back to config.json):

export ZEUS_URL=http://localhost:8080

LLM provider

LLM settings live under a single top-level llm_provider object. Use resolve_llm_provider_config(cfg) in code to read it.

"llm_provider": {
  "label": "xAI Grok",
  "base_url": "https://api.x.ai/v1",
  "api_key": "",
  "models": [
    "grok-4-1-fast-non-reasoning",
    "grok-4-1-fast-reasoning",
    "grok-4",
    "grok-3-mini"
  ]
}
Key Purpose
label Display name for logs and tooling
base_url OpenAI-compatible chat completions endpoint
api_key Provider API key
models Model IDs to choose from; pass models[0] (or another entry) to run_agent

Any OpenAI-compatible endpoint works — point base_url and api_key at your provider and list the model IDs you want to use.

Catalog sync

chat_requests_sync in config controls background catalog pulls:

Key Default Meaning
scopes "from_samples" Scopes to sync: "from_samples", "from_contracts", or ["bucket/scope", ...]
modes "auto" Modes to fetch: "auto" (union of bundled + scope_contracts keys) or ["analytics", "code", ...]
on_startup false Reserved for apps that want sync on launch

Synced files land under ~/.config/zeus_client/chat_requests/{bucket}__{scope}/ with a manifest.json fingerprint. load_chat_request prefers scope-specific synced files over bundled snapshots.

Contract hashes

In the normal flow you do not compute hashes on the client. Verify a standardized V2 chat_request with Zeus (Catalog → "Verify with Zeus"), save the stamped response, and sync or copy it into your catalog dir. The stamped contract.hash (or _hash) is what session create and drift checks use.

compute_contract_hash remains for offline diagnostics and legacy unstamped files only.

Lint catalog rules (open-surface conflicts)

Operators can inject unbounded rules into hash-excluded surfaces (guidance.*, especially guidance.injections.business_logic and guidance.optimal_paths). Over time those rules can contradict each other. The client ships a read-only linter:

Version What it does
V1 (ZC-35) Soft / advisory NL heuristics (always/never, duplicates, optimal_paths hygiene)
V2 (ZC-36) Structured open-rule effects + deterministic hard conflicts, open-vs-locked checks, assemble-time cache
Surface Paths Linter role
Contract-locked (hashed) instructions.*, masq, verbs / tools, messages[*].content before SCOPE BRIEF Never rewritten; open-vs-locked may flag opposition
Open inserts (hash-excluded) entire guidance tree, contract, metadata, _*, post-brief injects Primary conflict inventory

Structured open rules (hard lint source of truth) look like:

{
  "id": "ban-find-beer",
  "effect": "forbid_tool",
  "tool": "find",
  "when": { "entity_type": "Beer" },
  "source": "plugin",
  "kind": "routing",
  "rule": "Do not use find for Beer."
}
from zeus_client import lint_chat_request, lint_catalog_assembled, hash_policy_summary

report = lint_chat_request(chat_req)
print(report.conflict_score, report.severity)  # score secondary; hard counts primary
print(report.hard_finding_count, report.soft_finding_count, report.open_vs_locked_count)
for f in report.findings:
    print(f.layer, f.severity, f.check_id, f.message)

# Assemble-time (cached by contract hash + open rules hash)
report = lint_catalog_assembled(chat_req)  # respects guidance.catalog_lint / env

print(hash_policy_summary())

CLI:

python scripts/lint_chat_request.py path/to/chat_request.json
python scripts/lint_chat_request.py path/to/chat_request.json --json
python scripts/lint_chat_request.py --policy
python scripts/lint_chat_request.py --schema          # structured open-rule schema
python scripts/lint_chat_request.py path/to/chat_request.json --fail-on hard  # CI

Config (per catalog guidance.catalog_lint, or env ZEUS_CATALOG_LINT_MODE / ZEUS_CATALOG_LINT_FAIL_ON):

mode: off | assemble | debug | ci
hard_conflicts / soft_nl / open_vs_locked: bool
fail_on: none | hard | high | medium | low   # chat never fails; CI uses hard

When guidance.debug is true (or mode is assemble/debug/ci), run_agent runs assemble-time lint once per catalog fingerprint (cached), attaches trace["catalog_lint"] in debug/ci or when hard findings exist, and never blocks the turn on soft findings.

See .grok/guides/CHAT_REQUEST_CONFLICT_LINT.md for V1 vs V2 detail, migration from free-text, and limitations of locked-side extraction.

Structured responses

Pass structured=True to run_agent to receive schema-filtered Zeus rows alongside the natural-language answer:

answer, trace, turns, meta, structured = await run_agent(
    zcfg["url"], zcfg,
    provider["base_url"], provider["api_key"], provider["models"][0],
    "v2", "analytics",
    sample["bucket"], sample["scope"], sample["collection"],
    "List the top Colorado breweries by name.",
    prior_turns=[],
    structured=True,
)

print(structured.answer)       # same as answer (summary from return verb)
print(structured.zeus_data)    # [{"id": "n_...", "name": "...", ...}, ...]
print(structured.decomposition)  # structured query understanding (if model emitted it)
print(structured.warnings)     # dropped unknown fields, missing schema, etc.

zeus_data rows are extracted from the last successful Zeus data tool call in trace["tool_calls"] (find, search, pipeline, project, etc.) and filtered to fields allowed by:

  1. output_schema argument to run_agent (highest precedence), e.g. {"entity_type": "Hotel", "fields": ["id", "name", "rating"]}
  2. guidance.injections.output_schema in the loaded chat_request (operator-defined, hash-excluded)
  3. MINI-SCHEMA from the scope brief (get_mini_schema)

Reserved fields id, doc_key, and entity_type are always kept. FK join columns like brewery_id.name are kept when the prefix matches an entity_fk in MINI-SCHEMA. Unknown fields are dropped and listed in structured.warnings (also appended to trace["notes"] as [WARN] …).

You can also call extract_structured_response(answer, trace, chat_req) directly after a normal run_agent turn without re-running the agent.

Default structured=False preserves the original 4-tuple return value for backward compatibility.

Crawl / Walk / Run

Subclass AgentHooks and pass hooks=MyHooks() to run_agent to observe or steer the loop without forking core logic:

Level Hook Use
Crawl observe(event, data) Log structured events (run_start, zeus_result, final_answer, …)
Walk before_zeus_dispatch, after_zeus_dispatch Mutate tool args or rewrite results before the LLM sees them
Run on_round_start, on_ai_response, should_continue Stop early, inject messages, or cap rounds via AgentDecision

Public API

Key exports from import zeus_client:

Symbol Purpose
run_agent One user turn: LLM + Zeus tools + session/trace; optional structured=True for zeus_data
StructuredAgentResponse, extract_structured_response Parse trace into schema-filtered rows
AgentHooks, AgentDecision Crawl/Walk/Run hook points
load_config, save_config, resolve_zeus_config, resolve_llm_provider_config Config management
sync_chat_requests, SyncResult Pull stamped catalogs from Zeus
load_chat_request, list_chat_requests Catalog loading and discovery
resolve_contract_for_scope Contract binding
compute_contract_hash, extract_stamped_hash Stamped hash read + offline fallback
lint_chat_request, lint_catalog_assembled, ConflictReport, Finding, CatalogLintConfig, hash_policy_summary, structured_rule_schema Open-rule conflict lint (ZC-35/ZC-36)
resolve_zeus_auth, invalidate_zeus_session Zeus authentication
dispatch_zeus_call, dispatch_zeus_tool, dispatch_zeus_v2_verb Zeus API calls
create_zeus_session, continue_session_turn Durable sessions
rehydrate_session, post_session_trace Session rehydrate and trace shards
ZeusClient Async context manager for HTTP lifecycle

Initialize HTTP manually if not using ZeusClient:

from zeus_client import init_http, close_http

await init_http()
# ... your code ...
await close_http()

Error handling

The client uses three strategies depending on severity:

Strategy When What you see
Fatal RuntimeError Misconfiguration or unreachable Zeus before a turn can start Exception propagates; the call aborts
Structured JSON error codes Zeus tool/session HTTP transport failures Status 0 plus {"error": "<code>", "message": "..."} in the response body; the agent loop continues and surfaces the body to the LLM
Soft / trace errors Non-fatal session, trace, or LLM issues during a turn Recorded in trace["notes"], trace["session_error"], or returned as a user-facing answer string; the turn may still complete

Inspect trace after run_agent for session drift, auth re-mint notes, and the runtime contract audit block.

HTTP client lifecycle

Message / code Likely cause Fix
HTTP client not initialised (lifespan not run) client() called before init_http() or outside async with ZeusClient() Wrap calls in async with ZeusClient(): or call await init_http() at startup and await close_http() on shutdown

Configuration (load_config)

Message / code Likely cause Fix
config.json is not valid JSON at line … Trailing commas, // comments, or other invalid JSON in ~/.config/zeus_client/config.json Repair the file; use a _comment string key instead of comments

Zeus authentication (resolve_zeus_auth)

Message / code Likely cause Fix
The URL … looks like a Zeus Client address (port 8091/9999) zeus.url points at the Python client UI/nginx, not the Engine API Set zeus.url to the Engine base URL (typically http://<host>:8080) or export ZEUS_URL=…
bearer mode selected but bearer_token is empty auth_mode is bearer with no token Set zeus.bearer_token in config
session mode selected but session_id is empty auth_mode is session with no id Set zeus.session_id to a valid Zeus session
basic mode needs a bucket+scope resolve_zeus_auth called without bucket/scope in basic mode Pass bucket and scope from your sample; basic login is per-scope (POST /v1/{bucket}/{scope}/auth/session)
no credentials for scope {bucket}/{scope} No username for that scope Add zeus.scope_credentials["{bucket}/{scope}"] or global zeus.username / zeus.password
proxy_auth credentials differ from Zeus username/password Edge proxy and Zeus Basic credentials differ but share one Authorization header Use the same Basic credentials on both sides, or terminate proxy auth only on non-Zeus routes
Zeus unreachable at {url}: … DNS, firewall, or Zeus down; httpx connect/timeout error Verify host, port, and that Zeus Engine is running
HTTP 401 from an nginx reverse proxy … Reverse proxy rejected the request before it reached Zeus Add zeus.proxy_auth (or proxy_auth_username / proxy_auth_password) for the proxy gate
Zeus login failed ({status}): … Wrong username/password, scope mismatch, or Zeus auth error Confirm scope credentials in Zeus; check Zeus logs and response body
Zeus login returned no session_id Login returned 200 but body lacked session_id Inspect Zeus /v1/{bucket}/{scope}/auth/session response; upgrade or repair Zeus
unknown auth mode: {mode} Invalid zeus.auth_mode Use none, basic, bearer, or session

401 self-heal: During tool dispatch, a 401 in basic mode triggers invalidate_zeus_session + forced re-login and one retry. Failure is noted in trace["notes"] as auth: re-mint after 401 failed (…).

Catalog loading

Message / code Likely cause Fix
no chat_request file for mode '{mode}' No synced or bundled catalog for that mode/scope Run sync_chat_requests(cfg) or add the file under ~/.config/zeus_client/chat_requests/
HTTP {status} (live brief fetch) Zeus /v1/ai/chat_request.json failed while borrowing a scope brief Non-fatal: agent continues with on-disk catalog; fix Zeus URL/auth and sync catalogs
bootstrap HTTP {status}: … Scope bootstrap endpoint failed Check Zeus URL, auth, and that the scope exists
chat_request HTTP {status}: … Catalog fetch during sync/bootstrap failed Same as above; inspect status and body snippet

Catalog sync (sync_chat_requests)

Message / code Likely cause Fix
no Zeus URL configured Missing zeus.url and no ZEUS_URL env override Set URL in config or environment
no scopes configured for chat_requests sync chat_requests_sync.scopes resolved to an empty list Configure samples, scope_contracts, or an explicit scope list
Per-entry errors[].error (e.g. chat_request HTTP 500: …) Fetch failed for one scope/mode; other scopes may still sync Fix Zeus for that scope; re-run sync; check SyncResult.errors

Zeus tool dispatch (structured codes)

Returned as JSON when httpx fails (status 0). Zeus HTTP 4xx/5xx return the raw response text instead.

error code Likely cause Fix
dispatch_failed Network error, timeout, or connection reset calling a V1 tool or V2 verb Verify Zeus reachability; check TOOL_TIMEOUT; inspect trace["tool_calls"] for url and req_id

Durable sessions (structured codes and statuses)

error code / message Likely cause Fix
session_create_failed Transport error on POST /v2/session Check Zeus URL, auth, and that durable sessions are enabled on the server
session_turn_failed Transport error on POST /v2/session/{id}/turn Same; confirm session_id is valid
session_trace_failed Transport error on POST /v2/session/trace Same; trace posting is best-effort
Hub Detective thin on multi-hop / pipeline turns External client multi-hop join is incomplete for some hops Prefer result.debug.detective / support pack; open preferred_req_id / req_ids[] on the tool hop (not the /turn hop)
no session_id continue_session_turn called with empty id Ensure session create succeeded or pass zeus_session_id from prior session_meta
bad trace params Missing session id or round <= 0 for trace post Fix session state before commit
HTTP 409 + payload_hash in body Client contract_hash does not match Zeus-computed hash Re-verify catalog in Zeus UI, sync stamped file, align scope_contracts hash with stamped contract.hash
trace {status} / turn {status} in trace["session_error"] Trace or turn shard POST returned non-success Inspect Zeus logs via X-Zeus-Req-Id; check round numbering and session expiry
contract_mismatch / Session tracking failed (server text) Bound contract drifted from server expectation Sync fresh stamped catalog; update scope_contracts; see runtime audit in trace["notes"]
Rehydrate failed (note only) GET /v2/session/{id} empty or error Session may have expired; omit zeus_session_id to create a new session

Set zeus.enable_durable_sessions: false to skip session APIs when the server lacks session support.

LLM provider errors

Message / pattern Likely cause Fix
⚠️ Upstream LLM error (HTTP {status}): … Provider returned non-200 or non-JSON Verify llm_provider.api_key, base_url, and model id; check provider quota and rate limits
trace["steps"][].type == "llm_error" Same; recorded in trace Inspect detail field for provider error body

Business logic validation (inject_business_logic, audit_rows_against_rules)

Message / code Likely cause Fix
business rule references unknown entity_type … Rule entity_type not in MINI-SCHEMA Fix rule or merge live scope brief so schema is present
business rule for … references unknown field(s) … Rule fields do not exist on entity Correct field names against MINI-SCHEMA
business rule must be str or dict, got … Invalid rule type passed to inject_business_logic Pass a string or dict only
unknown predicate op … in rule Invalid operator in deny_when / require Use >, >=, <, <=, ==, !=, or in

Runtime contract audit (trace["notes"])

After each turn, checks are appended as [PASS] / [FAIL] lines. Common failures:

Check Likely cause Fix
Source file has real embedded contract Placeholder TO_BE_FILLED hash in catalog Verify with Zeus and sync stamped file
Embedded hash matches compute on loaded object Catalog rules edited after stamping, or system prompt has trailing whitespace while a live SCOPE BRIEF was merged (stamp keeps the newline; post-merge hash TrimRights it) Prefer re-verify/re-sync after edits. Trailing-whitespace-only drift is healed on load (heal_trailing_ws_stamp_drift); align scope_contracts with the post-heal / post-merge hash
Bound contract_hash matches payload hash scope_contracts hash differs from loaded catalog Update binding to stamped hash
Session created with contract_status=match Drift or no contract configured Align contract id/hash; or intentionally run without contract
No contract_mismatch / drift error Server rejected contract on session create See session 409 / payload_hash fixes above

If the audit itself throws, trace["notes"] contains runtime_audit_failed: … (non-fatal).

Demo Builder Kit

Build productized demos (NL search UI, agent loop, result cards, trace panel, Docker) using this library:

Resource Location
Kit (this repo) docs/demo-builder/
Entry for agents docs/demo-builder/AGENTS.md
Recipes + config RECIPES.md, CONFIG.md
HTTP contract API_CONTRACT.md
Reference app Sibling monorepo TravelPlan (demo_travel_sample)
GitBook Site section Demo → Python (content path demo/python in koten_docs)

Minimal programmatic agent (no UI): examples/minimal_agent.py.

Build and publish

pip install build twine
python -m build
twine upload dist/*

Development quality gates

pip install -e ".[dev]"
make ci          # ruff + mypy + pytest/cov + build/twine

GitHub Actions (.github/workflows/):

Workflow Trigger Role
ci.yml PR / push main Required offline gate
release.yml tag v* Build, GitHub Release, optional PyPI
integration.yml manual Lab-only (non-blocking stub)

Release (human): bump version clocks + CHANGELOG → merge → git tag vX.Y.Z && git push origin vX.Y.Z.
Do not self-award MATRIX / claim supported from CI green alone. pip-audit is non-blocking until ZCP-44.

License

BSD-3-Clause — see LICENSE.

Metadata

Release files for kotenai-zeus-client 2.4.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for kotenai-zeus-client 2.4.1
File Size Uploaded
kotenai_zeus_client-2.4.1.tar.gz 189.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for kotenai-zeus-client 2.4.1
File Interpreter ABI Platform
kotenai_zeus_client-2.4.1-py3-none-any.whl Python 3 none any Details

Total release size: 405.0 kB

Release files / kotenai_zeus_client-2.4.1.tar.gz

Download URL kotenai_zeus_client-2.4.1.tar.gz
Size 189.5 kB
Tags Source
SHA-256 checksum
How to use checksums
e0ef62127b496aa10fabe022f1621abfe75bcacfa59599ac392d6fde732a0ce3
BLAKE2b-256 checksum
How to use checksums
fb38e9960c1915a8c6f4d0f00f388d2dd712cf4c527e2d41485a7957432e2f8d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.

Transparency log

Release files / kotenai_zeus_client-2.4.1-py3-none-any.whl

Download URL kotenai_zeus_client-2.4.1-py3-none-any.whl
Size 215.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
13b889fce6ce2a89f54f0be89c510fa436db4540eced626d2b0982d6cc2ef662
BLAKE2b-256 checksum
How to use checksums
100855e629fc9bd8238d3be112ec1a199399b2f29e1a55f980ac54a2bf5f353e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.

Transparency log

Release history Release notifications | RSS feed

2.5.1

2 release files

This release

2.4.1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page