Metadata-Version: 2.4
Name: remembr-proof
Version: 0.3.0
Summary: Python SDK for the REMEMBR Proof Seal API — verify AI reasoning chains
Author-email: REMEMBR Council <hello@remembrrr.ai>
License: MIT
Project-URL: Homepage, https://remembrrr.ai
Keywords: ai,verification,proof,reasoning,llm,safety,audit
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Provides-Extra: agents
Requires-Dist: openai-agents; extra == "agents"

# remembr-proof

Python SDK for the REMEMBR Proof Seal API.

Verify AI outputs against any visible supporting trace, detect contradictions, and generate audit-ready certificates with a single function call.

For the HTTP-first walkthrough, see `../../docs/proof-seal-quickstart.md`.
For the canonical API acceptance boundary, see `../../PROOF_SEAL_API_CONTRACT.md`.

## Install

```bash
pip install remembr-proof
```

## Quick Start

```python
from remembr_proof import ProofSeal

seal = ProofSeal(api_key="rp_live_YOUR_KEY")

cert = seal.verify(
    output="Employees must complete security awareness training every year.",
    task_type="policy",
    retrieved_context=[
        {
            "id": "policy-7.2",
            "title": "Security Awareness Policy",
            "content": "All employees must complete security awareness training annually.",
        }
    ],
    citations=[
        {
            "source_id": "policy-7.2",
            "quote": "All employees must complete security awareness training annually.",
            "claim": "Training is required every year",
        }
    ],
)

print(cert.verdict)      # "verified"
print(cert.confidence)   # 0.92
print(cert.support.support_score)  # 1.0
print(cert.contradictions)  # []

# Output-only calls are accepted, but the SDK does not pretend certainty
# when no visible trace is supplied.
output_only = seal.verify(
    output="Employees must complete security awareness training every year.",
    task_type="policy",
)
print(output_only.verdict)  # "insufficient_evidence"
print(output_only.insufficient_evidence_reasons)  # ["missing_visible_support"]

# Optional: request the shadow extractor report for comparison/debugging
shadow_cert = seal.verify(
    output="Employees must complete security awareness training every year.",
    task_type="policy",
    reasoning_steps=[
        {
            "role": "assistant",
            "content": "Security policy requires annual training.",
            "claims": ["Training is annual"],
            "evidence": ["Policy 7.2"],
            "confidence": 0.9,
        },
    ],
    shadow_extraction=True,
)

print(shadow_cert.shadow_extractor_status)  # "success" | "skipped" | "error"
if shadow_cert.shadow_reasoning_integrity:
    print(shadow_cert.shadow_reasoning_integrity.integrity_score)
if shadow_cert.shadow_extractor_error:
    print(shadow_cert.shadow_extractor_error)

# Check usage
usage = seal.get_usage()
print(f"Today: {usage.today_count}/{usage.daily_limit}")
```

API keys use the `rp_` family of prefixes. Self-serve trial keys use
`rp_free_`, paid pilot keys use `rp_live_`, and founder keys use
`rp_founder_`.

## Policy And Shadow Extraction

`reasoning_steps` is optional, but stronger verdicts require visible support.
If you only send the final output, Proof Seal will usually return
`insufficient_evidence` instead of a strong verification verdict.

For high-trust task types such as `policy`, `legal_internal`, and
`finance_ops`, `verified` is stricter than a generic confidence label. In
those workflows, Proof Seal will not return `verified` if unresolved
unsupported claims remain after visible-evidence reconciliation.

When a request resolves to `insufficient_evidence`, the certificate also
includes machine-readable `insufficient_evidence_reasons`. The SDK exports the
canonical taxonomy as `INSUFFICIENT_EVIDENCE_REASONS` plus
`is_insufficient_evidence_reason()` so callers can branch on stable reason IDs
instead of ad-hoc strings:

- `missing_visible_support`
- `weak_support_present`
- `unsupported_claims_present`
- `missing_grounded_citations`
- `missing_successful_tool_call`

When a request resolves to `policy_rejected`, the certificate also includes
machine-readable `policy_rejection_reasons`. The SDK exports the canonical
taxonomy as `POLICY_REJECTION_REASONS` plus `is_policy_rejection_reason()`:

- `integrity_below_minimum`
- `support_below_minimum`
- `contradictions_present`
- `unsupported_claims_present`
- `missing_required_grounded_citations`
- `missing_required_successful_tool_call`
- `unsafe_content_detected`

```python
from remembr_proof import (
    INSUFFICIENT_EVIDENCE_REASONS,
    POLICY_REJECTION_REASONS,
    ProofSeal,
    is_insufficient_evidence_reason,
    is_policy_rejection_reason,
)

cert = seal.verify(
    output="Critical decision output.",
    task_type="policy",
    retrieved_context=[
        {"id": "policy-7.2", "content": "All employees must complete security awareness training annually."},
    ],
    citations=[
        {"source_id": "policy-7.2", "quote": "All employees must complete security awareness training annually."},
    ],
    policy={
        "min_support_score": 0.75,
        "require_grounded_citations": True,
    },
    shadow_extraction=True,
)

print(cert.is_policy_rejected)
print(cert.policy_violations)
print(POLICY_REJECTION_REASONS)
print(cert.shadow_extractor_status)
print(INSUFFICIENT_EVIDENCE_REASONS)

for reason in cert.policy_rejection_reasons:
    assert is_policy_rejection_reason(reason)

for reason in cert.insufficient_evidence_reasons:
    assert is_insufficient_evidence_reason(reason)
```

## Middleware (OpenAI / Anthropic)

```python
from openai import OpenAI
from remembr_proof import with_proof_seal

client = with_proof_seal(OpenAI(), api_key="rp_live_YOUR_KEY")

response = client.chat.completions.create(
    model="gpt-5.5",
    messages=[{"role": "user", "content": "Summarize the quarterly numbers."}],
)

print(response.proof_certificate.verdict)
print(response.proof_certificate.confidence)
```

## OpenAI Agents SDK

Install the optional agent dependency:

```bash
pip install "remembr-proof[agents]"
```

Wrap an OpenAI Agents SDK agent to verify the final output and visible run trace before your application trusts the result:

```python
from agents import Agent, function_tool
from remembr_proof import ProofSeal, VerifiedAgent

@function_tool
def lookup_policy(query: str) -> str:
    return "Security awareness training is annual."

agent = Agent(name="Policy researcher", tools=[lookup_policy])
seal = ProofSeal(api_key="rp_live_YOUR_KEY")
verified_agent = VerifiedAgent(
    agent,
    seal,
    task_type="policy",
    policy={"min_support_score": 0.75, "require_successful_tool_call": True},
)

result = verified_agent.run_sync("Can employees skip annual security training?")

print(result.final_output)
print(result.certificate.verdict)
print(result.is_verified)
```

`VerifiedAgent` keeps `openai-agents` as a soft dependency. Importing `remembr_proof` does not require it; the dependency is required only when `VerifiedAgent.run()` or `VerifiedAgent.run_sync()` is called.

## Perplexity Pro Search

Use `PerplexityClient` for Sonar API research and `VerifiedSearch` to verify the answer plus returned citations before trusting it:

```python
from remembr_proof import PerplexityClient, ProofSeal, VerifiedSearch

search = VerifiedSearch(
    PerplexityClient(api_key="pplx_YOUR_KEY"),
    ProofSeal(api_key="rp_live_YOUR_KEY"),
    task_type="research",
    policy={"require_grounded_citations": True, "reject_on_contradictions": True},
)

result = search.query("What changed in the market this week?")
print(result.answer)
print(result.verdict)
```

Perplexity output is external research, not proof. Store the returned Proof Seal certificate id and review unresolved contradictions before acting on the answer.

## Own Special Ability: Adversarial Synthesis

Use `AdversarialSynthesis` when you want REMEMBR to verify both a claim and its strongest challenge before reporting what survived:

```python
from remembr_proof import AdversarialSynthesis, ProofSeal

seal = ProofSeal(api_key="rp_live_YOUR_KEY")
synthesis = AdversarialSynthesis(seal)

result = synthesis.run_sync(
    claim="Enterprise AI spend will reach $297B by 2027.",
    evidence=[{"id": "src-1", "content": "AI spending projected at $297B by 2027."}],
    citations=[{"source_id": "src-1", "quote": "$297B by 2027", "claim": "$297B by 2027"}],
    task_type="research",
)

print(result.synthesis_verdict)
print(result.refined_confidence)
print(result.crux)
```

The public Worker packet for this ability is `GET /api/own-special-ability`; the admin advisory packet is `GET /api/admin/synthesis`.

## Real Client Use Cases

The repo includes concrete client workflow packets:

```bash
python examples/created-features/client-real-life-use-cases.py --dry-run
```

The dry run does not call the API. It shows the payloads for support QA, legal notice-period review, finance invoice checks, compliance policy answers, market research packets, and release notes gated on tool output.

Run live only after setting credentials and a base URL:

```bash
REMEMBR_PROOF_API_KEY=rp_live_YOUR_KEY \
REMEMBR_PROOF_BASE_URL=http://127.0.0.1:8787 \
python examples/created-features/client-real-life-use-cases.py --live
```

## Computer Code Runner

Use `CodeRunner` for local subprocess execution and `VerifiedCodeRunner` when you want Proof Seal to verify captured output as a tool result:

```python
from remembr_proof import CodeRunner, ProofSeal, VerifiedCodeRunner

runner = VerifiedCodeRunner(
    CodeRunner(timeout=10),
    ProofSeal(api_key="rp_live_YOUR_KEY"),
)

result = runner.run_python("print(2 + 2)")
print(result.stdout)
print(result.certificate.verdict if result.certificate else "unverified")
```

`CodeRunner` is not a sandbox. Run untrusted code in a container or VM and do not grant it access to secrets or private data.

## Pricing

| Tier | Base | Per Verification | Daily Limit | Monthly Limit | Rate Limit |
|------|------|-----------------|-------------|---------------|------------|
| Free | $0/mo | $0 | 100 | 2,000 | 10/min |
| Pro | $49/mo | $0.005 | 10,000 | 300,000 | 60/min |
| Scale | $299/mo | $0.003 | 100,000 | 3,000,000 | 300/min |
| Enterprise | Custom | $0.001 | 1,000,000 | 30,000,000 | 1,000/min |

## Error Handling

All API errors raise `VerificationError`. The `status_code` attribute holds the HTTP status:

```python
from remembr_proof import ProofSeal, VerificationError

seal = ProofSeal(api_key="rp_live_YOUR_KEY")

try:
    cert = seal.verify(output="...", task_type="policy")
except VerificationError as e:
    if e.status_code == 401:
        print("Invalid or revoked API key")
    elif e.status_code == 429:
        print("Rate limit or daily/monthly quota exceeded — back off and retry")
    elif e.status_code == 400:
        print(f"Bad request: {e}")
    else:
        print(f"API error {e.status_code}: {e}")
```

Connection failures (DNS, timeout) also raise `VerificationError` with `status_code = 0`.

The SDK has no built-in retry logic. For production use, wrap calls with your own exponential backoff on `429` and `5xx` responses.

## Timeouts

The default request timeout is **30 seconds**. Override it at construction time:

```python
seal = ProofSeal(api_key="rp_live_YOUR_KEY", timeout=60)
```

## Dependencies

The SDK uses the Python standard library only (`urllib`, `dataclasses`, `json`). No third-party packages are required.
