Skip to main content

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.

Installation

pip install cheqpoint

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+
  • requests library

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

cheqpoint-0.1.0.tar.gz (10.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cheqpoint-0.1.0-py3-none-any.whl (10.7 kB view details)

Uploaded Python 3

File details

Details for the file cheqpoint-0.1.0.tar.gz.

File metadata

  • Download URL: cheqpoint-0.1.0.tar.gz
  • Upload date:
  • Size: 10.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.7

File hashes

Hashes for cheqpoint-0.1.0.tar.gz
Algorithm Hash digest
SHA256 5c4896bb6deeaba784954640c21bcc611f08c7e451471c65f69143228c032eae
MD5 5161b95a851693ae9346de345c1a10f5
BLAKE2b-256 d016eebe8a5623f2affaf7222e0c5dc077cd70566fcbbbbfec826f31557a12f1

See more details on using hashes here.

File details

Details for the file cheqpoint-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: cheqpoint-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 10.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.7

File hashes

Hashes for cheqpoint-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 437a80ecffc9bc0bdec8a89bc3cc237567faa5a22910acd828465c02e80ea6b6
MD5 f9b23956fa40ef89d4acba71d4b9929c
BLAKE2b-256 986e91cc34232bb13515df41d01ac8c69a383bd2ed982e73d323c2f103bb5374

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page