Closed Beta — Aira is currently invite-only. Request access to join the early program.
Aira

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.

Installation

npm install aira-sdk

Gateway (zero-code integration)

import OpenAI from "openai";
import { gatewayOpenAIConfig } from "aira-sdk/gateway";

const client = new OpenAI({
  ...gatewayOpenAIConfig({ airaApiKey: "aira_live_..." }),
  apiKey: "sk-...",
});

Quick Start

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).

Method Signatures

// 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

Error Handling

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;
}

Agent Registry

// 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" });

Evidence & Discovery

// 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 });

Agent Estate

// 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" },
});

Escrow

// 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",
});

Ask Aira (Chat)

const response = await aira.ask("How many email actions were notarized this week?");
console.log(response.content);
console.log(response.toolsUsed);  // ["count_actions"]

Public Verification

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."

Trust Layer

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.

DID Identity

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");

Verifiable Credentials

// 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" });

Mutual Notarization

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:...",
});

Reputation Score

const rep = await aira.getReputation("my-agent");
console.log(rep.score);  // 84
console.log(rep.tier);   // "Verified"

Framework Integrations

Vercel AI SDK

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),
    });
  },
});

LangChain.js

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] },
);

OpenAI Agents SDK

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" });

MCP Server

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

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.


Session

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",
  });
}

Webhook Verification

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.


All Methods

Actions

MethodDescription
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.

Agents

MethodDescription
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

Evidence

MethodDescription
createEvidencePackage()Seal actions into bundle
listEvidencePackages()List packages
getEvidencePackage(id)Get detail
timeTravel(pointInTime)Point-in-time query
liabilityChain(actionId)Multi-hop chain

Estate

MethodDescription
setAgentWill(slug)Set succession plan
getAgentWill(slug)Get will
issueDeathCertificate(slug)Issue death cert
getDeathCertificate(slug)Get cert
createComplianceSnapshot()Attestation
listComplianceSnapshots()List snapshots

Escrow

MethodDescription
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

Trust Layer

MethodDescription
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

Policies

MethodDescription
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

Sanitize

MethodDescription
sanitizeText()Scan text for PII, PHI, secrets, prompt injection
detokenize()Reverse tokenization — map tokens back to originals

Webhooks (management)

MethodDescription
createWebhook()Create a webhook subscription
listWebhooks()List all webhooks
deleteWebhook(id)Delete a webhook

Usage

MethodDescription
getUsage()Get usage summary for current billing period
listUsageEvents()List individual usage events

Models

MethodDescription
listModels()List available models
getModelPreferences()Get model preferences (disabled list)
updateModelPreferences(disabledModels)Update which models are disabled

Cases

MethodDescription
runCase(details, models)Run a compliance case
getCase(id)Get case detail
listCases()List cases

Receipts

MethodDescription
getReceipt(id)Get a cryptographic receipt
exportReceipt(id, format)Export receipt as JSON or PDF

Compliance Bundles

MethodDescription
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

Compliance Reports

MethodDescription
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

DORA

MethodDescription
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

Drift Detection

MethodDescription
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

Settlements

MethodDescription
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

Output Policy

MethodDescription
getOutputPolicy()Get output content-scan policy
updateOutputPolicy(updates)Update output content-scan policy

Explanations

MethodDescription
getActionExplanation(actionId)Get Article 6 right-to-explanation
verifyActionExplanation(explanation)Public verify — recompute envelope signature
downloadActionExplanationPdf(actionId)Download explanation as PDF

Code Governance

MethodDescription
getPrViolations(owner, repo, pullNumber)Get policy violations for a GitHub PR

Replay Context

MethodDescription
getReplayContext(actionId)Get reproducibility metadata for an action

Chat

MethodDescription
ask(message)Natural language query

Error Handling

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.

Configuration

const aira = new Aira({
  apiKey: "aira_live_xxx",
  baseUrl: "https://your-self-hosted.com",  // Self-hosted
  timeout: 60000,                            // Request timeout (ms)
});

Policies

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.

On this page