npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@cobound/prova-sdk

v0.5.0

Published

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

Readme

@cobound/prova-sdk

Agent-side SDK for the Prova AI control plane. Thin wrappers around the three HTTP endpoints every customer hits at runtime:

  • POST /api/v1/audit/ingest: persist signed AI decision events
  • POST /api/v1/gateway/check: pre-execution policy + detector evaluation
  • POST /api/v1/inventory: actively register an integration

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

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

Install

npm install @cobound/prova-sdk

Requires Node 18+ (uses the built-in fetch and crypto modules).

Quick start

import { ProvaClient } from '@cobound/prova-sdk';

const prova = new ProvaClient({ apiKey: process.env.PROVA_API_KEY! });

// Ingest a decision after the model call.
await prova.ingest({
  kind: 'model_call',
  source: { org_id: 'YOUR_ORG', framework: 'langgraph', app_id: 'claims-orchestrator' },
  model: { provider: 'openai', name: 'gpt-4o' },
  payload: { messages, response },
});

// Or check before the model call:
const { action, findings } = await prova.gatewayCheck({
  kind: 'model_call',
  payload: { messages },
});
if (action === 'block') throw new Error(`blocked: ${findings.map(f => f.detector).join(', ')}`);

Pass verifyReceipts: true to make the client verify every returned receipt's Ed25519 signature against the published public key before resolving.

LangChain.js / LangGraph.js auto-instrumentation

Drop the handler into any chain or graph invoke. Every LLM call, node, and tool call is ingested as a signed receipt. Fail-silent: a Prova outage never breaks the agent.

import { ProvaClient } from '@cobound/prova-sdk';
import { ProvaCallbackHandler } from '@cobound/prova-sdk/callbacks';

const prova = new ProvaClient({ apiKey: process.env.PROVA_API_KEY! });
const handler = new ProvaCallbackHandler(prova, {
  appId: 'claims-orchestrator',
  environment: 'production',
  framework: 'langgraph',
});

await graph.invoke(inputs, { callbacks: [handler] });

No hard dependency on @langchain/core; the handler is a plain handler object LangChain.js accepts in the callbacks array.

Gate deploys on regression (prova-eval)

Tag runs with the deploy that produced them (the client reads PROVA_RELEASE automatically and stamps source.release on every event), then fail CI when a new release regresses against the last good one. Deterministic and label-free: it compares health, flag rate, loop rate, and cost between two releases with a confidence interval behind every verdict.

# exits 1 only when the candidate release actually regressed
PROVA_API_KEY=prv_... npx @cobound/prova-sdk prova-eval \
  --app-id claims-agent --baseline "$LAST_GOOD_SHA" --candidate "$GIT_SHA"

Without --baseline/--candidate it lists the releases seen in the window. The same comparison is available as GET /api/v1/eval/compare for non-Node CI.

Vercel AI SDK

Wrap your model with provaMiddleware and every generateText / streamText call emits a signed model_call receipt with token usage, so cost is computed and signed server-side. Streaming calls are tapped, not buffered. Works with the ai package v5 and v6.

import { wrapLanguageModel } from 'ai';
import { openai } from '@ai-sdk/openai';
import { ProvaClient } from '@cobound/prova-sdk';
import { provaMiddleware } from '@cobound/prova-sdk/vercel';

const prova = new ProvaClient({ apiKey: process.env.PROVA_API_KEY! });
const model = wrapLanguageModel({
  model: openai('gpt-4o'),
  middleware: provaMiddleware(prova, { appId: 'my-agent' }),
});
// use `model` with generateText / streamText exactly as before

Telemetry is fire-and-forget: a failed ingest never breaks your model call. The ai package is an optional peer dependency, so the SDK installs cleanly without it.

Catch the loop as it forms

The handler 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). By default it also runs the same detection in-process and warns (console.warn) the moment a persistent loop forms, so you see it in real time rather than only later in the dashboard.

The default warns, it does not stop the run. A structural loop is also what a healthy planner/executor iteration looks like, and stopping every cycle would break agents that are working correctly. Pass breakOnLoop: true to upgrade the warning to a stop: the handler throws CoordinationLoopError and sets raiseError so LangChain.js propagates it and the run halts.

import { ProvaCallbackHandler, CoordinationLoopError } from '@cobound/prova-sdk';

const handler = new ProvaCallbackHandler(prova, {
  appId: 'claims-orchestrator',
  breakOnLoop: true,
});

try {
  await graph.invoke(inputs, { callbacks: [handler] });
} catch (e) {
  if (e instanceof CoordinationLoopError) {
    // e.match: { agents, born_at_step, persistence_steps, total_steps, total_agents }
    console.error('stopped a coordination loop across', e.match.agents);
  }
}

The detection is a faithful port of the canonical server-side detector, and is verified against it in CI, so a loop seen locally is the same loop an auditor sees in the receipt. For a runtime without LangChain callbacks, drive LoopGuard directly:

import { LoopGuard, CoordinationLoopError } from '@cobound/prova-sdk';

const guard = new LoopGuard(); // raiseOnDetect: true by default
for (const { node, reads, writes } of runAgent()) {
  guard.observe(node, reads, writes); // throws CoordinationLoopError on a persistent loop
}

Circuit breaker: stop runaway spend

budgetUsd and maxSteps are hard caps you set, so they stop the run by default (unlike loop detection, which warns). Combine them with breakOnLoop for one circuit breaker against runaway agents:

import { ProvaCallbackHandler, BoundaryViolationError } from '@cobound/prova-sdk';

const handler = new ProvaCallbackHandler(prova, {
  appId: 'claims-orchestrator',
  budgetUsd: 0.50,    // stop if the run's estimated spend exceeds $0.50
  maxSteps: 40,       // stop after 40 agent steps
  breakOnLoop: true,  // stop on a coordination loop
});

try {
  await graph.invoke(inputs, { callbacks: [handler] });
} catch (e) {
  if (e instanceof BoundaryViolationError) {
    console.error('circuit breaker tripped:', e.match.dimension);
  }
}

The handler attaches normalized token_usage to every model_call receipt so the server can compute and sign the canonical cost_usd. The in-process cost estimate (built-in catalog, override with setModelPrice) is used only to trip the budget locally.

Run it locally, no account

analyzeLocal(events) runs loop detection and cost estimation entirely in-process. No API key, no network. Pass the events the SDK emits and read the report. The loop algorithm matches the server, so a loop seen locally is the loop a signed receipt would report.

import { analyzeLocal } from '@cobound/prova-sdk';

const report = analyzeLocal(events);
// { events, steps, model_calls, models, estimated_cost_usd, loop }
if (report.loop) console.error('coordination loop:', report.loop.agents);

Migrate existing logs

CLI:

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

Or programmatically:

import { migrate, readNdjson } from '@cobound/prova-sdk/migrate';
import { createReadStream } from 'fs';

await migrate({
  client: prova,
  source: 'langfuse',
  rows: readNdjson(createReadStream('observations.ndjson', 'utf-8')),
  onProgress: (p) => console.error(p),
});

Supported sources: langsmith, langfuse, openai. Each row becomes a signed AIDecisionEvent with payload._migrated_from set to the source. Idempotency keys are derived from the source row id, so re-running the migration is safe.

Verify a receipt offline

import { verifyReceipt } from '@cobound/prova-sdk';

await verifyReceipt(receipt, { publicKeyPem: PUBLIC_KEY_PEM });

Or fetch the public key from the deployment automatically:

await verifyReceipt(receipt, { baseUrl: 'https://api.prova.cobound.dev' });