Skip to main content

Agent-side SDK for the Prova AI control plane (ingest, gateway-check, register).

Project description

prova-sdk (Python)

Agent-side SDK for the Prova AI control plane. Thin wrappers around:

  • POST /api/v1/audit/ingest
  • POST /api/v1/gateway/check
  • POST /api/v1/inventory

Plus an Ed25519 receipt verifier and a one-shot migration tool that bulk-imports existing LangSmith / Langfuse / OpenAI logs into the Audit Vault.

Separate from the legacy prova package (the reasoning-chain verifier). See /docs/sdk for guidance on which one to install.

Install

pip install prova-sdk

Requires Python 3.10+.

Quick start

from prova_cp import ProvaClient

prova = ProvaClient(api_key="prv_...")

prova.ingest({
    "kind": "model_call",
    "source": {"org_id": "YOUR_ORG", "framework": "langgraph", "app_id": "claims-orchestrator"},
    "model": {"provider": "openai", "name": "gpt-4o"},
    "payload": {"messages": messages, "response": response},
})

check = prova.gateway_check({"kind": "model_call", "payload": {"messages": messages}})
if check["action"] == "block":
    raise PolicyBlocked(check["findings"])

Pass verify_receipts=True to make the client verify every returned receipt's Ed25519 signature against the published public key before returning.

LangGraph / LangChain auto-instrumentation

Install the optional extra and drop the callback handler into any graph. Every LLM call, node, and tool call is ingested as a signed receipt automatically. No per-node code changes.

pip install "prova-sdk[langgraph]"
from prova_cp import ProvaClient, ProvaCallbackHandler

prova = ProvaClient(api_key="prv_...")
handler = ProvaCallbackHandler(
    prova,
    app_id="claims-orchestrator",
    environment="production",
    framework="langgraph",
)

# LangGraph
graph.invoke(inputs, config={"callbacks": [handler]})

# LangChain
chain.invoke(inputs, config={"callbacks": [handler]})

The handler is fail-silent: a Prova outage logs at warning level and never breaks the agent. LLM calls become model_call receipts, graph nodes become agent_step, tool calls become tool_call.

Catch the loop in-process

The handler also accumulates the {node, reads, writes} trace and emits one agent_run receipt per run, so the server-side coordination_loop detector fires from auto-instrumentation (it only triggers on agent_run, never on per-step events). That catch is asynchronous: by the time the receipt is signed, the agents have already burned the budget.

Pass break_on_loop=True to run the same detection algorithm in-process and stop the run the moment a persistent loop forms:

from prova_cp import ProvaCallbackHandler, CoordinationLoopError

handler = ProvaCallbackHandler(prova, app_id="claims-orchestrator", break_on_loop=True)

try:
    graph.invoke(inputs, config={"callbacks": [handler]})
except CoordinationLoopError as e:
    # e.match: {agents, born_at_step, persistence_steps, total_steps, total_agents}
    log.error("broke a coordination loop across %s", e.match["agents"])

The signed agent_run receipt is flushed before the exception propagates, so the audit trail records the loop you caught. The detection is a faithful port of the canonical server-side detector, so a loop caught locally is the same loop an auditor sees in the receipt.

For a runtime without LangChain callbacks, drive LoopGuard directly:

from prova_cp import LoopGuard, CoordinationLoopError

guard = LoopGuard()  # raise_on_detect=True by default
for node, reads, writes in run_agent():
    guard.observe(node, reads=reads, writes=writes)  # raises on a persistent loop

CrewAI

CrewAI has no LangChain-style callbacks; use its step_callback / task_callback hooks instead.

from prova_cp import ProvaClient, ProvaCrewAI

tap = ProvaCrewAI(ProvaClient(api_key="prv_..."), app_id="research-crew")
crew = Crew(agents=[...], tasks=[...],
            step_callback=tap.step_callback,
            task_callback=tap.task_callback)

Agent steps become agent_step receipts; completed tasks become agent_run.

Raw OpenAI / Anthropic clients (no framework)

Wrap the vendor client once. Every completion is mirrored to a signed receipt. The vendor response is returned unchanged and a Prova failure never raises. Synchronous, async (AsyncOpenAI/AsyncAnthropic), and streamed (stream=True) calls are all captured; for streams the receipt fires once after the stream is fully consumed, with the chunk text reassembled.

from openai import OpenAI
from prova_cp import ProvaClient, wrap_openai

client = wrap_openai(OpenAI(), ProvaClient(api_key="prv_..."), app_id="support-bot")
client.chat.completions.create(model="gpt-4o", messages=[...])  # auto-ingested

wrap_anthropic is identical for the Anthropic SDK (messages.create).

Migrate existing logs

CLI:

PROVA_API_KEY=prv_... prova-migrate --source langsmith --file runs.ndjson

Programmatic:

from prova_cp import ProvaClient, migrate
from prova_cp.migrate import read_ndjson

with ProvaClient(api_key="prv_...") as client, open("observations.ndjson") as f:
    result = migrate(client, "langfuse", read_ndjson(f))
    print(result)

Supported sources: langsmith, langfuse, openai. Idempotency keys are derived from the source row id, so re-running the migration is safe.

Verify a receipt offline

from prova_cp import verify_receipt

verify_receipt(receipt, public_key_pem=PUBLIC_KEY_PEM)

Or fetch the public key from the deployment automatically:

verify_receipt(receipt, base_url="https://api.prova.cobound.dev")

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

prova_sdk-0.3.0.tar.gz (19.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

prova_sdk-0.3.0-py3-none-any.whl (25.3 kB view details)

Uploaded Python 3

File details

Details for the file prova_sdk-0.3.0.tar.gz.

File metadata

  • Download URL: prova_sdk-0.3.0.tar.gz
  • Upload date:
  • Size: 19.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for prova_sdk-0.3.0.tar.gz
Algorithm Hash digest
SHA256 7384cd7e4b453065744759306508ee14ee761e176b4767ff8eec9b52886d8726
MD5 19b70fb420978c1d8ce7e6a008458af4
BLAKE2b-256 9fc39a7f458b6544fedf98f88389a2c1286c28fe408769fdd5ec33a79ae08794

See more details on using hashes here.

File details

Details for the file prova_sdk-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: prova_sdk-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 25.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for prova_sdk-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f42da3c98998f6d8b4e223c51b3a66d85c2c6eb5b3679c870947c3d422c16ccd
MD5 be7a43ebb41770c25a2fd83b330a0134
BLAKE2b-256 3148089e3591f881ce5b128c65404e2e5ecdce648753d7884da57684adfc80cd

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page