Connect the agent
Wire the SDK into your agent. Cooperative mode asks first; enforced mode makes bypass impossible.
Install the SDK
Official clients for TypeScript/JavaScript and Python — both Apache-2.0 with zero runtime dependencies:
# TypeScript / JavaScript
npm i @identiqube/provenant-sdk
# Python (imports as `provenant_sdk`)
pip install provenant-sdkOn the registries: @identiqube/provenant-sdk (npm) · provenant-sdk (PyPI). The examples below are TypeScript; the Python client mirrors the same surface (from provenant_sdk import ProvenantClient).
Cooperative mode
Your code holds the credential and asks first:
import { ProvenantClient } from '@identiqube/provenant-sdk';
const provenant = new ProvenantClient({ baseUrl: process.env.PROVENANT_API!, apiKey: process.env.PROVENANT_KEY! });
const d = await provenant.authorize({ type: 'payment.send', resource: 'vendor:acme', valueCents: 2500 });
if (d.status === 'authorized') {
const ref = await payVendor();
await provenant.complete(d.id, { success: true, externalRef: ref });
} else if (d.status === 'pending_approval') {
// poll provenant.getAction(d.id) until authorized, then execute
} else {
console.warn('denied:', d.decision.reason); // full trail in d.decision.checks
}Enforced (brokered) mode
The agent cannot bypass policy. In Govern → Connectors add a connector (the downstream target; its credential is stored server-side, never handed to the agent), then invoke through it:
const r = await provenant.invoke({ connectorId: 'con_…', type: 'payment.send', resource: 'vendor:acme', valueCents: 2500 });
// Provenant performs the call ONLY after an allow; denied/held never reach the resource.Pass-through requests (call any API)
A connector stores the base URL + credential + policy scope; the agent supplies the actual request.type/resource/valueCents are the policy descriptors; request is the HTTP call to forward:
const r = await provenant.invoke({
connectorId: 'con_…',
type: 'payment.send', resource: 'vendor:acme', valueCents: 2500, // ← evaluated by policy
request: { // ← forwarded verbatim
method: 'POST',
path: '/v1/charges', // resolved against the connector base URL, CONFINED to its host
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ amount: 2500, currency: 'eur', source: 'tok_x' }),
},
});
// r.output = { status, headers, body } ← the downstream response, returned to the agentSafety
path is confined to the connector's host and base path (sibling-prefix and encoded-traversal escapes are rejected). The server-held credential overrides any auth header the agent sets, and credential-bearing response headers (set-cookie, authorization, …) are stripped before the response reaches the agent.MCP gateway
Point any MCP client at POST /v1/mcp (with the agent key). Your connectors appear as tools and everytools/call is policy-gated.
Framework tools (Vercel AI SDK, LangChain, CrewAI)
Already using an agent framework? Wrap any tool's executor with governTool (TypeScript) or govern_tool (Python): every call is authorized, executed, and completed through Provenant, with no change to how your framework invokes the tool.
import { governTool } from '@identiqube/provenant-sdk';
import { tool } from 'ai';
const pay = tool({
description: 'Pay a vendor invoice',
parameters: z.object({ vendor: z.string(), amountCents: z.number() }),
execute: governTool(provenant, payVendor, {
type: 'payment.send',
resource: (a) => `vendor:${a.vendor}`,
valueCents: (a) => a.amountCents,
}),
});from provenant_sdk import govern_tool
governed_pay = govern_tool(
provenant, pay_vendor,
type="payment.send",
resource=lambda a: f"vendor:{a['vendor']}",
value_cents=lambda a: a["amount_cents"],
) # hand governed_pay to LangChain / CrewAI / LangGraph like any tool fnOn allow the tool runs and the outcome is reported for you. On deny or hold-for-approval the tool never runs and the call returns a { provenant: "blocked", status, reason, … } object your model reads as the tool result — so the agent explains the refusal instead of acting.
Deeper automation (agent-driven)
- Discovery —
provenant.connectors()returns the org's enabled connectors (id, name, scope, base host, auth summary — never secrets), so ids needn't be hard-coded. - Capability routing — call
invoke({ type, resource, request })withoutconnectorId; Provenant routes to the connector whose scope matches. One match → used; none → denied; multiple → rejected (pass an explicit id to disambiguate). - Self-registration — an agent can spawn an attenuated child at runtime:
const { key } = await provenant.spawn({
name: 'invoice-worker',
mandate: { name: 'narrowed', allowedActions: ['payment.send'], allowedResources: ['vendor:acme'],
maxActionValueCents: 50_00, requireApprovalOverCents: 0, rateLimitPerMinute: 30 },
});The child's mandate is the intersection of the request and the parent's — never broader. Children are linked to the parent in the ledger (the agent.created entry records the parent and the delegation), bounded by a depth limit shown on the agent's lineage card, and cascade-revoked with the parent. An agent's detail page shows its parent and delegated children.