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.

python
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=100

LangGraph (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.

python
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.

python
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

python
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

typescript
// 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,
})