Skip to main content

pylva (Python)

Cost infrastructure for AI agent businesses. Auto-instruments openai and anthropic clients; emits server-priced telemetry to your Pylva backend.

Version 1.0.5 adds policy-driven non-LLM cost tracking. Public APIs follow SemVer; the telemetry wire format remains schema 1.6.

pip install pylva-sdk
import pylva

pylva.init(api_key="pv_live_...", endpoint="https://api.pylva.com")
# every subsequent openai / anthropic call emits a telemetry event.

Package name

The PyPI distribution package is pylva-sdk; the runtime import package is pylva:

pip install pylva-sdk
import pylva

Failover (reliability_failover rules)

If you use reliability_failover rules, switch to the explicit-client constructor so Pylva has a handle to the backup provider:

from openai import OpenAI
from anthropic import Anthropic
from pylva import Pylva

Pylva(
    api_key="pv_live_...",
    openai=OpenAI(),
    anthropic=Anthropic(),
    providers={"openrouter": openrouter_client},
)

Use providers={...} for any additional provider id exactly as it appears in your rules or telemetry.

pylva.init(api_key) keeps working for telemetry-only deployments. In v1.0, the SDK detects active cross-provider failover states and surfaces warnings; actual backup-provider dispatch is still beta/internal and is not part of the stable launch promise.

Auto-instrumentation

Importing pylva monkey-patches any openai / anthropic modules already loaded. Patches are isolated per R1 — SDK errors never propagate to your agent.

Calls are captured with: model, provider, tokens_in, tokens_out, latency_ms, status, step_name (if set), customer_id. Cost is computed server-side.

Tracking context

from pylva import track_context

with track_context(customer_id="acme-corp", step="authentication"):
    resp = openai_client.chat.completions.create(...)

track_context is a contextvars-backed context manager; it threads metadata across async + threaded boundaries correctly.

LangGraph / LangChain callback

For LangGraph apps, use the callback handler when you want cost attribution by graph run, node, and customer:

pip install "pylva-sdk[langchain]"
import os
from pylva.langchain import PylvaCallbackHandler

handler = PylvaCallbackHandler(api_key=os.environ["PYLVA_API_KEY"])

graph.invoke(
    {"question": "Where did spend increase?"},
    config={
        "callbacks": [handler],
        "metadata": {"pylva_customer_id": "cust_acme"},
    },
)

The handler reads LangChain usage metadata, preserves LangGraph run ids, uses langgraph_node as the default step name, and never captures prompt, completion, tool input, or tool output text. Metadata step labels from langgraph_node, langgraph_step, and pylva_step must be identifier-like ([A-Za-z0-9_.:/-], max 100 chars). Free-text prompts or messages should never be placed in metadata; unsafe labels are ignored.

Non-LLM costs

For automatic LangGraph / LangChain tool-call tracking, use dashboard policy mode. Unknown tools are sent to Cost Sources as pending discoveries; they do not affect customer cost until a builder marks them tracked and configures the metric, unit, matchers, and price in the dashboard.

from pylva.langchain import PylvaCallbackHandler

handler = PylvaCallbackHandler(
    api_key="pv_live_...",
    non_llm={"mode": "policy"},
)

You can provide a usage extractor when a tracked tool consumes more than one unit per call:

handler = PylvaCallbackHandler(
    api_key="pv_live_...",
    non_llm={
        "mode": "policy",
        "usage_extractors": {
            "tavily": lambda ctx: 1,
        },
    },
)

track_tool_calls=True is still supported for backwards compatibility, but it records every observed tool call as calls=1. Prefer policy mode for production cost attribution.

For explicit non-LLM usage reporting, keep using report_usage():

from pylva import report_usage

report_usage(
    customer_id="acme-corp",
    tool="translation",
    metric="characters",
    value=4200,
    step="translation",
)

Reactive budget enforcement (B2a)

When a builder configures a budget_limit rule with hard_stop=True, the SDK enforces pre-call:

import pylva
from pylva import PylvaBudgetExceeded, BudgetExceededSource

pylva.init(api_key="pv_live_...")

try:
    resp = openai_client.chat.completions.create(...)
except PylvaBudgetExceeded as err:
    print(f"Budget hit for {err.customer_id}: ${err.accumulated_usd:.2f} / ${err.limit_usd:.2f}")
    print(f"Source: {err.source.value}")  # 'sdk_precall' or 'backend_ingest_flag'
    # graceful degradation

How it works

  • Pre-call accumulator (per-process dict + threading.Lock). Keyed on (rule_id, scope_token, period_start). Local enforcement is driven by backend budget flags and /budget/sync reconciliation. If the local view is already over a hard-stop limit, the SDK raises PylvaBudgetExceeded(source=BudgetExceededSource.SDK_PRECALL).

  • Backend-authoritative flag. Every ingest response may carry budget_exceeded[]. The SDK bumps local accumulators to limit + 1 on receipt; next pre-call raises source=BACKEND_INGEST_FLAG.

  • 5-min sync loop. A threading.Timer re-POSTs accumulator state to /api/v1/budget/sync and overwrites local with the server truth (not additive).

  • Passthrough. Cold rules cache or unreachable backend → pre-call is a no-op. Your agent never blocks due to Pylva being degraded (R5).

Rule behavior matrix

type hard_stop Behavior
budget_limit True Pre-call raises PylvaBudgetExceeded; LLM call skipped.
budget_limit False Pre-call prints an advisory warning (1/min per rule); LLM call proceeds.
cost_threshold n/a Post-call evaluation only (backend); no SDK-side enforcement.

Webhook verification

import os
from pylva import verify_webhook, InvalidSignatureFormat

def handle_webhook(body: str, signature: str, timestamp: str):
    try:
        ok = verify_webhook(body, signature, os.environ["WEBHOOK_SECRET"], timestamp)
    except InvalidSignatureFormat:
        return 400
    if not ok:
        return 400
    # ...

verify_webhook accepts both raw hex and the sha256=<hex> GitHub-style prefix (B2a D34 parity with TS SDK). Default timestamp tolerance is 300 s.

Privacy & PII

Pylva does not redact step_name, customer_id, or metadata values. Do not pass raw user message content, email addresses, or phone numbers into these fields. LangGraph metadata step labels are accepted only when they are identifier-like; other validation rejects HTML and most control characters. This does not protect against free-form PII.

SDKs never auto-redact by design: regex redaction is noisy and incomplete, and classifier redaction would add an LLM round-trip to the hot path. PII handling is the builder's responsibility; we provide exportable data and deletion endpoints.

License

MIT.

Metadata

Release files for pylva-sdk 1.0.5

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

Source distribution (sdist)

Source distribution for pylva-sdk 1.0.5
File Size Uploaded
pylva_sdk-1.0.5.tar.gz 74.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pylva-sdk 1.0.5
File Interpreter ABI Platform
pylva_sdk-1.0.5-py3-none-any.whl Python 3 none any Details

Total release size: 131.1 kB

Release files / pylva_sdk-1.0.5.tar.gz

Download URL pylva_sdk-1.0.5.tar.gz
Size 74.1 kB
Tags Source
SHA-256 checksum
How to use checksums
85c9696a458a913ddcf6095eaf273a9a61b0222ad4583e82057024d06bb62c9c
BLAKE2b-256 checksum
How to use checksums
a3b5f7475f57dd4a983df6e27af06e25557d2c8fef3ea24f003f4de408bdaa6f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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 Jul 8, 2026.

Transparency log

Release files / pylva_sdk-1.0.5-py3-none-any.whl

Download URL pylva_sdk-1.0.5-py3-none-any.whl
Size 57.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5579354a2f89481440650b94fc4ebcdf6fcd40d5f0820125bdc4fcb4caea8796
BLAKE2b-256 checksum
How to use checksums
b1f8a5687a9b6222ccc5c47a30174c8f480f82cd7f281b6275b810461b34cdb9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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 Jul 8, 2026.

Transparency log

Release history Release notifications | RSS feed

1.1.0

2 release files

This release

1.0.5 This release

2 release files

1.0.4

2 release files

1.0.3

2 release files

1.0.2

2 release files

1.0.1

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