Install the SDK and point it at Lite or the proxy.
Copy, run, verify.
Each recipe now follows the same shape: choose when it applies, copy the smallest working setup, run the verification check, then confirm the proof row or operator state. Source repos still carry the full examples; this page keeps the integration path executable at a glance.
Start here when the app already calls Anthropic or OpenAI through a native SDK.
@clavenar/agent-sdk
Framework
Keep the orchestration layer
Pass the wrapped provider into LangChain, Vercel AI, Computer Use, or Realtime flows.
client: wrapped
Operator
Turn on the control plane
Configure Slack HIL, SAML, Postgres, Helm, and observe-to-enforce rollout.
HIL + Ledger + Identity
Audit
Export proof rows
Stream ledger evidence to Splunk, Datadog, or generic HTTP with per-sink cursors.
ledger egress
- Recipe matrix
- Agent integration pattern
- TypeScript SDK
- Python SDK
- LangChain
- Vercel AI SDK
- Anthropic Computer Use
- OpenAI Realtime
- Operator runbooks
- Slack HIL deep-link
- SAML / SSO setup
- Postgres-backed ledger
- Helm deployment
- Observe-mode rollout
- Audit egress
Cards include language, edition, expected setup time, prerequisite, and proof output so readers can pick the smallest useful path.
Wrap Anthropic or OpenAI clients; raise pending/deny exceptions in app code.
- Lang
- TS
- Edition
- Lite/full
- Time
- 10 min
- Proof
proxy.verdict
Async and sync clients, plus LangChain and LlamaIndex examples.
- Lang
- Python
- Edition
- Lite/full
- Time
- 10 min
- Proof
proxy.verdict
Pass a wrapped provider client through ChatAnthropic or ChatOpenAI.
- Lang
- TS/Python
- Edition
- Lite/full
- Time
- 15 min
- Proof
- correlation replay
Keep generateText and streamText flows while gating tool calls.
- Lang
- TS
- Edition
- Lite/full
- Time
- 15 min
- Proof
- stream verdict
Gate computer, editor, and shell actions with a policy rule.
- Lang
- TS
- Edition
- Full
- Time
- 20 min
- Proof
policy.evaluated
Inspect function-call frames before invoking realtime tool handlers.
- Lang
- TS/Python
- Edition
- Lite/full
- Time
- 20 min
- Proof
- frame correlation
Deep-link pending approvals into the console with blast-radius context.
- Prereq
- Slack webhook
- Edition
- Full
- Time
- 15 min
- Proof
hil.approved
Build SAML support and stamp operator NameID into HIL decisions.
- Prereq
- IdP metadata
- Edition
- Full
- Time
- 30 min
- Proof
decided_by
Use the HA ledger backend without changing hash-chain bytes.
- Prereq
- Postgres URL
- Edition
- Full
- Time
- 25 min
- Proof
/verify
Deploy proxy, Brain, Policy, HIL, Ledger, Identity, and console.
- Prereq
- Cluster
- Edition
- Full
- Time
- 30 min
- Proof
- readyz + verify
Run policies in shadow before flipping them to enforce.
- Prereq
- New policy
- Edition
- Lite/full
- Time
- 1 week
- Proof
would_deny
Stream ledger rows with per-sink cursors and downstream dedupe.
- Prereq
- Sink token
- Edition
- Full
- Time
- 20 min
- Proof
- entry UUID
No recipes match that filter.
Wrap, don't rewrite.
The wrap pattern fits every framework that ultimately calls an Anthropic or OpenAI client. The SDKs auto-detect shape from the method surface and stay invisible until a verdict needs to surface.
Wrap the provider client before the framework sees it.
Keep the correlation id and replay its ledger rows.
@clavenar/agent-sdk
Choose this when your app already calls @anthropic-ai/sdk or openai directly and you want the smallest control-plane change.
-
Copy
npm install @clavenar/agent-sdk @anthropic-ai/sdk export CLAVENAR_ENDPOINT=http://localhost:8088
-
Run
import Anthropic from '@anthropic-ai/sdk'; import { clavenarWrap } from '@clavenar/agent-sdk'; const client = clavenarWrap(new Anthropic(), { endpoint: process.env.CLAVENAR_ENDPOINT, onPolicyError: (event) => console.warn(event.correlation_id), }); const r = await client.messages.create({ model: 'claude-opus-4-7', tools: [{ name: 'refund.issue', input_schema: { type: 'object' } }], messages: [{ role: 'user', content: 'Issue the refund' }], });
-
Verify
curl "$CLAVENAR_ENDPOINT/audit/correlation/$CORRELATION_ID"
Allowed calls return the upstream SDK result plus a correlation id; denied calls raise a policy error; review calls raise/return a pending object that maps to hil.created.
Full recipes: clavenar-typescript-sdk/examples/.
clavenar-ai on PyPI
Choose this when Python owns the agent loop. Async and sync clients share the same verdict behavior, and ClavenarPending.resolve() blocks for the operator decision.
-
Copy
python -m pip install clavenar-ai anthropic export CLAVENAR_ENDPOINT=http://localhost:8088
-
Run
from anthropic import AsyncAnthropic from clavenar_agent_sdk import ClavenarPending, clavenar_wrap client = clavenar_wrap(AsyncAnthropic(), endpoint="http://localhost:8088") try: result = await client.messages.create( model="claude-opus-4-7", messages=[{"role": "user", "content": "Update the account"}], ) except ClavenarPending as pending: result = await pending.resolve(timeout=300)
-
Verify
curl "$CLAVENAR_ENDPOINT/audit/correlation/$CORRELATION_ID" \ | python -m json.tool
Review paths should show hil.created followed by hil.approved or hil.denied; deny paths should include the policy reason.
LangChain + LlamaIndex recipes live under clavenar-python-sdk/examples.
Wrap the underlying provider client.
Choose this when LangChain owns orchestration but provider calls still terminate in Anthropic or OpenAI clients.
import Anthropic from '@anthropic-ai/sdk'; import { clavenarWrap } from '@clavenar/agent-sdk'; import { ChatAnthropic } from '@langchain/anthropic'; const wrapped = clavenarWrap(new Anthropic(), { endpoint: 'http://localhost:8088' }); const model = new ChatAnthropic({ client: wrapped }); const answer = await model.invoke('Call refund.issue for ticket 123');
The LangChain call shape stays unchanged; Clavenar adds the correlation id and ledger rows around tool execution.
Full pattern: examples/langchain-js and Python examples under clavenar-python-sdk/examples.
Pass the wrapped client to the provider factory.
Choose this when generateText or streamText owns the app flow and you need tool calls gated without changing prompt code.
import Anthropic from '@anthropic-ai/sdk'; import { createAnthropic } from '@ai-sdk/anthropic'; import { generateText } from 'ai'; import { clavenarWrap } from '@clavenar/agent-sdk'; const client = clavenarWrap(new Anthropic(), { endpoint: 'http://localhost:8088' }); const anthropic = createAnthropic({ client }); const result = await generateText({ model: anthropic('claude-opus-4-7'), prompt: 'Run the tool' });
Streaming continues through the Vercel AI SDK; a denied or parked tool call returns the Clavenar verdict instead of invoking the side effect.
Full recipe: examples/vercel-ai.
Gate high-risk tool blocks.
Choose this when computer, str_replace_editor, or bash actions need policy checks by trust boundary before they touch the desktop or shell.
# policies/computer_use.rego package clavenar.authz deny[msg] { input.request.params.name == "computer" input.request.params.arguments.action == "screenshot" not input.attestation.zone == "trusted_desktop" msg := "computer screenshot outside trusted desktop" } review[msg] { input.request.params.name == "bash" contains(input.request.params.arguments.command, "rm ") msg := "shell mutation requires operator review" }
Denied desktop actions return 403 policy_denied; shell mutations park with 202 pending and produce policy.evaluated plus hil.created.
Full recipe + Rego snippet: examples/anthropic-computer-use.
Gate function-call frames before handlers run.
Choose this when the app receives WebSocket frames and invokes tool handlers locally. Inspect the completed function-call arguments before the side effect.
for await (const frame of realtime) { if (!isRealtimeFunctionCallDone(frame)) continue; const verdict = await inspectRealtimeFunctionCall(frame, { endpoint: 'http://localhost:8088/mcp', callbackUrl: 'https://agent.example/hil/callback', }); if (verdict.status === 'allow') await invokeTool(frame); if (verdict.status === 'pending') await waitForOperator(verdict.correlation_id); }
Each function-call frame receives a correlation id before the local handler runs; review frames wait for HIL instead of executing immediately.
Full recipe: examples/openai-realtime · Python flavour: clavenar-python-sdk/examples.
Every setup path has a verification and rollback signal.
The OSS edition is one binary; the multi-service edition splits Brain, Policy, HIL, Ledger, Identity, and Console into isolated services. These runbooks cover the extra operational surface.
Credential, cluster, sink, or IdP dependency needed before deploy.
HTTP check, metric, ledger row, or UI state that proves the recipe worked.
The fastest safe reversal when a dependency or config is wrong.
Approve in-channel.
Choose this when operators already triage in Slack but still need the console for blast radius and history before deciding.
Prerequisites
- Slack incoming webhook URL.
- Reachable
CLAVENAR_CONSOLE_URL. - HIL service token configured for proxy-created pendings.
Steps
CLAVENAR_HIL_SLACK_WEBHOOK_URL=https://hooks.slack.com/services/... CLAVENAR_CONSOLE_URL=https://console.clavenar.com
Verify
Create a review-tier request and confirm Slack receives a pending card with an Open in console link.
Rollback / failure signal
Remove the webhook env var to stop Slack posts. Missing cards usually mean the webhook rejected the payload or the HIL service never saw hil.created.
Approving from the console after the Slack deep-link produces hil.approved with the operator identity and note.
Source: clavenar-hil README · Slack section.
Build with --features saml.
Choose this when operator identity must come from an enterprise IdP and HIL decisions need a durable SAML NameID in the audit chain.
Prerequisites
- SAML IdP metadata URL.
- Group names mapped to Admin, Approver, and Viewer roles.
- Console image built with SAML feature support.
Steps
docker build \ --build-arg CLAVENAR_CARGO_FEATURES=saml \ -t clavenar-console:saml . CLAVENAR_CONSOLE_AUTH_MODE=saml CLAVENAR_CONSOLE_SAML_METADATA_URL=https://<idp>/metadata CLAVENAR_CONSOLE_SAML_GROUP_ATTR=Group CLAVENAR_CONSOLE_OIDC_GROUP_ADMIN=clavenar-admin CLAVENAR_CONSOLE_OIDC_GROUP_APPROVER=clavenar-approver CLAVENAR_CONSOLE_OIDC_GROUP_VIEWER=clavenar-viewer
Verify
Browser flow is GET /auth/saml/login to POST /auth/saml/acs; approve a HIL item and replay the correlation id.
Rollback / failure signal
Switch auth mode back to OIDC. SAML failures show as login loop, missing group claim, or decided_by without a saml: prefix.
Approved HIL rows stamp decided_by = saml:<NameID> and keep the operator note in the ledger replay.
Full guide in the clavenar-console README.
Use HA storage without changing proof bytes.
Choose this when ledger availability matters more than SQLite simplicity. Hash-chain bytes stay byte-identical across SQLite and Postgres.
Prerequisites
- Postgres database and credentials.
- Ledger image built with
--features postgres. - Backup of the current SQLite ledger if migrating.
Steps
CLAVENAR_LEDGER_BACKEND=postgres CLAVENAR_LEDGER_POSTGRES_URL=postgres://clavenar:<pw>@db.internal/clavenar_ledger
Verify
Call GET /verify after migration and compare row count/head hash with the source ledger.
Rollback / failure signal
Return CLAVENAR_LEDGER_BACKEND=sqlite and restore the last known-good snapshot. Treat 409 from /verify as a stop-the-line incident.
GET /verify returns { "valid": true } with the expected height after the backend switch.
Sidecar deployment on AWS / GCP / Azure.
Choose this when the full stack belongs beside production agents in Kubernetes and cloud IAM/VPC/DNS are managed by platform teams.
Prerequisites
- Cluster access and namespace.
- Secrets for proxy, HIL, ledger, identity, and console.
- Postgres backend for multi-replica ledger or
replicaCount: 1for SQLite.
Steps
helm install my-clavenar ./charts/clavenar \ --set image.tag=v1.119.1 \ --set ledger.backend=postgres \ --set ledger.postgresUrl=postgres://... kubectl get svc clavenar-proxy
Verify
Check /readyz for every service, then run GET /verify and one gated POST /mcp.
Rollback / failure signal
Use helm rollback. Failed readiness usually means a secret, service URL, or ledger backend value is wrong.
Proxy service is reachable, dependency /readyz endpoints pass, and the first tool call leaves a valid ledger trace.
Land a new policy in shadow first.
Choose this when a new Rego rule could deny legitimate work and you need real traffic evidence before enforcement.
Prerequisites
- New policy in
policies/. - Dashboard access to
would_denymetrics. - Owner assigned to review false positives.
Steps
CLAVENAR_MODE=observe
CLAVENAR_LITE_MODE=observe
# after the soak window
CLAVENAR_MODE=enforce
Verify
Watch clavenar_proxy_would_deny_total by tool and intent, then replay representative correlations before flipping to enforce.
Rollback / failure signal
Return to observe if support tickets spike, false-positive correlations appear, or legitimate workflows park unexpectedly.
Observe mode writes would_deny evidence without blocking; enforce mode converts the same policy path into real denies or reviews.
Splunk HEC · Datadog Logs · generic HTTP.
Choose this when the ledger remains the source of truth but compliance, SOC, or incident workflows need a downstream copy.
Prerequisites
- Splunk HEC token, Datadog API key, or generic bearer token.
- Outbound network path from ledger to the sink.
- Destination dedupe on ledger entry UUID.
Steps
CLAVENAR_LEDGER_EGRESS_SPLUNK_URL=https://hec.splunk.example/services/collector CLAVENAR_LEDGER_EGRESS_SPLUNK_TOKEN=<hec-token> CLAVENAR_LEDGER_EGRESS_DATADOG_SITE=datadoghq.com CLAVENAR_LEDGER_EGRESS_DATADOG_API_KEY=<dd-api-key> CLAVENAR_LEDGER_EGRESS_GENERIC_URL=https://logs.internal/ingest CLAVENAR_LEDGER_EGRESS_GENERIC_BEARER=<optional-bearer>
Verify
Generate a known correlation id, wait for the sink cursor, then search the destination for the ledger entry UUID.
Rollback / failure signal
Disable only the failing sink. Cursors advance only after confirmation, so the next successful sweep retries from the first failed row.
Downstream events carry the stable ledger UUID and correlation id, allowing duplicate POSTs to dedupe without weakening the source chain.