Human-in-the-loop approval SDK for AI agents
Project description
cheqpoint
Official Python SDK for Cheqpoint — human-in-the-loop approval queues for AI agents.
python3 -m pip install cheqpoint
Verify installation
python3 -c "import cheqpoint; print(cheqpoint.__version__)"
[!TIP] macOS / Linux Troubleshooting: If you see
ModuleNotFoundErrorafter installing, ensure you are usingpython3 -m pip installto target the correct Python environment.
Quick start
import os
from cheqpoint import CheqpointClient
client = CheqpointClient(api_key=os.environ["CHEQPOINT_API_KEY"])
# Your agent calls this instead of executing directly.
# checkpoint() submits the request and waits for a human decision.
result = client.checkpoint(
type="refund",
risk_level="high",
summary="Refund $149 to sarah@example.com",
details={"userId": "usr_123", "amount": 149, "currency": "USD"},
justification="Double-charged on invoice #1821",
)
# effective_details returns modifiedDetails if set, else original details
stripe.refunds.create(**result.effective_details)
Constructor
CheqpointClient(
api_key: str, # Required. Your workspace API key.
base_url: str = "https://app.cheqpoint.co",
timeout: float = 300, # Default poll timeout in seconds
)
Methods
checkpoint(...) → CheckpointResult
Submit an action for review and block until a human decides.
| Parameter | Type | Default | Description |
|---|---|---|---|
type |
str |
required | Short label for the action (e.g. "refund", "email") |
risk_level |
"low" | "medium" | "high" |
required | Risk level of the action |
summary |
str |
required | One-sentence description shown to reviewers |
details |
dict |
required | Structured payload. Returned as-is (or modified) on approval |
justification |
str | None |
None |
Agent's reasoning shown to reviewers |
webhook_url |
str | None |
None |
URL for Cheqpoint to POST the decision to |
poll_interval |
float |
3 |
Seconds between status polls |
timeout |
float | None |
client default | Max seconds to wait |
Returns CheckpointResult when approved.
Raises RejectedError if rejected.
Raises TimeoutError if no decision within timeout.
@dataclass
class CheckpointResult:
id: str
status: str # "APPROVED"
details: dict # original payload
modified_details: dict | None # reviewer edits, if any
response_notes: str | None # reviewer's note
def effective_details(self) -> dict:
"""Returns modified_details if set, else original details."""
create_request(...) → dict
Fire-and-forget. Submits the request and returns immediately with {"id": "..."}. Pair with a webhook_url or poll manually with get_request.
get_request(request_id) → RequestStatus
Fetch the current status of a request.
@dataclass
class RequestStatus:
id: str
status: str # "PENDING" | "APPROVED" | "REJECTED"
type: str
risk_level: str
summary: str
details: dict
modified_details: dict | None
response_notes: str | None
webhook_delivered: bool
created_at: str
decided_at: str | None
Error handling
from cheqpoint import CheqpointClient, CheqpointError, RejectedError, TimeoutError
try:
result = client.checkpoint(...)
except RejectedError as e:
print(f"Rejected: {e.response_notes}")
except TimeoutError as e:
print(f"Timed out for request {e.request_id}")
except CheqpointError as e:
print(f"API error {e.status_code}: {e}")
Examples
With webhook (recommended for production)
result = client.create_request(
type="db-write",
risk_level="medium",
summary="Delete user account usr_456",
details={"userId": "usr_456", "reason": "GDPR deletion request"},
webhook_url="https://yourapp.com/webhook/cheqpoint",
)
request_id = result["id"]
# Store request_id — your Flask/Django webhook handler receives the decision
Manual polling
result = client.create_request(type="email", risk_level="low", ...)
request_id = result["id"]
# Check later
status = client.get_request(request_id)
if status.status == "APPROVED":
payload = status.modified_details or status.details
send_email(**payload)
LangChain agent tool
from langchain_core.tools import tool
@tool
def issue_refund(user_id: str, amount: float, reason: str) -> str:
"""Issue a refund to a customer. Requires human approval."""
result = client.checkpoint(
type="refund",
risk_level="high",
summary=f"Refund ${amount} to user {user_id}",
details={"userId": user_id, "amount": amount, "reason": reason},
)
payload = result.effective_details
return f"Refund approved for ${payload['amount']}"
CrewAI tool
from crewai_tools import BaseTool
class CheqpointApprovalTool(BaseTool):
name: str = "Request Human Approval"
description: str = "Submit a risky action for human approval before executing."
def _run(self, action_type: str, summary: str, details: dict) -> str:
result = client.checkpoint(
type=action_type,
risk_level="high",
summary=summary,
details=details,
)
return f"Approved. Effective details: {result.effective_details}"
Flask webhook handler
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route("/webhook/cheqpoint", methods=["POST"])
def cheqpoint_webhook():
data = request.get_json()
status = data["status"]
payload = data.get("modifiedDetails") or data["details"]
if status == "APPROVED":
process_action(payload)
return jsonify({"ok": True}), 200
Requirements
- Python 3.9+
requestslibrary
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cheqpoint-0.1.1.tar.gz.
File metadata
- Download URL: cheqpoint-0.1.1.tar.gz
- Upload date:
- Size: 11.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bab48bd6ec3392b4bc69f08e7074e94ca4812e7368cbb2ccfcadbadc1275f053
|
|
| MD5 |
d9cb6032b9de7f90e04c58b4bad7ab15
|
|
| BLAKE2b-256 |
865cace9a39a3536fc3405a88af8d5f4a0ce0dcb8ed4611addbcc3ce373f4d75
|
File details
Details for the file cheqpoint-0.1.1-py3-none-any.whl.
File metadata
- Download URL: cheqpoint-0.1.1-py3-none-any.whl
- Upload date:
- Size: 11.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b0d0c23e9a14fda0193118630c79fbdcf526a60bb3021831b210e1a8904dfb69
|
|
| MD5 |
67ccf251efd7d47ad87f79c4dd55a854
|
|
| BLAKE2b-256 |
34a6755f1bdb13e802a2236aca94c4d073c2cabe59feee28ae045ff3e9fcfcb2
|