TypeScript SDK for integrating OpenBox AI governance into Temporal workflows. Direct port of the Python SDK.
- Intercepts every workflow and activity execution and sends governance events to OpenBox Core
- Evaluates HTTP and database operations mid-activity via OpenTelemetry hooks
- Enforces governance verdicts: ALLOW, BLOCK, HALT, REQUIRE_APPROVAL
- Signs all requests with Ed25519 (AIP DID protocol) for tamper-proof audit trails
npm install openbox-temporal-sdkRequired peer dependencies (if not already in your project):
npm install @temporalio/worker @temporalio/workflow @temporalio/activityCopy .env.example to .env and fill in your values:
cp .env.example .envOPENBOX_API_KEY=obx_live_your_api_key_here
OPENBOX_AGENT_DID=did:aip:your-agent-did-here
OPENBOX_AGENT_PRIVATE_KEY=your_base64_private_key_seed_here
OPENBOX_API_URL=https://core.openbox.aiNever commit
.env— it is git-ignored. Commit.env.exampleinstead.
import * as dotenv from 'dotenv';
dotenv.config();
import { Worker } from '@temporalio/worker';
import { OpenBoxPlugin } from 'openbox-temporal-sdk';
const worker = await Worker.create({
taskQueue: 'my-task-queue',
workflowsPath: require.resolve('./workflows'),
activities: myActivities,
plugins: [
new OpenBoxPlugin({
openboxUrl: process.env.OPENBOX_API_URL!,
openboxApiKey: process.env.OPENBOX_API_KEY!,
agentDid: process.env.OPENBOX_AGENT_DID,
agentPrivateKey: process.env.OPENBOX_AGENT_PRIVATE_KEY,
}),
],
});
await worker.run();That's it. Every workflow and activity that runs through this worker will automatically have governance events sent to your OpenBox dashboard.
| Option | Type | Default | Description |
|---|---|---|---|
openboxUrl |
string |
— | OpenBox Core API URL (required) |
openboxApiKey |
string |
— | API key (obx_live_... or obx_test_...) |
agentDid |
string |
null |
Agent DID for request signing (did:aip:...) |
agentPrivateKey |
string |
null |
Base64 Ed25519 private key seed |
onApiError |
'fail_open' | 'fail_closed' |
'fail_open' |
What to do if OpenBox Core is unreachable |
apiTimeout |
number |
30 |
Governance API timeout in seconds |
instrumentHttp |
boolean |
true |
Intercept outbound HTTP calls |
instrumentDatabases |
boolean |
true |
Intercept database queries |
instrumentFileIo |
boolean |
false |
Intercept file I/O operations |
skipWorkflowTypes |
string[] |
[] |
Workflow types to skip governance for |
skipActivityTypes |
string[] |
[] |
Activity types to skip |
sendActivityStartEvent |
boolean |
true |
Emit ActivityStarted events |
If you want OpenBox to create the Temporal Worker for you:
import { createOpenBoxWorker } from 'openbox-temporal-sdk';
const worker = await createOpenBoxWorker({
temporalAddress: 'localhost:7233',
taskQueue: 'my-task-queue',
workflowsPath: require.resolve('./workflows'),
activities: myActivities,
openboxUrl: process.env.OPENBOX_API_URL!,
openboxApiKey: process.env.OPENBOX_API_KEY!,
agentDid: process.env.OPENBOX_AGENT_DID,
agentPrivateKey: process.env.OPENBOX_AGENT_PRIVATE_KEY,
});
await worker.run();fetch(Node.js built-in)axiosgotundicinode-fetch
- PostgreSQL (
pg) - MySQL (
mysql2) - MongoDB
- Redis (
redis,ioredis) - TypeORM / Knex (via query hooks)
When OpenBox evaluates an operation, it returns one of:
| Verdict | Behaviour |
|---|---|
allow |
Execution continues normally |
block |
Throws GovernanceBlockedError — stops the current activity |
halt |
Throws GovernanceBlockedError — signals workflow to terminate |
require_approval |
Pauses execution pending human approval (HITL) |
Catch these in your activities:
import { GovernanceBlockedError } from 'openbox-temporal-sdk';
try {
const result = await fetch('https://api.example.com/data');
} catch (e) {
if (e instanceof GovernanceBlockedError) {
console.log(`Blocked: ${e.verdict.value} — ${e.reason}`);
throw e; // re-throw to surface to Temporal
}
}Set OPENBOX_DEBUG=1 to enable verbose SDK logging:
OPENBOX_DEBUG=1 npx ts-node your-worker.ts# Full lifecycle test — sends all 9 event types to OpenBox dashboard
npx ts-node --project tsconfig.json test-lifecycle.ts
# Quick smoke test — single WorkflowStarted event
npx ts-node --project tsconfig.json test-run.tsVerify results in your OpenBox dashboard.
npm run build # compile to dist/
npm run build:watch # watch mode
npm test # run jest tests
npm run lint # eslintsrc/
index.ts # Public API surface
plugin.ts # OpenBoxPlugin (Temporal SimplePlugin)
worker.ts # createOpenBoxWorker()
config.ts # GovernanceConfig, initialize(), Ed25519Signer
activity_interceptor.ts # ActivityGovernanceInterceptor
workflow_interceptor.ts # WorkflowGovernanceInterceptor
hook_governance.ts # Per-operation governance evaluation (HTTP/DB hooks)
http_governance_hooks.ts # OTel HTTP instrumentation hooks
db_governance_hooks.ts # OTel database instrumentation hooks
span_processor.ts # WorkflowSpanProcessor (bounded LRU maps)
request_signing.ts # AIP Ed25519 signed-request construction + retry
activities.ts # GovernanceActivities (sendGovernanceEvent)
errors.ts # Full error hierarchy
types.ts # WorkflowEventType, Verdict, etc.
otel_setup.ts # OpenTelemetry setup
tracing.ts # @traced decorator, createSpan
client.ts # GovernanceClient
hitl.ts # Human-in-the-loop helpers
verdict_handler.ts # enforceVerdict()
context_propagation.ts # AsyncLocalStorage context helpers
- All requests to OpenBox Core are signed with Ed25519 using the AIP DID protocol
- The
agentPrivateKeynever leaves your process — only the signature is transmitted - Store credentials in
.env(never commit them — see.gitignore) - Use
obx_test_...keys in development,obx_live_...in production