• Joined on 2026-05-04

uais-wai (1.0.1)

Published 2026-07-27 06:43:37 +00:00 by admin

Installation

pip install --index-url  --extra-index-url https://pypi.org/simple uais-wai

About this package

WAI (Watcher AI) Python SDK — fire-and-forget event ingest, diagnose, trace for UAIS ecosystem apps

uais-wai — WAI Python SDK

Python client for the WAI (Watcher AI) observability + intervention platform.

Hatayı ben yönetirim, hata beni değil.

Install

uais-wai is published to UAIS' internal Gitea package registry, not public PyPI — a plain pip install uais-wai will fail (no matching distribution / 401). You need both the internal index (for uais-wai itself) and public PyPI (for its transitive dependencies, e.g. httpx, pydantic) — --extra-index-url is required, a single --index-url alone is not enough:

pip install \
  --index-url "https://admin:${GITEA_PKG_READ_TOKEN}@gitea.uais.ai/api/packages/uais/pypi/simple/" \
  --extra-index-url "https://pypi.org/simple/" \
  uais-wai

# with FastAPI adapter
pip install ... 'uais-wai[fastapi]'
# with SQLAlchemy adapter
pip install ... 'uais-wai[sqlalchemy]'

GITEA_PKG_READ_TOKEN is the read-only package-registry token distributed to sibling projects (source of truth: uais-platform/platform-config.md) — it is not a per-repo git credential, only a package-pull token. For a CI pipeline, put the same two flags in pip.conf:

[global]
index-url = https://admin:${GITEA_PKG_READ_TOKEN}@gitea.uais.ai/api/packages/uais/pypi/simple/
extra-index-url = https://pypi.org/simple/

Python 3.12+.

Quickstart

import os
from uais_wai import WAIClient

wai = WAIClient(
    endpoint="https://wai.uais.ai",
    tenant_id="example",                     # app_uid bound to your tenant
    api_key=os.environ["WAI_API_KEY"],
    environment=os.getenv("WAI_ENV", "production"),
    app_version=os.getenv("APP_VERSION"),
    # SLA tuning (defaults shown)
    diagnose_timeout_ms=3000,
    diagnose_default_action="escalate",      # what to return on diagnose timeout
    local_buffer_size=1000,
    flush_interval_ms=500,
)

# Fire-and-forget event (returns immediately; batched in the background).
await wai.event(
    source="db",
    severity="error",
    category="db.query.slow",
    payload={"reason": "lock_timeout", "query_ms": 5200},
    context={"workspace_id": "ws-1"},
)

# Fire-and-forget metric.
await wai.metric("llm.latency_ms", 1230.5, unit="ms",
                 labels={"provider": "openrouter", "model": "anthropic/claude-sonnet-4.5"})

# Blocking diagnose (bounded by diagnose_timeout_ms).
try:
    do_thing()
except Exception as exc:
    diagnosis = await wai.diagnose(error=exc, context={"workspace_id": "ws-1", "operation": "db_write"})
    if diagnosis.timed_out:
        log.warning("WAI slow; using local default: %s", diagnosis.action)
    if diagnosis.action == "retry":
        retry_with(diagnosis.payload.get("backoff_ms", 500))
    elif diagnosis.action == "fallback":
        run_fallback(diagnosis.payload)
    else:
        escalate(diagnosis)
    await wai.diagnose_outcome(diagnosis.id, success=True)

Tracing

async with wai.trace("agent_turn", attributes={"role": "architect"}) as span:
    span.set_attribute("retries", 0)
    response = await llm.complete(...)
    span.event("llm_call", attributes={"model": "claude"})

Spans nest automatically — wai.event() calls inside a trace() block inherit the trace + span IDs.

FastAPI

from uais_wai.fastapi import WAIMiddleware
app.add_middleware(WAIMiddleware, client=wai, slow_threshold_ms=1000)

Emits per-request http.latency_ms metric, plus events on 5xx, slow requests, and unhandled exceptions. Each request opens a trace so handler events get the same trace_id.

SQLAlchemy

from sqlalchemy import create_engine
from uais_wai.sqlalchemy import attach_wai

engine = create_engine(DSN)
attach_wai(engine, wai, slow_query_ms=500)

Emits db.query.slow, db.deadlock.detected, db.pool.exhausted, db.connection.failed. Works with sync + async engines.

Behavior guarantees

Concern What the SDK does
Backend down Events buffer locally; client never crashes
Buffer full Drop newest; emit wai.ratelimit.local_buffer_full when reconnected
429 rate limit Honors Retry-After + X-RateLimit-*, exponential backoff
Diagnose timeout Returns Diagnosis(timed_out=True, action=diagnose_default_action) + fires wai.diagnose.timeout event
Network partition Auto-reconnect on next event
PII Stack traces + payloads scrubbed for UUIDs, secrets, emails before send

Shutdown

await wai.close()           # flushes buffer + closes connections
# or
async with WAIClient(...) as wai:
    ...                     # auto-close on exit

License

Apache-2.0.

Requirements

Requires Python: >=3.12
Details
PyPI
2026-07-27 06:43:37 +00:00
2
UAIS / WAI Team
Apache-2.0
32 KiB
Assets (1)
Versions (1) View all
1.0.1 2026-07-27