Praxa documentation
Everything to wire up audit logging, understand the tier ladder, and prove — cryptographically, not just by our word — that a chain wasn’t tampered with.
Quickstart by SDK
Pick the SDK you already use. Every wrapper posts one event per call to POST /api/v1/events in the background — the customer’s own call is never blocked or broken by an audit-log failure.
Vercel AI SDK
npm install @piposlabs/praxa-vercel-ai
import { generateText } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
import { wrapWithAudit } from "@piposlabs/praxa-vercel-ai";
const model = wrapWithAudit(anthropic("claude-sonnet-4-6"), {
agentId: "agt_xxxxxxxxxxxxxxxxxxxx",
apiKey: process.env.PRAXA_API_KEY!,
});
const { text } = await generateText({ model, prompt: "Hello" });
// -> audit event posted to Praxa in the backgroundOpenAI Node SDK
npm install @piposlabs/praxa-openai-sdk
import OpenAI from "openai";
import { wrapChatCompletionsCreate } from "@piposlabs/praxa-openai-sdk";
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const auditedCreate = wrapChatCompletionsCreate(openai, {
agentId: "agt_xxxxxxxxxxxxxxxxxxxx",
apiKey: process.env.PRAXA_API_KEY!,
});
const completion = await auditedCreate({
model: "gpt-4o",
messages: [{ role: "user", content: "Hello" }],
});Anthropic Node SDK
npm install @piposlabs/praxa-anthropic-sdk
import Anthropic from "@anthropic-ai/sdk";
import { wrapMessagesCreate } from "@piposlabs/praxa-anthropic-sdk";
const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
const auditedCreate = wrapMessagesCreate(anthropic, {
agentId: "agt_xxxxxxxxxxxxxxxxxxxx",
apiKey: process.env.PRAXA_API_KEY!,
});
const msg = await auditedCreate({
model: "claude-sonnet-4-6",
max_tokens: 1000,
messages: [{ role: "user", content: "Hello" }],
});LangChain (Node/TS)
npm install @piposlabs/praxa-langchain
import { ChatOpenAI } from "@langchain/openai";
import { createPraxaCallbackHandler } from "@piposlabs/praxa-langchain";
const praxaCallback = createPraxaCallbackHandler({
agentId: "agt_xxxxxxxxxxxxxxxxxxxx",
apiKey: process.env.PRAXA_API_KEY!,
});
const model = new ChatOpenAI({ modelName: "gpt-4o", callbacks: [praxaCallback] });
await model.invoke([{ role: "user", content: "Hello" }]);Don’t see your stack? Call POST /api/v1/events directly from anything that can POST JSON — see the request shape in the Article 12 implementation guide.
Concepts
| Term | Meaning |
|---|---|
| Agent | A logical grouping for one AI feature in your app — e.g. “Customer Support Bot”. Register once, get a UUID; every event references it. |
| Event | A single AI-agent decision: input + output + model + rationale + downstream effects, SHA-256 chained to the previous event for the same agent. |
| Chain | The append-only hash chain of events per agent. Any tampering breaks continuity from that point forward and is detectable by re-verifying. |
| Anchor | A periodic, Ed25519-signed snapshot of the chain head, so an auditor can prove your chain state at time T without trusting our runtime. |
| Report | A compliance evidence pack generated from your real events: NIST AI RMF / EU AI Act Annex IV / SOC 2 evidence. |
Tier limits
| Free | Starter | Business | Enterprise | |
|---|---|---|---|---|
| Price | $0 | $79/mo | $249/mo | Contact sales |
| Agents | 1 | 5 | 25 | Unlimited |
| Events / month | 10,000 | 100,000 | 1,000,000 | Unlimited |
| Retention | 30 days | 1 year | 7 years | Custom |
| Webhook delivery | — | ✓ | ✓ | ✓ |
| NIST AI RMF report | — | ✓ | ✓ | ✓ |
| EU AI Act Annex IV / SOC 2 kit | — | — | ✓ | ✓ |
POST /api/v1/events returns 429 once you hit your monthly cap, with X-RateLimit-* headers. Nothing already ingested is dropped. See full pricing for plan details.
Verifying a chain (standalone)
Every event’s entry_hash is a SHA-256 over the event payload plus the previous event’s hash, so tampering anywhere breaks continuity from that point forward. You — or your auditor — can verify any exported chain without trusting Praxa’s runtime, using the open-source, MIT-licensed @piposlabs/praxa-verify (zero runtime dependencies, ~150 lines — read it, audit it, run it on your own export):
# Export your chain, then verify locally — no network call needed:
npx @piposlabs/praxa-verify chain-export.json
# Or pipe it straight from the API:
curl -H "Authorization: Bearer $PRAXA_API_KEY" \
"https://praxa.piposlab.com/api/v1/agents/<id>/export" \
| npx @piposlabs/praxa-verify --stdinExit code 0 = chain verified, 1 = tampering detected. Anchors are additionally signed with Ed25519 — verify an anchor signature against our public key at /api/v1/pubkey.
Outbound webhooks
Starter tier and above: subscribe a URL at /settings/webhooks to receive every successful event ingest as an HMAC-signed POST — mirror your audit trail into Splunk, Datadog, or your own BI stack without polling the API. The signature format is Stripe-compatible:
import { createHmac, timingSafeEqual } from "node:crypto";
function verifyPraxaWebhook(body: string, header: string, secret: string) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
const expected = createHmac("sha256", secret)
.update(`${parts.t}.${body}`)
.digest("hex");
if (!timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1))) {
throw new Error("signature_mismatch");
}
}Retention & purge
Retention is customer-controlled per agent (Business+) or per tenant (all tiers), from 1 day to forever. Praxa never hard-deletes a chain entry — at purge time only the payload (input_payload / output_payload) is scrubbed; the hash-chain bookkeeping (entry_hash, previous_hash, chain_position) is preserved forever, so the chain keeps verifying end-to-end even after payloads age out.
Support
Email alex@piposlab.com for anything that needs a human — integration help, a verification question, or a false-positive report on praxa-verify.