TypeScript SDK
Use TypeScript for Node services, web backends, internal tools, and guarded business-action wrappers.
Reference install
npm install @haltstate/sdkFirst-party TypeScript SDK
Package: @haltstate/sdk
Version: 1.0.2
Status: first-party implementation; build verified; automated test coverage pending.
SDK guard call
import { HaltStateClient, ApprovalPending, ActionDenied } from '@haltstate/sdk';
const client = new HaltStateClient({
tenantId: process.env.HALTSTATE_TENANT_ID!,
apiKey: process.env.HALTSTATE_API_KEY!,
baseUrl: 'https://haltstate.ai',
agentId: 'retail-refund-agent',
failOpen: false,
});
try {
const permit = await client.guard('refund.create', {
params: { amount: 126, currency: 'USD' },
idempotencyKey: `refund:${ledgerEntryId}`,
});
await executeRefundOnce(ledgerEntryId, permit);
} catch (error) {
if (error instanceof ApprovalPending) return;
if (error instanceof ActionDenied) return;
throw error;
}Raw HTTP fallback
Prefer the SDK for normal Node workers. If a constrained runtime cannot use the package, call the branded governance namespace directly: POST /api/haltstate/sentinel/action/guard. The older /api/sentinel/* path remains a compatibility alias, not the lead public contract.
Browser boundary
Do not place privileged HaltState keys in public frontend code. Browser dashboards should call your backend, and your backend should call HaltState with server-side credentials.
Client configuration
const client = new HaltStateClient({
tenantId: process.env.HALTSTATE_TENANT_ID!,
apiKey: process.env.HALTSTATE_API_KEY!,
baseUrl: 'https://haltstate.ai',
timeout: 30,
failOpen: false,
retryCount: 3,
agentId: 'retail-refund-agent',
});Guard and report
import { HaltStateClient, ApprovalPending, ActionDenied, ActionExpired } from '@haltstate/sdk';
try {
const permit = await client.guard('deploy_to_production', {
params: { version: '2.0.0', environment: 'prod' },
idempotencyKey: `deploy-${buildId}`,
agentId: 'deploy-agent',
});
await deploy(permit);
} catch (error) {
if (error instanceof ApprovalPending) return;
if (error instanceof ActionDenied) return;
if (error instanceof ActionExpired) return;
throw error;
}withGuard helper
const result = await client.withGuard(
'customer.email.send',
{
params: { template: 'refund-followup', customerRisk: 'medium' },
idempotencyKey: `email:${message.id}`,
},
async (permit) => sendCustomerEmail(message, permit)
);Error hierarchy and type guards
import { isControlFlowSignal, isHaltStateError } from '@haltstate/sdk';
try {
await client.guard('refund.create', { idempotencyKey: `refund:${id}` });
} catch (error) {
if (isControlFlowSignal(error)) {
// ApprovalPending, ActionDenied, or ActionExpired.
return;
}
if (isHaltStateError(error)) {
console.error('HaltState error:', error.message);
}
throw error;
}Kill switch client option
Node agents can enable background kill-switch checks when they are long-running. Keep that capability server-side and paired with explicit shutdown behavior so a remote kill signal cannot leave a partial business action half-written.
Implementation notes
Keep the HaltState call as close as possible to the side effect. The agent may plan and draft freely, but the wrapper around the actual action should be the place where authority is checked. That wrapper should send only the context required for policy evaluation: safe identifiers, normalized amounts, action names, risk flags, schedule windows, and redaction status. Raw customer payloads and secrets should stay in the business system or protected operator tooling.
Operational evidence
For each action, preserve the decision, the worker outcome, the idempotency key, safe resource references, latency, proof status, and redaction status. This evidence supports incident response and control narratives because it shows what the system did at runtime rather than only describing what the policy document intended. HaltState supports alignment work; it is not a substitute for legal advice or a compliance certification.