Overview

Agent framework integrations

Installation#

Primary — TypeScript runtime guard + SDK:

npm install @coderifts/agent-guard @coderifts/sdk

Secondary — Python SDK:

pip3 install coderifts-sdk

Full mode contract (analyze vs authorize): Decision Spec v2. MCP clients: MCP Integration.

TypeScript — withCodeRifts (canonical)#

Wrap the OpenAI (or any) tool table so mutating tools cannot run without a CodeRifts authorize preflight. The host must register only the returned tools array. Operation is required (receipts bind to it).

import { withCodeRifts } from '@coderifts/agent-guard';
import { CodeRifts } from '@coderifts/sdk';
 
const client = new CodeRifts({ apiKey: process.env.CODERIFTS_API_KEY });
 
// Register ONLY tools from the returned table — anything else bypasses the guard.
const { tools } = withCodeRifts({
  tools: rawOpenAITools,
  client,
  operation: 'merge',       // required: merge | deploy | publish | tool_call | …
  environment: 'production',
});
 
// When you call preflight yourself (e.g. MCP or REST twin), use the authorize wrapper:
const result = await client.authorizeChangeSet({
  context: { operation: 'merge' },
  artifacts: [{ id: 'api', type: 'openapi', before: baseSpec, after: headSpec }],
});
 
// Branch on execution_action only (authorize). Unknown values fail closed.
if (result.execution_action !== 'CONTINUE') {
  throw new Error(`halted: ${result.execution_action} (${result.decision})`);
}
 
// A valid signature is NOT authorization. currently_authorized lives on the
// verify-receipt response, not on the preflight result — check it before acting.
if (!result.chain_receipt) throw new Error('CodeRifts: authorize returned no chain_receipt to verify');
if (!result.decision_result) throw new Error('CodeRifts: missing decision_result');
 
const authz = await client.verifyReceipt(result.chain_receipt, {
  operation: 'merge',
  target_id: result.decision_result.artifact_digest ?? undefined,
  fingerprint: result.verdict_fingerprint,
  decision_result: result.decision_result,
});
 
if (authz.currently_authorized !== true) {
  throw new Error(`not authorized: ${authz.status ?? 'unknown'}`);
}

See also Agent Quickstart.

LangGraph (Python) — preflight node#

Secondary path. Authorize mode + branch on execution_action. For strongest prevention use TypeScript withCodeRifts above.

pip3 install coderifts-sdk langgraph
from langgraph.graph import StateGraph
from coderifts import CodeRifts
 
coderifts = CodeRifts(api_key="cr_live_...")
 
def preflight_node(state):
    result = coderifts.authorize_change_set(
        artifacts=[{
            "id": state["artifact_id"], "type": "openapi",
            "before": state["old_spec"], "after": state["new_spec"],
        }],
        context={"operation": "merge", "environment": "staging"},
    )
    action = result.execution_action
    if action != "CONTINUE":
        return {**state, "blocked": True, "reason": f"aborted: {action} (decision={result.decision})"}
    receipt = getattr(result, "chain_receipt", None)
    authz = coderifts.verify_receipt(
        receipt, operation="merge", environment=getattr(result, "environment", None),
        target_id=getattr(result.decision_result, "artifact_digest", None),
        fingerprint=getattr(result, "verdict_fingerprint", None),
        decision_result=result.decision_result.to_dict(),
    ) if receipt else None
    if getattr(authz, "currently_authorized", None) is not True:
        return {**state, "blocked": True, "reason": "receipt not currently_authorized"}
    return {**state, "blocked": False, "receipt": receipt}
 
builder = StateGraph(dict)
builder.add_node("preflight", preflight_node)
graph = builder.compile()

AutoGen — safe tool wrapper (Python)#

pip3 install coderifts-sdk pyautogen
from coderifts import CodeRifts
coderifts = CodeRifts(api_key="cr_live_...")
 
def safe_tool_call(artifact_id, old_spec, new_spec, tool_fn, *args, **kwargs):
    result = coderifts.authorize_change_set(
        context={"operation": "tool_call"},
        artifacts=[{"id": artifact_id, "type": "openapi", "before": old_spec, "after": new_spec}],
    )
    if result.execution_action != "CONTINUE":
        return f"BLOCKED: aborted execution_action={result.execution_action!r} (decision={result.decision})"
    receipt = getattr(result, "chain_receipt", None)
    authz = coderifts.verify_receipt(receipt, operation="tool_call",
        target_id=getattr(result.decision_result, "artifact_digest", None),
        fingerprint=getattr(result, "verdict_fingerprint", None),
        decision_result=result.decision_result.to_dict()) if receipt else None
    if getattr(authz, "currently_authorized", None) is not True:
        return "BLOCKED: receipt not currently_authorized"
    return tool_fn(*args, **kwargs)

CrewAI and LangChain (Python)#

CrewAI wraps a SafeAPITool class that authorizes on init and re-checks execution_action before every run; LangChain wraps the same authorize + verify sequence inside an @tool-decorated function. Both follow the identical pattern above: authorize_change_set → branch on execution_actionverify_receipt → check currently_authorized is True before executing.

pip3 install coderifts-sdk crewai        # CrewAI
pip3 install coderifts-sdk langchain-core  # LangChain

SDK surface (summary)#

Full field contract: Decision Spec v2.

Method Description Returns
preflight_change_set(..., preflight_mode=) preflight_mode required. authorize (with context.operation): branch on execution_action. analyze: risk only (analysis_outcome, may_execute:false) — not permission. mode-dependent
verify_receipt(token, ...) Verify a signed chain-receipt you already hold. A valid signature is not authorization by itself. currently_authorized, status, payload

Updated

Was this page helpful?