LangChain
Add a human approval checkpoint to any LangChain tool or chain step. Works with LangChain JS/TS and Python, including LangGraph.
Prerequisites
- Python 3.9+ or Node.js environment.
cheqpointSDK installed.- LangChain framework configured with custom tools.
Steps
- Initialize the Cheqpoint client with your
CQ_API_KEY. - Identify the sensitive tools in your LangChain toolkit (e.g.,
DatabaseWriteTool,StripeChargeTool). - Inside the tool's
_runor_arunmethod, callclient.request()with the tool's input parameters. - Block execution while waiting for the Cheqpoint response.
- If the response status is
approved, execute the original tool logic. - If the response status is
rejected, raise aValueErroror return a message to the LLM stating the action was blocked by human oversight.
Installation
bash
pip install cheqpoint langchain langchain-openaiSample request payload
json
{
"action": "db_delete_record",
"summary": "Agent attempting to delete record from 'customers' table",
"details": {
"table": "customers",
"record_id": "881",
"query": "DELETE FROM customers WHERE id = 881"
},
"justification": "User requested account deletion under GDPR right to be forgotten."
}Sample Cheqpoint response
json
{
"status": "approved",
"modifiedDetails": {
"query": "UPDATE customers SET deleted_at = NOW() WHERE id = 881"
},
"decisionNote": "Perform soft delete instead of hard delete for audit safety."
}Python — request_sync() in a LangChain tool
python
from cheqpoint import CheqpointClient
cheq = CheqpointClient(api_key="cq_live_...")
class DatabaseWriteTool(BaseTool):
name = "database_write"
description = "Execute a write query after human approval"
def _run(self, query: str, table: str, record_id: str) -> str:
result = cheq.request_sync(
action="db_delete_record",
summary=f"Agent attempting to delete record from '{table}' table",
details={"table": table, "record_id": record_id, "query": query},
justification="User requested account deletion under GDPR.",
timeout_ms=30_000, # poll up to 30 s
)
if result["status"] == "approved":
effective = result.get("modifiedDetails") or {"query": query}
return execute_query(effective["query"])
return f"Action blocked: {result.get('decisionNote', 'rejected by reviewer')}"Notes
You have full control over what data is passed into the details object to provide human reviewers with sufficient context.
Tips
Start by routing only high-risk or high-value actions to minimize friction while maintaining oversight.
Get your Connection Key at cheqpoint.co/signup.