Pylva SDK — cost infrastructure for AI agent businesses
Project description
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.2 publishes the LangGraph / LangChain callback integration on
top of the public SDK foundation. 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(),
)
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.
Non-LLM costs
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/syncreconciliation. If the local view is already over a hard-stop limit, the SDK raisesPylvaBudgetExceeded(source=BudgetExceededSource.SDK_PRECALL). -
Backend-authoritative flag. Every ingest response may carry
budget_exceeded[]. The SDK bumps local accumulators tolimit + 1on receipt; next pre-call raisessource=BACKEND_INGEST_FLAG. -
5-min sync loop. A
threading.Timerre-POSTs accumulator state to/api/v1/budget/syncand 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. The charset-regex input validation rejects HTML
and most control characters — it does not protect against free-form PII.
See specs.md Appendix D14 for the rationale. PII handling is the builder's
responsibility; we provide exportable data and deletion endpoints.
License
MIT.
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pylva_sdk-1.0.2.tar.gz.
File metadata
- Download URL: pylva_sdk-1.0.2.tar.gz
- Upload date:
- Size: 63.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b6fd45d288b241a1853d87f97df631be1c8be130f739106ec14f58afed9ca7ff
|
|
| MD5 |
47ea74f62f63a2d2ae0bcbc2e68349e6
|
|
| BLAKE2b-256 |
512e0c4019ffecd033de392c1f5ea83052614a3863af5e3bd46e91918e28ad67
|
Provenance
The following attestation bundles were made for pylva_sdk-1.0.2.tar.gz:
Publisher:
publish-python-sdk.yml on SpaceGravity/pylva
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pylva_sdk-1.0.2.tar.gz -
Subject digest:
b6fd45d288b241a1853d87f97df631be1c8be130f739106ec14f58afed9ca7ff - Sigstore transparency entry: 1975215252
- Sigstore integration time:
-
Permalink:
SpaceGravity/pylva@8c9b9605dd92232d921b3f33dade70ab70acfe7e -
Branch / Tag:
refs/tags/pylva-py-v1.0.2 - Owner: https://github.com/SpaceGravity
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python-sdk.yml@8c9b9605dd92232d921b3f33dade70ab70acfe7e -
Trigger Event:
push
-
Statement type:
File details
Details for the file pylva_sdk-1.0.2-py3-none-any.whl.
File metadata
- Download URL: pylva_sdk-1.0.2-py3-none-any.whl
- Upload date:
- Size: 51.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
65101ed92e13d37441d5c555acd1482e5f4b8bbadbd7d049adb6a635701be3f3
|
|
| MD5 |
3ea6433285b35103a7eddd0afbecfb73
|
|
| BLAKE2b-256 |
1e344b8c096a9080bb9eaa93e75383036e3c1ecd11693a17493bf3746d64e97c
|
Provenance
The following attestation bundles were made for pylva_sdk-1.0.2-py3-none-any.whl:
Publisher:
publish-python-sdk.yml on SpaceGravity/pylva
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pylva_sdk-1.0.2-py3-none-any.whl -
Subject digest:
65101ed92e13d37441d5c555acd1482e5f4b8bbadbd7d049adb6a635701be3f3 - Sigstore transparency entry: 1975215366
- Sigstore integration time:
-
Permalink:
SpaceGravity/pylva@8c9b9605dd92232d921b3f33dade70ab70acfe7e -
Branch / Tag:
refs/tags/pylva-py-v1.0.2 - Owner: https://github.com/SpaceGravity
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python-sdk.yml@8c9b9605dd92232d921b3f33dade70ab70acfe7e -
Trigger Event:
push
-
Statement type: