SDK Guide¶
CRP ships a progressive-disclosure SDK (SPEC-032). Start with one line of code and unlock deeper control only when you need it. No rewrites. No architecture changes.
Who this is for
- Developers who want governance without learning a new API
- Compliance teams who need audit trails and risk scores
- Engineers who want full control over routing, safety, and provenance
Installation¶
Verify the install:
Need a specific provider?
CRP works with OpenAI, Anthropic, Google Gemini, Mistral, Cohere, Ollama, LM Studio, vLLM, and any OpenAI-compatible endpoint. Install the provider SDK you already use -- CRP does not replace it.
Level 0 -- Governance (Zero New Concepts)¶
Change one line and every call is governed, risk-scored, and audited.
from openai import OpenAI
client = OpenAI(
api_key="your-provider-key",
base_url="https://gateway.crprotocol.io/v1",
)
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Hello"}],
)
# Governance signals are attached automatically
print(response.crp.risk) # LOW | MEDIUM | HIGH | CRITICAL
print(response.crp.grounded) # True | False
print(response.crp.compliant) # True | False
That's it
No new imports. No new concepts. Your existing code stays the same.
Understanding the .crp object¶
Every response carries a governance summary. Here is what each field means:
| Field | Type | Meaning |
|---|---|---|
risk |
str |
Overall risk level: LOW, MEDIUM, HIGH, CRITICAL |
grounded |
bool |
Whether the response is anchored to provided context |
compliant |
bool |
Whether the response passes configured safety policies |
fabrications |
int |
Number of unsupported claims detected |
chain_valid |
bool |
Whether the audit chain is intact |
injection_detected |
bool |
Whether prompt-injection patterns were found |
pii_detected |
bool |
Whether personal data was detected in output |
safety_budget_remaining |
float |
Remaining safety budget (0.0--1.0) |
Handle high-risk responses
Level 1 -- Quality (One New Concept: "knowledge")¶
Give CRP your documents, then ask questions with grounded, coherent answers.
import crp
client = crp.Client()
# Ingest documents, directories, URLs, or raw strings
client.ingest("./docs/")
client.ingest("https://example.com/spec.pdf")
# Ask questions -- CRP retrieves, reasons, and cites sources
answer = client.ask("Write a deployment guide")
print(answer.text) # The generated response
print(answer.quality) # S | A | B | C | D
print(answer.complete) # Did it cover the whole task?
print(answer.sources) # [{title, doc_id, used_facts, relevance_score}]
Source attribution¶
Each source tells you exactly where the information came from:
for src in answer.sources:
print(f"{src.title} (relevance: {src.relevance_score:.2f})")
print(f" Used {src.used_facts} facts from doc {src.doc_id}")
What happens behind the scenes
ask() runs the full CRP quality pipeline invisibly:
1. CDR -- Contextual Document Retrieval finds relevant chunks
2. CDGR -- Cross-Document Graph Reasoning connects facts across sources
3. STL -- Semantic Topic Labelling positions the query in knowledge space
4. Continuation -- Multi-turn coherence maintenance
5. Verification -- Grounding check against source documents
Level 2 -- Control¶
Depth control¶
Control how thorough the response should be:
# quick | standard | thorough | exhaustive
answer = client.ask("Explain transformers", depth="thorough")
| Depth | Use when | Typical latency |
|---|---|---|
quick |
Simple FAQs, low stakes | Fast |
standard |
General tasks (default) | Normal |
thorough |
Complex analysis, research | Slower |
exhaustive |
Critical decisions, compliance | Slowest |
Tool registration¶
Register Python functions as tools. CRP can call them automatically when needed.
@client.tool
def search_docs(query: str) -> str:
"""Search internal documentation."""
return vector_db.search(query)
@client.tool
def get_metrics(service: str) -> dict:
"""Get service health metrics."""
return monitoring.get(service)
# CRP may call search_docs("auth service") automatically
answer = client.ask("What does our auth service do?")
Reasoning transparency¶
Inspect how the answer was built:
answer = client.ask("Should we use microservices?")
print(answer.how_it_was_built) # STL operation sequence
print(answer.open_questions) # Gaps identified
print(answer.decisions) # Trade-offs made by the CSO
Use this for compliance documentation
how_it_was_built and decisions give you an audit-ready explanation of why the model produced a specific output. Save these for regulatory evidence packs.
Configuration¶
CRP loads crp.config.yaml automatically if it exists in the working directory.
# crp.config.yaml
provider:
name: openai
api_key: ${OPENAI_API_KEY}
safety:
profile: balanced
halt_on_critical: true
grounding_threshold: 0.8
audit:
destination: comply.crprotocol.io
webhook_secret: ${WEBHOOK_SECRET}
context:
mode: full
max_sources: 10
Environment variable substitution
Values prefixed with ${} are resolved from environment variables at load time.
Safety profiles¶
| Profile | Description | Best for |
|---|---|---|
permissive |
Minimal intervention | Internal tools, low-risk domains |
balanced |
Default protection | Most production workloads |
strict |
Halt on MEDIUM+ risk | Financial, legal, high-stakes |
medical |
HIPAA-aligned | Healthcare applications |
financial |
SOX-aligned | Banking, trading, accounting |
Override per-request:
Session Persistence¶
CRP sessions survive restarts. Pass a session handle to resume context:
import crp
client = crp.Client()
# Start a session
response = client.complete("My name is Alice")
session_id = client.session.id # Save this
# Later -- or in another process
client2 = crp.Client(session=session_id)
response2 = client2.complete("What is my name?")
# "Alice" -- context is preserved
Session storage
By default sessions are in-memory. For production, configure Redis or PostgreSQL in crp.config.yaml.
Streaming¶
Stream responses for real-time UIs:
import crp
client = crp.Client()
for chunk in client.complete("Tell me a story", stream=True):
print(chunk.text, end="", flush=True)
if chunk.crp.risk == "CRITICAL":
print("\n[HALTED -- critical risk detected]")
break
Each chunk carries partial governance signals, so you can interrupt mid-generation if risk escalates.
Multi-turn Conversations¶
Build conversational agents with persistent context:
import crp
client = crp.Client()
# Turn 1
r1 = client.ask("What is the EU AI Act?")
print(r1.text)
# Turn 2 -- context is automatic
r2 = client.ask("What are the penalties for non-compliance?")
print(r2.text)
# Turn 3 -- references earlier turns
r3 = client.ask("How does that compare to GDPR fines?")
print(r3.text)
CLI¶
The crp CLI provides governance tools without writing code:
# Scan a codebase for ungoverned AI calls
python -m crp scan --paths ./src --format sarif
# Validate a configuration file
python -m crp validate crp.config.yaml
# Run benchmarks
python -m crp benchmark --suite conformance
# Export audit trail
python -m crp audit --session <id> --format json
See the CLI Guide for full reference.
Error Handling¶
CRP uses graceful degradation. If a safety check fails, you get a governed response instead of a raw exception:
import crp
client = crp.Client()
response = client.complete("Generate a medical diagnosis")
if response.finish_reason == "error":
print("Dispatch failed -- check logs")
print(f"Risk level: {response.crp.risk}")
else:
print(response.text)
Always check .crp.risk
Even when finish_reason is stop, the response may be HIGH or CRITICAL risk. Your application logic should decide whether to show, flag, or block the output.
Next Steps¶
- Quickstart -- Get running in 5 minutes
- CLI Reference -- Command-line tools
- Session Persistence -- Deep-dive on multi-turn state
- Streaming -- Real-time response handling
- Sidecar -- Deploy as a Kubernetes sidecar
API Reference¶
crp.Client¶
class CRPClient:
def __init__(
self,
provider: LLMProvider | None = None,
config: CRPConfig = CRPConfig(),
safety: str | dict = "balanced",
depth: str = "auto",
)
Methods¶
| Method | Level | Description |
|---|---|---|
complete(prompt, ...) |
0 | Single-turn completion with governance |
ask(question, ...) |
1 | Multi-turn quality-aware query |
ingest(path) |
1 | Ingest documents into CKF |
tool(fn) |
2 | Decorator to register a callable tool |
call_tool(name, ...) |
2 | Execute a registered tool |
Response Types¶
CRPCompletionResponse (Level 0)
- text: str -- Generated text
- crp: CRPResponseMeta -- Governance summary
- finish_reason: str -- stop | error | halted
- usage: dict -- Token counts
CRPAskResponse (Level 1--2)
- All fields from CRPCompletionResponse, plus:
- quality: str -- S | A | B | C | D
- sources: list[SourceAttribution] -- Cited documents
- complete: bool -- Whether the whole task was covered
- how_it_was_built: str -- Reasoning trace
- open_questions: list[str] -- Identified gaps
- decisions: list[dict] -- Trade-off log
For the full progressive-disclosure specification, see
SPECS_5_06_2026_CRP_v4/specs/CRP-SPEC-032-developer-experience.md.