TypeScript SDK Install, configure, and use the Aira TypeScript SDK. Two-step authorize and notarize flow, async client, framework integrations for Vercel AI, LangChain.js, and OpenAI Agents.
OpenAI Anthropic
import OpenAI from "openai" ;
import { gatewayOpenAIConfig } from "aira-sdk/gateway" ;
const client = new OpenAI ({
... gatewayOpenAIConfig ({ airaApiKey: "aira_live_..." }),
apiKey: "sk-..." ,
});
Aira uses a two-step flow. Call authorize() before the agent acts to get a policy decision. Call notarize() after the agent executes to mint the receipt.
import { Aira, AiraError } from "aira-sdk" ;
const aira = new Aira ({ apiKey: "aira_live_..." });
try {
const auth = await aira. authorize ({
actionType: "wire_transfer" ,
details: "Send 75,000 EUR to vendor X" ,
agentId: "payments-agent" ,
});
if (auth.status === "authorized" ) {
// Execute the actual action
const result = await sendWire ( 75000 , "vendor" );
// Step 2: notarize the outcome and mint the receipt
const receipt = await aira. notarize ({
actionId: auth.action_uuid,
outcome: "completed" ,
outcomeDetails: `Sent successfully. ref=${ result . id }` ,
});
console. log (receipt.signature); // Ed25519 signature
} else if (auth.status === "pending_approval" ) {
// Held for human review. Agent must wait.
await queue. enqueue (auth.action_uuid);
}
} catch (e) {
if (e instanceof AiraError && e.code === "POLICY_DENIED" ) {
console. error ( `Blocked: ${ e . message }` );
return ;
}
throw e;
}
See the Quickstart for more on the three branches (authorized, pending_approval, POLICY_DENIED).
// Step 1: request authorization
const auth = await aira. authorize ({
actionType: string,
details: string,
agentId?: string,
agentVersion?: string,
instructionHash?: string,
modelId?: string,
modelVersion?: string,
parentActionId?: string,
endpointUrl?: string,
storeDetails?: boolean,
idempotencyKey?: string,
requireApproval?: boolean,
approvers?: string[],
});
// Returns Authorization:
// auth.action_uuid (UUID string)
// auth.status ("authorized" | "pending_approval")
// auth.created_at
// auth.request_id
// auth.warnings (string[] | null)
//
// Throws AiraError(code: "POLICY_DENIED") on policy deny.
// Step 2: notarize the outcome after execution
const receipt = await aira. notarize ({
actionId: string,
outcome?: "completed" | "failed" , // default: "completed"
outcomeDetails?: string,
});
// Returns ActionReceipt:
// receipt.action_uuid
// receipt.status ("notarized" | "failed")
// receipt.receipt_uuid (null when failed)
// receipt.payload_hash (null when failed)
// receipt.signature (Ed25519, null when failed)
// receipt.timestamp_token (RFC 3161, may be null on TSA failure)
// receipt.created_at
// receipt.request_id
// receipt.warnings
import { Aira, AiraError } from "aira-sdk" ;
try {
const auth = await aira. authorize ({ actionType: "wire_transfer" , details: "..." });
} catch (e) {
if (e instanceof AiraError ) {
if (e.code === "POLICY_DENIED" ) {
// Action blocked by policy
console. error ( `Blocked: ${ e . message }` );
console. error ( `Policy ID: ${ e . details ?. policy_uuid }` );
console. error ( `Audit row: ${ e . details ?. action_uuid }` );
return ;
}
if (e.code === "DUPLICATE_REQUEST" ) return ;
}
throw e;
}
// Register
const agent = await aira. registerAgent ({
agentSlug: "support-agent-v2" ,
displayName: "Customer Support Agent" ,
capabilities: [ "email" , "chat" , "tickets" ],
public: true ,
});
// Publish version
await aira. publishVersion ({
slug: "support-agent-v2" ,
version: "1.0.0" ,
modelId: "claude-sonnet-4-6" ,
changelog: "Initial release" ,
});
// Update
await aira. updateAgent ( "support-agent-v2" , { description: "Updated description" });
// List versions
const versions = await aira. listVersions ( "support-agent-v2" );
// Decommission
await aira. decommissionAgent ( "old-agent" );
// Transfer ownership
await aira. transferAgent ( "my-agent" , { toOrgId: "org-uuid" , reason: "M&A" });
// Create sealed evidence package
const pkg = await aira. createEvidencePackage ({
title: "Q1 2026 Lending Audit Trail" ,
actionIds: [ "act-uuid-1" , "act-uuid-2" , "act-uuid-3" ],
description: "All lending decisions for BaFin review" ,
});
// Time-travel query
const result = await aira. timeTravel ({
pointInTime: "2026-03-20T00:00:00Z" ,
agentSlug: "lending-agent" ,
});
// Liability chain
const chain = await aira. liabilityChain ( "act-uuid" , { maxDepth: 10 });
// Set succession plan
await aira. setAgentWill ({
slug: "support-agent" ,
successorSlug: "support-agent-v3" ,
successionPolicy: "transfer_to_successor" ,
dataRetentionDays: 2555 ,
notifyEmails: [ "compliance@acme.com" ],
instructions: "Transfer conversation history. Delete PII after 7 years." ,
});
// Get will
const will = await aira. getAgentWill ( "support-agent" );
// Issue death certificate (agent must be decommissioned first)
await aira. decommissionAgent ( "old-agent" );
const cert = await aira. issueDeathCertificate ( "old-agent" , { reason: "Replaced by v3" });
// Compliance snapshot
const snapshot = await aira. createComplianceSnapshot ({
framework: "eu-ai-act" ,
agentSlug: "lending-agent" ,
findings: { art_12_logging: "pass" , art_14_oversight: "pass" },
});
// Create account
const account = await aira. createEscrowAccount ({
purpose: "Vendor contract #4521" ,
currency: "EUR" ,
});
// Record commitment
await aira. escrowDeposit (account.id, { amount: 5000.0 , description: "Liability commitment" });
// Release
await aira. escrowRelease (account.id, { amount: 5000.0 });
// Dispute
await aira. escrowDispute (account.id, {
amount: 5000.0 ,
description: "Agent error in contract terms" ,
});
const response = await aira. ask ( "How many email actions were notarized this week?" );
console. log (response.content);
console. log (response.toolsUsed); // ["count_actions"]
No authentication required:
const result = await aira. verifyAction ( "action-uuid" );
console. log (result.valid); // true
console. log (result.message); // "Action receipt exists and signing key is valid."
Standards-based identity and trust for agents: W3C DIDs, Verifiable Credentials, mutual notarization, and reputation scoring. See the full Trust Layer guide for architecture details.
Every registered agent gets a W3C-compliant DID (did:web):
// DID is assigned on registration
const agent = await aira. registerAgent ({
agentSlug: "my-agent" ,
displayName: "My Agent" ,
capabilities: [ "email" , "chat" ],
});
// agent.did → "did:web:airaproof.com:agents:my-agent"
// Rotate keys
await aira. rotateAgentKeys ( "my-agent" );
// Get the agent's W3C Verifiable Credential
const vc = await aira. getAgentCredential ( "my-agent" );
// Verify it
const result = await aira. verifyCredential (vc);
console. log (result.valid); // true
// Revoke
await aira. revokeCredential ( "my-agent" , { reason: "Agent deprecated" });
For high-stakes actions, both parties co-sign:
// Agent A initiates
const request = await aira. requestMutualSign ({
actionId: "act-uuid" ,
counterpartyDid: "did:web:partner.com:agents:their-agent" ,
});
// Agent B completes
const receipt = await aira. completeMutualSign ({
actionId: "act-uuid" ,
did: "did:web:partner.com:agents:their-agent" ,
signature: "z..." ,
signedPayloadHash: "sha256:..." ,
});
const rep = await aira. getReputation ( "my-agent" );
console. log (rep.score); // 84
console. log (rep.tier); // "Verified"
Use the Aira middleware with the Vercel AI SDK. For each tool step, call authorize() before the tool runs and notarize() after it returns.
import { Aira, AiraError } from "aira-sdk" ;
import { generateText } from "ai" ;
const aira = new Aira ({ apiKey: "aira_live_..." });
const result = await generateText ({
model: yourModel,
tools: yourTools,
prompt: "Analyze Q1 revenue" ,
experimental_prepareStep : async ( step ) => {
// authorize the intended tool call before Vercel runs it
const auth = await aira. authorize ({
actionType: "tool_call" ,
agentId: "vercel-agent" ,
details: `Invoke ${ step . toolCall ?. toolName }` ,
});
if (auth.status !== "authorized" ) {
throw new Error ( `Tool call not authorized: ${ auth . status }` );
}
step.meta = { actionId: auth.action_uuid };
},
onStepFinish : async ( step ) => {
// notarize after the tool returns
await aira. notarize ({
actionId: step.meta.actionId,
outcome: "completed" ,
outcomeDetails: JSON . stringify (step.toolResults),
});
},
});
import { Aira } from "aira-sdk" ;
import { AiraCallbackHandler } from "aira-sdk/extras/langchain" ;
const aira = new Aira ({ apiKey: "aira_live_xxx" });
const handler = new AiraCallbackHandler ({
client: aira,
agentId: "research-agent" ,
modelId: "gpt-5.2" ,
});
// Every tool call and chain completion gets a signed receipt
const result = await chain. invoke (
{ input: "Analyze Q1 revenue" },
{ callbacks: [handler] },
);
import { Aira } from "aira-sdk" ;
import { AiraGuardrail } from "aira-sdk/extras/openai-agents" ;
const aira = new Aira ({ apiKey: "aira_live_xxx" });
const guardrail = new AiraGuardrail ({
client: aira,
agentId: "assistant-agent" ,
});
// Wrap tools — every call and result gets a signed receipt
const search = guardrail. wrapTool (searchTool, { toolName: "web_search" });
const execute = guardrail. wrapTool (codeExecutor, { toolName: "code_exec" });
import { Aira } from "aira-sdk" ;
import { createServer, getTools, handleToolCall } from "aira-sdk/extras/mcp" ;
import { Server } from "@modelcontextprotocol/sdk/server/index.js" ;
import { ListToolsRequestSchema, CallToolRequestSchema } from "@modelcontextprotocol/sdk/types.js" ;
const aira = new Aira ({ apiKey: "aira_live_xxx" });
const { listTools , callTool } = createServer (aira);
const server = new Server ({ name: "aira" , version: "1.0.0" }, { capabilities: { tools: {} } });
server. setRequestHandler (ListToolsRequestSchema, listTools);
server. setRequestHandler (CallToolRequestSchema, callTool);
The server exposes tools including authorize_action, notarize_action, get_action, verify_action, get_receipt, resolve_did, verify_credential, get_reputation, request_mutual_sign, get_pr_violations, and list_policies. The MCP-connected agent calls authorize_action before acting and notarize_action after.
Add to your MCP client config:
{
"mcpServers" : {
"aira" : {
"command" : "npx" ,
"args" : [ "aira-sdk" , "mcp" ],
"env" : { "AIRA_API_KEY" : "aira_live_xxx" }
}
}
}
Offline mode is for post-hoc audit actions where authorize has already run (or is not required). It queues pending records locally and flushes them when connectivity returns.
const aira = new Aira ({ apiKey: "aira_live_..." , offline: true });
// Queue a two-step record locally. authorize and notarize are serialized.
const auth = await aira. authorize ({
actionType: "scan_completed" ,
details: "Scanned document batch #77" ,
agentId: "scanner-agent" ,
});
// Execute the real work offline...
await aira. notarize ({
actionId: auth.action_uuid,
outcome: "completed" ,
outcomeDetails: "Batch 77 scanned, 412 pages" ,
});
console. log (aira.queue.pendingCount);
// Flush to API when back online. Policies are evaluated server-side at flush time.
const results = await aira. sync ();
Offline mode means policies are not checked until sync() runs. Use it for audit-only workflows, not for gated actions.
Pre-fill defaults for a block of related actions. Every authorize() call within the session inherits the agent identity and model.
const session = aira. session ({ agentId: "onboarding-agent" , modelId: "claude-sonnet-4-6" });
const auth = await session. authorize ({
actionType: "identity_verified" ,
details: "Verified customer ID #4521" ,
});
if (auth.status === "authorized" ) {
await verifyIdentityInDb ( 4521 );
await session. notarize ({
actionId: auth.action_uuid,
outcome: "completed" ,
outcomeDetails: "KYC check passed" ,
});
}
Verify that incoming webhooks are authentic Aira events. HMAC-SHA256 signature verification ensures tamper-proof delivery.
import { verifySignature, parseEvent } from "aira-sdk/extras/webhooks" ;
const isValid = verifySignature (
req.body, // payload (Buffer or string)
req.headers[ "x-aira-signature" ], // "sha256={hex}"
"whsec_xxx" , // webhook secret
);
if (isValid) {
const event = parseEvent (req.body);
console. log (event.eventType); // "action.notarized"
console. log (event.data); // Action data with cryptographic receipt
}
Supported event types: action.authorized, action.approval_requested, action.approved, action.denied, action.notarized, action.failed, action.cosigned, agent.registered, agent.decommissioned, evidence.sealed, escrow.deposited, escrow.released, escrow.disputed, compliance.snapshot_created, case.complete, case.requires_human_review.
Method Description authorize()Step 1. Request permission before the agent acts. notarize()Step 2. Report the outcome and mint the receipt. getAction(id)Get action detail with policy evaluation and receipt. listActions()List actions with filters. cosign(actionId)Human co-signature on a notarized action (JWT auth). setLegalHold(id)Prevent deletion. releaseLegalHold(id)Remove legal hold. getActionChain(id)Chain of custody. verifyAction(id)Public verification.
Method Description registerAgent()Register identity getAgent(slug)Get detail + versions listAgents()List with status filter updateAgent(slug)Update metadata publishVersion(slug)Publish new version listVersions(slug)List all versions decommissionAgent(slug)Decommission transferAgent(slug)Transfer ownership getAgentActions(slug)Actions by this agent
Method Description createEvidencePackage()Seal actions into bundle listEvidencePackages()List packages getEvidencePackage(id)Get detail timeTravel(pointInTime)Point-in-time query liabilityChain(actionId)Multi-hop chain
Method Description setAgentWill(slug)Set succession plan getAgentWill(slug)Get will issueDeathCertificate(slug)Issue death cert getDeathCertificate(slug)Get cert createComplianceSnapshot()Attestation listComplianceSnapshots()List snapshots
Method Description createEscrowAccount()Create account listEscrowAccounts()List accounts getEscrowAccount(id)Get detail escrowDeposit(id, amount)Record commitment escrowRelease(id, amount)Release commitment escrowDispute(id, amount, desc)File dispute
Method Description getAgentDid(slug)Retrieve agent's W3C DID rotateAgentKeys(slug)Rotate Ed25519 signing keys getAgentCredential(slug)Get current W3C Verifiable Credential getAgentCredentials(slug)Get full credential history verifyCredential(vc)Verify a Verifiable Credential revokeCredential(slug)Revoke a credential requestMutualSign(actionId, did)Initiate mutual notarization completeMutualSign(actionId, did, signature, hash)Complete mutual notarization getPendingMutualSign(actionId)Get payload awaiting counterparty signature getMutualSignReceipt(actionId)Get co-signed receipt rejectMutualSign(actionId)Reject a mutual signing request getReputation(slug)Get reputation score and tier getReputationHistory(slug)Get reputation history attestReputation(slug, ...)Submit signed attestation of interaction verifyReputation(slug)Verify a reputation score resolveDid(did)Resolve any DID to DID Document
Method Description createPolicy()Create a governance policy listPolicies()List all active policies getPolicy(id)Get a single policy updatePolicy(id)Update a policy deletePolicy(id)Delete a policy activatePolicy(id)Activate a policy deactivatePolicy(id)Deactivate a policy dryRunPolicy(id, context)Test a policy without executing
Method Description sanitizeText()Scan text for PII, PHI, secrets, prompt injection detokenize()Reverse tokenization — map tokens back to originals
Method Description createWebhook()Create a webhook subscription listWebhooks()List all webhooks deleteWebhook(id)Delete a webhook
Method Description getUsage()Get usage summary for current billing period listUsageEvents()List individual usage events
Method Description listModels()List available models getModelPreferences()Get model preferences (disabled list) updateModelPreferences(disabledModels)Update which models are disabled
Method Description runCase(details, models)Run a compliance case getCase(id)Get case detail listCases()List cases
Method Description getReceipt(id)Get a cryptographic receipt exportReceipt(id, format)Export receipt as JSON or PDF
Method Description createComplianceBundle()Seal a regulator-ready evidence bundle listComplianceBundles()List bundles getComplianceBundle(id)Get bundle detail exportComplianceBundle(id)Download self-contained JSON export getBundleInclusionProof(bundleId, receiptId)Get Merkle inclusion proof for a receipt
Method Description createComplianceReport()Generate a regulatory PDF report listComplianceReports()List reports with filters getComplianceReport(id)Get report metadata verifyComplianceReport(id)Verify report signature and content hash downloadComplianceReport(id)Download report PDF as bytes
Method Description createDoraIncident()Open a DORA ICT incident (Article 17) listDoraIncidents()List incidents with filters getDoraIncident(id)Get incident detail classifyDoraIncident(id)Classify a detected incident (Article 18) resolveDoraIncident(id)Mark incident resolved with post-mortem downloadDoraIncidentReport(id)Download major-incident PDF for ESA createIctThirdParty()Add vendor to ICT register (Article 28) listIctThirdParties()List ICT third-party register getIctThirdParty(id)Get third-party detail updateIctThirdParty(id)Update third-party entry createDoraTest()Log a resilience test (Articles 24-27) listDoraTests()List resilience tests
Method Description getDriftStatus(agentId)Score recent behavior against baseline computeDriftBaseline(agentId, window)Compute baseline from production history seedSyntheticBaseline(agentId, config)Seed a baseline from config (cold-start) runDriftCheck(agentId)Score and persist alert if threshold exceeded listDriftAlerts(agentId)List drift alerts acknowledgeDriftAlert(agentId, alertId)Acknowledge a drift alert
Method Description createSettlement()Seal unsettled receipts into a Merkle settlement listSettlements()List settlements getSettlement(id)Get settlement detail getSettlementInclusionProof(receiptId)Get Merkle inclusion proof for a receipt
Method Description getOutputPolicy()Get output content-scan policy updateOutputPolicy(updates)Update output content-scan policy
Method Description getActionExplanation(actionId)Get Article 6 right-to-explanation verifyActionExplanation(explanation)Public verify — recompute envelope signature downloadActionExplanationPdf(actionId)Download explanation as PDF
Method Description getPrViolations(owner, repo, pullNumber)Get policy violations for a GitHub PR
Method Description getReplayContext(actionId)Get reproducibility metadata for an action
Method Description ask(message)Natural language query
import { AiraError } from "aira-sdk" ;
try {
const auth = await aira. authorize ({
actionType: "email_sent" ,
details: "Send onboarding email" ,
agentId: "support-agent" ,
});
} catch (e) {
if (e instanceof AiraError ) {
if (e.code === "POLICY_DENIED" ) {
console. log ( `Blocked: ${ e . message }` );
} else if (e.code === "PLAN_LIMIT_EXCEEDED" ) {
console. log ( "Monthly operation limit reached" );
} else {
console. log ( `[${ e . code }] ${ e . message } (status=${ e . status })` );
}
}
}
See Error Handling for the full list of error codes.
const aira = new Aira ({
apiKey: "aira_live_xxx" ,
baseUrl: "https://your-self-hosted.com" , // Self-hosted
timeout: 60000 , // Request timeout (ms)
});
Create and manage governance policies programmatically:
// Create an AI policy for Code Governance
const policy = await aira. createPolicy ({
name: "AI Agent Governance" ,
mode: "ai" ,
priority: 100 ,
aiModels: [ "claude-opus-4-8" ],
aiPrompt: "Review agent code for prompt safety, PII leakage..." ,
conditions: [
{ field: "action_type" , op: "eq" , value: "pr_code_scan" },
{ field: "agent_id" , op: "contains" , value: "acme/agent-platform" },
],
});
// List policies
const policies = await aira. listPolicies ();
// Update
await aira. updatePolicy (policy.id, { priority: 200 });
// Delete
await aira. deletePolicy (policy.id);
For full Code Governance documentation, see Code Governance .