Integrations
Integration Examples
Prova is a single POST call. These examples show how to wrap it into real pipelines — LangGraph, CrewAI, and generic Python and Node.js.
GitHub Actions — gate CI on reasoning validity
uses: cobound/prova-action@v1 — one YAML block blocks INVALID reasoning from reaching production. Writes a Step Summary, posts a PR comment, and emits outputs for downstream steps.
MCP server — let any agent verify its own reasoning before answering
pip install prova-mcp — drop into Claude Code, Cursor, Windsurf, Zed, or ChatGPT desktop. Tools for verify, fetch certificate, download Lean proof, and a local kernel-check that closes the trust loop without depending on Prova's servers.
Structured input for agent frameworks
If your agent framework already tracks an explicit graph of claims and dependencies, skip extraction entirely by posting to /verify/structured. This is faster, always returns confidence_score: 100, and is the recommended path for LangGraph, CrewAI, and custom orchestrators that maintain structured state.
import requests
PROVA_API_KEY = "your-api-key"
def verify_from_langgraph_state(state: dict) -> dict:
"""Build a Prova argument graph from a LangGraph state dict and verify it."""
# Map your state fields to Prova node types
nodes = [
{"id": "claim-1", "type": "premise", "text": state["evidence"]},
{"id": "claim-2", "type": "claim", "text": state["intermediate_finding"]},
{"id": "claim-3", "type": "conclusion", "text": state["final_decision"]},
]
edges = [
{"from": "claim-1", "to": "claim-2"},
{"from": "claim-2", "to": "claim-3"},
]
response = requests.post(
"https://api.prova.cobound.dev/verify/structured",
headers={"Authorization": f"Bearer {PROVA_API_KEY}"},
json={
"nodes": nodes,
"edges": edges,
"retain": True,
"metadata": {"pipeline": "langgraph-agent"},
},
timeout=30,
)
return response.json() # always confidence_score=100LangGraph (Python)
Add Prova verification as a node in your LangGraph graph. When an agent produces a reasoning chain, pipe it through Prova before acting on the decision.
import requests
from langgraph.graph import StateGraph
PROVA_API_KEY = "your-api-key"
def prova_verify_node(state):
"""LangGraph node: verify agent reasoning before acting."""
reasoning = state.get("agent_reasoning", "")
if not reasoning:
return state
response = requests.post(
"https://api.prova.cobound.dev/verify",
headers={"Authorization": f"Bearer {PROVA_API_KEY}"},
json={
"reasoning": reasoning,
"retain": True,
"metadata": {
"pipeline": "langgraph-agent",
"node": state.get("current_node", "unknown"),
},
},
timeout=30,
)
cert = response.json()
return {
**state,
"prova_verdict": cert["verdict"],
"prova_certificate_id": cert["certificate_id"],
"prova_certificate_url": cert["certificate_url"],
# Optionally block on INVALID:
"reasoning_valid": cert["verdict"] == "VALID",
}
# Add to your graph
builder = StateGraph(YourState)
builder.add_node("agent", your_agent_node)
builder.add_node("verify_reasoning", prova_verify_node)
builder.add_node("act", your_action_node)
builder.add_edge("agent", "verify_reasoning")
builder.add_conditional_edges(
"verify_reasoning",
lambda s: "act" if s["reasoning_valid"] else "reject",
)
graph = builder.compile()CrewAI (Python)
Wrap a CrewAI task result with Prova verification using a custom callback.
import requests
from crewai import Task, Crew, Agent
def verify_with_prova(task_output: str, task_name: str = "") -> dict:
"""Verify CrewAI task reasoning output with Prova."""
resp = requests.post(
"https://api.prova.cobound.dev/verify",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={
"reasoning": task_output,
"metadata": {"task": task_name, "pipeline": "crewai"},
},
timeout=30,
)
return resp.json()
# After task execution:
crew = Crew(agents=[...], tasks=[...])
result = crew.kickoff()
cert = verify_with_prova(result.raw, task_name="final_recommendation")
print(f"Verdict: {cert['verdict']}")
print(f"Certificate: {cert['certificate_url']}")Generic Python pipeline
import requests
import logging
logger = logging.getLogger(__name__)
class ProvaVerifier:
"""Drop-in Prova verifier for any Python AI pipeline."""
def __init__(self, api_key: str, pipeline_name: str = ""):
self.api_key = api_key
self.pipeline_name = pipeline_name
self.base_url = "https://api.prova.cobound.dev"
def verify(
self,
reasoning: str,
domain: str | None = None,
retain: bool = True,
raise_on_invalid: bool = False,
) -> dict:
resp = requests.post(
f"{self.base_url}/verify",
headers={"Authorization": f"Bearer {self.api_key}"},
json={
"reasoning": reasoning,
"retain": retain,
"metadata": {
"pipeline": self.pipeline_name,
**({"domain": domain} if domain else {}),
},
},
timeout=30,
)
resp.raise_for_status()
cert = resp.json()
logger.info(
"Prova: %s | cert=%s | confidence=%d",
cert["verdict"],
cert["certificate_id"],
cert["confidence_score"],
)
if raise_on_invalid and cert["verdict"] == "INVALID":
raise ValueError(
f"Reasoning failed Prova check: {cert['failure']['type']} "
f"at {cert['failure']['location']}. "
f"Certificate: {cert['certificate_url']}"
)
return cert
# Usage
verifier = ProvaVerifier(api_key="sk-...", pipeline_name="loan-approvals")
cert = verifier.verify(
reasoning=ai_output,
domain="financial",
raise_on_invalid=True, # blocks invalid reasoning from reaching decision
)Node.js / TypeScript pipeline
// prova.ts — drop-in verifier for Node.js pipelines
interface ProvaOptions {
apiKey: string
pipeline?: string
domain?: 'medical' | 'legal' | 'financial' | 'code' | 'general'
retain?: boolean
raiseOnInvalid?: boolean
}
export async function verifyReasoning(
reasoning: string,
options: ProvaOptions
): Promise<{ valid: boolean; certificateUrl: string; certificateId: string }> {
const response = await fetch('https://api.prova.cobound.dev/verify', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${options.apiKey}`,
},
body: JSON.stringify({
reasoning,
retain: options.retain ?? true,
metadata: {
pipeline: options.pipeline ?? 'node-pipeline',
...(options.domain ? { domain: options.domain } : {}),
},
}),
})
if (!response.ok) {
const err = await response.json()
throw new Error(`Prova API error: ${err.message}`)
}
const cert = await response.json()
if (options.raiseOnInvalid && cert.verdict === 'INVALID') {
throw new Error(
`Reasoning failed Prova check: ${cert.failure?.type} — ${cert.certificate_url}`
)
}
return {
valid: cert.verdict === 'VALID',
certificateUrl: cert.certificate_url,
certificateId: cert.certificate_id,
}
}
// Usage in your pipeline:
const { valid, certificateUrl } = await verifyReasoning(agentOutput, {
apiKey: process.env.PROVA_API_KEY!,
pipeline: 'contract-review',
domain: 'legal',
raiseOnInvalid: true,
})