JSPM

@stacksona/sdk

0.2.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 21
  • Score
    100M100P100Q70733F
  • License MIT

TypeScript SDK for Stacksona Gate AI agent observability, approvals and audit events.

Package Exports

  • @stacksona/sdk
  • @stacksona/sdk/dist/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@stacksona/sdk) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

@stacksona/sdk

TypeScript and JavaScript SDK for Stacksona Gate, the approval and audit layer for AI agents.

@stacksona/sdk lets AI agents log task events, request approval before gated actions, wait for human review, validate signed approval tokens, and safely continue only when Stacksona Gate allows or approves the action.

Use it to add human-in-the-loop approvals, audit logs, and runtime AI governance to your agent workflows with a simple Node.js SDK.

Stacksona AI Observability and Approval Layer

What it does

Stacksona Gate helps agents pause before sensitive actions and route those actions through an approval workflow.

With this SDK, your app or agent can:

  • Log agent task events for observability and audit trails
  • Request a decision before a gated action
  • Automatically wait for human approval or rejection
  • Validate signed one-time approval tokens
  • Execute approved actions safely
  • Track decision status by task or thread
  • Add a policy and approval layer to existing agent tools
  • Send revision events when a reviewer requests changes to a pending decision

Install

npm install @stacksona/sdk

Requirements

  • Node.js 18 or later
  • TypeScript or JavaScript project
  • A Stacksona Gate workspace
  • A Stacksona API key
  • Your Stacksona Gate URL

Environment variables

STACKSONA_GATE_URL=https://your-gate-subdomain.stacksona.cloud
STACKSONA_API_KEY=sg_your_api_key

baseUrl is required. Do not hard-code the example URL unless that is your actual Stacksona Gate tenant. Gate instances may use different subdomains.

Quick start: gate an action

Use runGatedAction for the normal integration path.

It requests a decision, waits when human review is required, validates signed approval tokens when enabled, and only executes your function when Stacksona Gate allows or approves the action.

import { StacksonaGateClient } from '@stacksona/sdk';

const gate = new StacksonaGateClient({
  baseUrl: process.env.STACKSONA_GATE_URL!,
  apiKey: process.env.STACKSONA_API_KEY!,
});

await gate.logEvent({
  taskId: 'task-abc-123',
  eventType: 'task.started',
  eventSummary: 'Customer requested refund of $500',
  payload: { customer_id: 'cus_99' },
});

const { decision, executed, result } = await gate.runGatedAction(
  {
    taskId: 'task-abc-123',
    workflowName: 'Customer Support',
    taskLabel: 'Refund request - Order #8821',
    toolName: 'issue_refund',
    subject: 'Issue refund of $500 to customer cus_99',
    riskLevel: 'high',
    summary: ['Order placed 14 days ago', 'No tracking movement'],
    payload: { amount: 500, currency: 'usd' },
  },
  async () => issueRefund({ amount: 500, currency: 'usd', customerId: 'cus_99' }),
  { validateSignedApprovalToken: true },
);

if (!executed) {
  console.log(`Action did not run: ${decision.status}`);
}

Manual approval flow

Use the lower-level methods when you need custom control over routing, timing, UI state, or execution.

const decision = await gate.requestDecision({
  taskId: 'task-abc-123',
  workflowName: 'Customer Support',
  taskLabel: 'Refund request - Order #8821',
  toolName: 'issue_refund',
  subject: 'Issue refund of $500 to customer cus_99',
  riskLevel: 'high',
  payload: { amount: 500, currency: 'usd' },
});

if (decision.status === 'allow') {
  await issueRefund();
}

if (decision.status === 'pending_review') {
  const finalDecision = await gate.pollDecision({ thread_id: decision.thread_id! });

  if (finalDecision.status === 'approved') {
    await issueRefund();
  }
}

Signed approval token validation

Signed approval tokens provide proof that a gated action was approved before execution.

const finalDecision = await gate.pollDecision({ thread_id: 'THR-4F2A9C1B' });

if (finalDecision.status === 'approved' && finalDecision.approval_token) {
  const validation = await gate.validateApprovalToken({
    taskId: finalDecision.task_id,
    signature: finalDecision.approval_token,
  });

  if (!validation.valid) {
    throw new Error(validation.reason ?? 'Approval token invalid');
  }
}

Main methods

logEvent(input)

Sends timeline context to Stacksona Gate reviewers.

Use this for agent observability, task history, audit logs, and reviewer context.

await gate.logEvent({
  taskId: 'task-abc-123',
  eventType: 'task.started',
  eventSummary: 'Customer requested refund for order #8821',
  payload: {
    customer_id: 'cus_99',
    order_id: 'ord_8821',
  },
});

logRevision(input)

Sends a request revision event to an existing pending review thread.

Use this when a reviewer asks the agent to change or modify a pending request before approval. The SDK sends a normal task event to Gate with the official revision event type format:

revision.{taskId}.{threadId}

Gate uses the taskId to keep the event tied to the running task and the threadId to update the exact pending decision thread. No new revision endpoint is used.

Revision events only apply while the target thread is still awaiting a reviewer decision, such as needs_review or escalated. Once a thread is approved or denied, that decision is final for the thread and the agent must not revise it in place.

await gate.logRevision({
  taskId: 'task-abc-123',
  threadId: 'THR-XXXXXXXX',
  revisionId: 'rev-002',
  workflowName: 'Customer Support',
  taskLabel: 'Refund request - Order #8821',
  toolName: 'issue_refund',
  subject: 'Approve conditional refund for customer cus_99',
  preview: 'Refund releases only after the prepaid return label is scanned.',
  riskLevel: 'high',
  summary: [
    'Reviewer requested a conditional refund',
    'Agent revised the proposal to wait for return-label scan',
  ],
  requestPayload: {
    amount: 500,
    currency: 'usd',
    release_condition: 'return_label_scanned',
  },
});

The SDK accepts camelCase fields and sends Gate the official snake_case revision payload:

{
  "event_type": "revision.task-abc-123.THR-XXXXXXXX",
  "event_summary": "Agent revised the request after reviewer feedback.",
  "payload": {
    "revision": {
      "revision_id": "rev-002",
      "workflow_name": "Customer Support",
      "task_label": "Refund request - Order #8821",
      "tool_name": "issue_refund",
      "subject": "Approve conditional refund for customer cus_99",
      "preview": "Refund releases only after the prepaid return label is scanned.",
      "risk_level": "high",
      "summary": [
        "Reviewer requested a conditional refund",
        "Agent revised the proposal to wait for return-label scan"
      ],
      "request_payload": {
        "amount": 500,
        "currency": "usd",
        "release_condition": "return_label_scanned"
      }
    }
  }
}

Revision payload fields

SDK field Sent to Gate as Description
revisionId revision_id Stable identifier for this revision, such as rev-001 or rev-002.
workflowName workflow_name Workflow name, same as the original decision request.
taskLabel task_label Human-readable task label shown to reviewers.
toolName tool_name Tool name being requested, same as the original decision request.
subject subject Updated subject line describing the revised action.
preview preview Optional human-readable description of the revised proposal.
riskLevel risk_level Risk level of the revised request.
summary summary Array of strings summarizing the revision context for the reviewer.
requestPayload request_payload The revised tool payload evaluated through Gate's standard decision rules.

After sending a revision event, resume polling on the same thread. Gate updates the pending decision with the revised request, re-evaluates the revised request_payload, and prevents approval of superseded stale revisions.

await gate.logRevision({
  taskId: 'task-abc-123',
  threadId: 'THR-XXXXXXXX',
  revisionId: 'rev-003',
  workflowName: 'Customer Support',
  taskLabel: 'Refund request - Order #8821',
  toolName: 'issue_refund',
  subject: 'Approve conditional refund for customer cus_99',
  preview: 'Refund releases only after return-label scan.',
  riskLevel: 'high',
  requestPayload: {
    amount: 500,
    currency: 'usd',
    release_condition: 'return_label_scanned',
  },
});

const finalDecision = await gate.pollDecision({ thread_id: 'THR-XXXXXXXX' });

if (finalDecision.status === 'approved') {
  await issueConditionalRefund({ releaseCondition: 'return_label_scanned' });
}

For advanced integrations, you can still send the same revision manually with logEvent() by setting eventType to revision.{taskId}.{threadId} and using the official payload.revision snake_case shape.


requestDecision(input)

Asks Stacksona Gate to allow, reject, or create a review thread for a gated action.

Use this before an agent takes a sensitive, risky, expensive, external, or policy-controlled action.

getDecision(query)

Checks the status of a decision by thread_id or task_id.

Use this when you need to refresh approval status from your own UI or workflow.

pollDecision(query, options)

Waits until a pending decision is approved or rejected.

The SDK uses recommended_poll_after_seconds when Stacksona Gate returns it. Otherwise, the fallback polling interval defaults to 15 seconds.

requestDecisionAndPoll(input, options)

Requests a decision and waits automatically when the result is pending_review.

Use this when you want a direct approval flow but still want to control action execution yourself.

validateApprovalToken(input)

Validates one-time approval tokens server-side.

Use this when signed approval tokens are enabled and you need proof that an action was approved before execution.

runGatedAction(input, action, options)

Helper that executes action only after the request is allowed or approved.

Use this for the fastest and safest integration path.

Common use cases

Use @stacksona/sdk when your AI agent needs approval before actions like:

  • Sending emails
  • Issuing refunds
  • Updating customer records
  • Calling external APIs
  • Running automations
  • Deploying code
  • Changing account settings
  • Accessing sensitive data
  • Triggering financial or operational workflows

Field compatibility

The public SDK accepts camelCase fields like:

  • workflowName
  • taskLabel
  • toolName
  • eventType
  • eventSummary

The SDK automatically serializes these fields to the snake_case API wire format.

Older positional forms, such as requestDecision(taskId, input), still work for compatibility.

TypeScript support

@stacksona/sdk is built for TypeScript and JavaScript projects.

It includes typed client methods for logging events, requesting decisions, polling approval status, validating approval tokens, and running gated actions.

Keywords

Stacksona Gate, AI agent approval, TypeScript SDK, JavaScript SDK, human-in-the-loop AI, agent audit logs, AI observability, runtime AI governance, approval workflow, AI policy layer, gated actions, agent safety, decision workflow.