This page describes the planned TypeScript SDK, @intercept/sdk. The package is not published, and the names, signatures and defaults below are a design target that may change. Use this page to understand the intended shape of an integration, not to write production code.
Constructor
import { Intercept } from "@intercept/sdk"; // illustrative — not yet published
const intercept = new Intercept({
apiKey: process.env.INTERCEPT_API_KEY,
policy: "./intercept.policy.json",
cluster: "mainnet-beta",
});| Option | Type | Default | Description |
|---|---|---|---|
apiKey |
string |
process.env.INTERCEPT_API_KEY |
Secret key sent as Authorization: Bearer. Required. |
policy |
string | Policy |
process.env.INTERCEPT_POLICY_PATH |
Path to intercept.policy.json or an in-memory policy object. |
cluster |
"mainnet-beta" | "devnet" |
process.env.INTERCEPT_CLUSTER or "mainnet-beta" |
Solana cluster used for simulation and execution. |
baseUrl |
string |
https://api.intercept.example/v0 (placeholder) |
API base URL. |
timeoutMs |
number |
2000 |
Per-request timeout. On timeout the SDK returns a SYS_TIMEOUT decision. |
failMode |
"closed" | "open" |
"closed" |
Behavior on transport errors. "closed" treats them as blocked. |
maxRetries |
number |
2 |
Retries for idempotent transport failures. |
See Configuration for environment variables and the policy file.
Types
type Decision = "approved" | "blocked" | "requires_approval";
type Layer = "risk" | "security" | "network" | "system";
interface Reason {
code: string; // e.g. "RISK_MAX_LEVERAGE", "SEC_BLOCKED_ADDRESS", "NET_FLAGGED_PROGRAM", "SYS_PAUSED"
layer: Layer;
message: string;
}
interface BalanceChange {
account: string; // base58
mint: string | null; // null for native SOL
before: string; // integer amount as string
after: string;
}
interface SimulationResult {
success: boolean;
computeUnits: number;
balanceChanges: BalanceChange[];
error?: string;
}
interface EvaluationResult {
evaluationId: string;
decision: Decision;
policyVersion: string;
reasons: Reason[];
simulation: SimulationResult;
latencyMs: number;
}
interface EvaluateContext {
agentId: string;
intent?: string; // natural-language intent, checked against simulated effects
idempotencyKey?: string;
}evaluate
evaluate(tx: VersionedTransaction | Transaction, ctx: EvaluateContext): Promise<EvaluationResult>Simulates the transaction, runs the risk and security engines against the active policy, and returns a decision. It never sends anything onchain. reasons is empty for a clean approval and may contain informational entries otherwise.
execute
execute(result: EvaluationResult): Promise<string> // transaction signatureSubmits a previously approved evaluation. In enforced mode, Intercept is designed to co-sign only if the transaction matches the evaluated bytes and the evaluation has not expired. In advisory mode, it submits the agent-signed transaction. Calling execute on a non-approved result throws.
Blocking only works if the integration is enforced. In advisory mode, nothing prevents an agent from bypassing execute and sending with its own key.
requestApproval
requestApproval(evaluationId: string, opts?: { note?: string }): Promise<{ status: "pending" }>Opens a human approval request for a requires_approval decision. Approvers respond out of band; you will receive an evaluation.approved or evaluation.blocked webhook.
policies
policies.validate(policy: Policy): Promise<{ valid: boolean; errors: { path: string; message: string }[] }>
policies.publish(policy: Policy): Promise<{ policyVersion: string; publishedAt: string }>validate checks a policy locally and against server rules without changing anything. publish makes it active for the agent; evaluations already in flight keep the version they started with.
pause and resume
pause(opts: { reason: string }): Promise<void>
resume(): Promise<void>pause sets the agent to paused. Every subsequent evaluation returns blocked with SYS_PAUSED until resume is called. Guardians listed in the policy are designed to be able to pause independently of the agent's API key.
webhooks.verify
webhooks.verify(payload: string, signature: string, opts?: { toleranceSec?: number }): WebhookEventVerifies the Intercept-Signature header against the raw request body and returns the parsed event, or throws. See Webhooks.
Full example
const result = await intercept.evaluate(transaction, {
agentId: "agent_7f3c",
intent: "Swap 1,200 USDC to SOL on Jupiter",
idempotencyKey: crypto.randomUUID(),
});
switch (result.decision) {
case "approved":
await intercept.execute(result);
break;
case "requires_approval":
await intercept.requestApproval(result.evaluationId);
break;
case "blocked":
log.warn({ reasons: result.reasons }, "transaction blocked");
break;
}