JSPM

@stacksona/agent-tools

1.0.3
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 23
  • Score
    100M100P100Q69385F
  • License MIT

Deterministic tools for AI agents by Stacksona: calculator, schema, JSON paths, policy, secrets, URL/file/table validation, OCR, image annotation, proof events, action fingerprinting, HTTP request inspection, and timezone-aware time checks.

Package Exports

  • @stacksona/agent-tools
  • @stacksona/agent-tools/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/agent-tools) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

@stacksona/agent-tools

Deterministic tools for AI agent workflows by Stacksona.

Website: https://stacksona.com

@stacksona/agent-tools is a standalone package for running deterministic utility tools from a CLI, TypeScript imports, or an MCP server. It can also produce Stacksona-compatible runtime event objects for use with the Stacksona SDK, but it does not import or require the SDK.

The package includes tools for safe calculation, schema validation, JSON path operations, table profiling and validation, URL checks, deterministic policy evaluation, portable policy strings, HMAC signatures, secret scanning, file inspection, hashing, text utilities, OCR, image annotation, basic image inspection, lightweight C2PA marker checks, action fingerprinting, HTTP request inspection, timezone-aware current time, time-window checks, and proof-wrapped outputs.

Each tool returns a structured response with:

  • a result
  • a deterministic explanation
  • input and output hashes
  • a replay-friendly proof envelope
  • redacted canonical input by default
  • structured errors with message and code
  • separate audit metadata for timestamps
  • bounded file and provenance scanning for chunked hashing and inspection

The goal is to move repeatable agent work out of prompts and into deterministic code paths that can be inspected, replayed, and logged.

Package

Install

npm install -g @stacksona/agent-tools

Or run without global install:

npx @stacksona/agent-tools list

Requirements

  • Node.js 18+
  • OCR requires a local tesseract binary
  • image.color_summary and image.average_hash require local ImageMagick convert
  • MCP mode requires an MCP-compatible client

Security controls for file, image, and OCR tools can be set in code or through environment variables. For library usage, prefer the explicit runtime config API:

import { configureAgentTools } from "@stacksona/agent-tools";

configureAgentTools({
  profile: "prod",
  allowedRoots: ["/safe/root"],
  maxFileBytes: 10 * 1024 * 1024,
  maxTableRows: 5000,
  maxPolicyValueDepth: 48
});

Environment variables are also supported for CLI and container deployments:

  • Set STACKSONA_AGENT_TOOLS_PROFILE=prod for tighter default limits.
  • Set STACKSONA_AGENT_TOOLS_ALLOWED_ROOTS=/safe/root to restrict readable and writable paths.
  • Set STACKSONA_AGENT_TOOLS_MCP_MODE=true; file tools then require STACKSONA_AGENT_TOOLS_ENABLE_FILE_TOOLS=true.
  • Set STACKSONA_AGENT_TOOLS_DISABLE_FILE_TOOLS=true to block all local file tools.
  • Optional limits: STACKSONA_AGENT_TOOLS_MAX_FILE_BYTES, STACKSONA_AGENT_TOOLS_MAX_TABLE_BYTES, STACKSONA_AGENT_TOOLS_MAX_TABLE_ROWS, STACKSONA_AGENT_TOOLS_MAX_POLICY_STRING_BYTES, STACKSONA_AGENT_TOOLS_MAX_POLICY_VALUE_DEPTH.

Security and error shape

Tool failures return a structured error object:

{
  "ok": false,
  "error": {
    "message": "human-readable failure reason",
    "code": "TOOL_EXECUTION_FAILED"
  }
}

Unknown tools use code: "UNKNOWN_TOOL".

Proof envelopes keep input_hash based on the original canonical input for replay and audit integrity, while proof.canonical_input is redacted by default. Secret-like values are redacted even when they appear inside generic string fields, not only when the field name is secret or token.

For example, secret.scan accepts both text and value inputs and redacts bearer tokens, Stripe-like keys, Stacksona sg_... keys, GitHub tokens, JWTs, AWS access keys, private keys, connection strings, and environment-style secret assignments before exposing canonical input.

stacksona-agent-tools call secret.scan '{"text":"Bearer sk_test_1234567890abcdef","include_context":true}'
stacksona-agent-tools call secret.scan '{"text":"sg_1234567890abcdef","include_context":true}'

The result includes fingerprints, previews, and optional redacted context. It does not return full secret values.

Repository layout

The source is split by feature so src/index.ts stays as the public entrypoint instead of a large implementation file:

src/core/             Shared types, canonicalization, envelopes, safety, versioning
src/tools/            Feature modules grouped by capability
src/tools/calculator.ts
src/tools/security.ts
src/tools/json.ts
src/tools/policy.ts
src/tools/text.ts
src/tools/workflow.ts
src/tools/action.ts
src/tools/http.ts
src/tools/time.ts
src/tools/url.ts
src/tools/table.ts
src/tools/file.ts
src/tools/image.ts
src/tools/provenance.ts
src/definitions.ts    Tool definitions and schemas
src/registry.ts       Tool dispatch
src/events.ts         Stacksona-compatible runtime events
src/cli.ts            CLI and MCP server entry
src/index.ts          Public exports and bin entrypoint

CLI

List tools:

stacksona-agent-tools list

Run a request file:

stacksona-agent-tools run examples/calculator.request.json

Call a tool directly:

stacksona-agent-tools call calculator.evaluate '{"expression":"round_money(refund_amount(249.99, 49.99))"}'

Start the MCP server:

stacksona-agent-tools mcp

Claude Desktop MCP config

{
  "mcpServers": {
    "stacksona-agent-tools": {
      "command": "stacksona-agent-tools",
      "args": ["mcp"]
    }
  }
}

Stacksona SDK-compatible event logging

The package does not depend on @stacksona/sdk. Instead, it can produce the same runtime event shape the SDK sends with emitRuntimeEvent.

Standalone event creation:

import { buildToolCallProposedEvent, buildToolCallResultEvent, runTool } from "@stacksona/agent-tools";

const proposed = buildToolCallProposedEvent({
  tenant_id: "tenant_123",
  session_id: "sess_123",
  task_id: "refund-123",
  tool: "calculator.evaluate",
  input: { expression: "249.99 - 49.99" }
});

const response = await runTool("calculator.evaluate", {
  expression: "249.99 - 49.99"
});

const result = buildToolCallResultEvent({
  tenant_id: "tenant_123",
  session_id: "sess_123",
  task_id: "refund-123",
  tool: "calculator.evaluate",
  input: { expression: "249.99 - 49.99" },
  response
});

With the Stacksona SDK on npm, pass the SDK method as an optional emitter:

import { runToolWithEvents } from "@stacksona/agent-tools";
import { StacksonaClient } from "@stacksona/sdk";

const stacksona = new StacksonaClient({ baseUrl, token });

const { response } = await runToolWithEvents({
  tenant_id,
  session_id,
  task_id: "refund-123",
  tool: "calculator.evaluate",
  input: { expression: "249.99 - 49.99" },
  emit: (event) => stacksona.emitRuntimeEvent(event)
});

That emits:

tool.call.proposed
tool.call.result

If the tool fails, the second event becomes:

tool.call.failed

Tool usage is represented as task and session history. Later approval requests do not need attached event references because Stacksona can review the session event stream.

Tool categories

Calculation and security

Tool Purpose
calculator.evaluate Safe arithmetic, statistics, formulas, constants, and unit conversion
password.policy_check Check a password against a deterministic policy
security.hash SHA-256 or SHA-512 hashing
security.hmac HMAC generation

Proof and data

Tool Purpose
proof.create Create deterministic input/output hashes
proof.verify Verify a proof envelope
json.format Stable pretty-print JSON
json.diff Deterministic JSON diff
schema.validate JSON Schema subset validation
json.path_get Get a nested JSON path
json.path_set Set a nested JSON path on a copy
json.path_remove Remove a nested JSON path on a copy
json.path_exists Check whether a nested JSON path exists

Text and output quality

Tool Purpose
text.redact_sensitive Redact common sensitive patterns
text.extract Extract emails, URLs, phones, hashtags
text.slugify Deterministic slug generation
output.check_constraints Check required sections, phrase bans, word limits
output.find_missing_fields Find missing required object fields
template.render Render safe {{path}} templates and report missing values

Risk and decision support

Tool Purpose
math.weighted_score Rank options with explicit weights
math.percent_change Percent change calculator
date.deadline_status Determine overdue/due soon status
risk.detect_sensitive_fields Detect sensitive-looking keys and values
risk.requires_approval Rule-based approval recommendation
action.fingerprint Stable SHA-256 fingerprint for exact agent actions
http.request_inspect Inspect planned HTTP requests before execution
time.current Return the current time in a requested IANA timezone
time.window_check Check whether an action is inside an allowed day/time window
policy.evaluate Deterministic if/then policy evaluation
policy.compile Compile a policy object into a portable stp1... policy string
policy.decode Decode and verify a portable policy string
policy.verify Verify a policy string hash, optional expected hash, and optional signature secret
policy.sign Sign a policy string with HMAC-SHA256
policy.verify_signature Verify a signed policy string
policy.explain Generate deterministic plain-text policy explanations
policy.run Run values through a policy string and return output and trace
secret.scan Pattern-based secret/token scanner
url.inspect Local URL parser and safety classifier
url.allowlist_check Deterministic URL allowlist check
table.profile Profile CSV or row data
table.validate Validate CSV or row data against rules

Files, images, and provenance

Tool Purpose
file.checksum File checksum
file.inspect Size, extension, MIME guess, text/binary, SHA-256, and constraints
image.metadata Read image dimensions
image.annotate_boxes Draw boxes and labels by writing an annotated SVG
image.color_summary Average RGB and coarse color buckets
image.average_hash 8x8 average hash
ocr.extract_text OCR with optional word boxes
provenance.c2pa_check Lightweight C2PA/content-credentials marker scan

Agent action governance examples

Fingerprint an exact action before approval:

stacksona-agent-tools call action.fingerprint '{"action":{"type":"refund","amount":2500,"currency":"usd","customer_id":"cus_123"}}'

Score an action before deciding whether to gate it:

Inspect a planned HTTP request before an agent executes it:

stacksona-agent-tools call http.request_inspect '{"method":"POST","url":"https://api.stripe.com/v1/refunds","headers":{"Authorization":"Bearer sk_live_redacted"},"body":{"charge":"ch_123","amount":2500}}'

Check whether an action is inside an allowed operating window:

stacksona-agent-tools call time.current '{"timezone":"America/Chicago"}'
stacksona-agent-tools call time.window_check '{"now":"2026-06-17T19:00:00-05:00","timezone":"America/Chicago","allowed_days":["mon","tue","wed","thu","fri"],"start":"09:00","end":"17:00"}'

Workflow validation examples

Schema validation:

stacksona-agent-tools call schema.validate '{"schema":{"type":"object","required":["amount"],"properties":{"amount":{"type":"number","minimum":100}}},"data":{"amount":200}}'

JSON path updates:

stacksona-agent-tools call json.path_set '{"value":{"customer":{"plan":"trial"}},"path":"customer.plan","set_value":"paid"}'

URL safety checks:

stacksona-agent-tools call url.allowlist_check '{"url":"https://api.stripe.com/v1/refunds","allowed_hosts":["api.stripe.com"]}'

Policy evaluation:

stacksona-agent-tools call policy.evaluate '{"facts":{"action":"refund","amount":250},"rules":[{"id":"refund_threshold","if":{"action":"refund","amount":{"gte":100}},"then":{"requires_approval":true,"reason":"refund_above_threshold"}}]}'

Portable policy strings:

Compile a policy object into a portable string:

stacksona-agent-tools call policy.compile '{"policy":{"name":"Refund policy","version":1,"mode":"first_match","limits":{"allowed_tools":["schema.validate","calculator.evaluate"],"max_steps":10},"steps":[{"id":"validate_request","tool":"schema.validate","with":{"schema":{"type":"object","required":["action","amount"],"properties":{"action":{"type":"string"},"amount":{"type":"number","minimum":0}}},"data":"$values"},"save_as":"validation"},{"id":"calculate_amount","when":{"$validation.valid":true},"tool":"calculator.evaluate","with":{"expression":"$request.expression"},"save_as":"calculation"},{"id":"large_refund","match":{"action":"refund","amount":{"gte":100},"$calculation.value":{"gte":100}},"output":{"decision":"require_approval","reason":"refund_amount_above_threshold","calculated_amount":"$calculation.value"}}],"default_output":{"decision":"allow","reason":"no_policy_match"}}}'

Explain that exact policy string in plain English:

stacksona-agent-tools call policy.explain '{"policy_string":"stp1.<base64url-policy>.<sha256_hash>"}'

Sign and verify a policy string:

stacksona-agent-tools call policy.sign '{"policy_string":"stp1.<base64url-policy>.<sha256_hash>","secret":"issuer-secret"}'
stacksona-agent-tools call policy.verify_signature '{"policy_string":"stp1.<base64url-policy>.<sha256_hash>.<hmac_signature>","secret":"issuer-secret"}'

Run request values through that exact policy string:

stacksona-agent-tools call policy.run '{"policy_string":"stp1.<base64url-policy>.<sha256_hash>","values":{"action":"refund","amount":200,"expression":"249.99 - 49.99"}}'

The explanation result includes a stable plain-text policy summary for business users and reviewers. The run result includes the final policy output, policy hash, values hash, matched steps, and deterministic trace.

The policy string format is:

stp1.<base64url-canonical-policy-json>.<sha256_policy_hash>

Base64url is only used for portability. Trust comes from canonical JSON, SHA-256 verification, and optional expected-hash verification with policy.verify.

policy.run enforces its tool allowlist at execution time. A crafted policy string cannot expand limits.allowed_tools beyond the built-in deterministic policy-runtime allowlist. policy.compile also rejects policy steps that request tools outside the configured allowlist, so invalid policies fail early while runtime still protects against hand-crafted strings.

Policy value resolution is depth-guarded with limits.max_resolution_depth and limits.max_value_depth, capped by runtime config. Deeply nested with, match, or output templates fail explicitly instead of recursing to arbitrary depth.

Table validation:

stacksona-agent-tools call table.validate '{"csv":"email,amount\na@example.com,100\nb@example.com,250","required_columns":["email","amount"],"column_rules":[{"column":"amount","type":"number","min":0}]}'

Secret scanning:

stacksona-agent-tools call secret.scan '{"text":"Authorization: Bearer sk_test_1234567890abcdef","include_context":true}'

Calculator capabilities

calculator.evaluate is a deterministic parser, not JavaScript eval.

It supports:

Operators: +, -, *, /, %, ^
Grouping: ( ... )
Decimals and scientific notation
Constants: pi, e
Basic functions: sqrt, abs, floor, ceil, round, min, max
Statistics: sum, average / avg, median
Bounds and percentages: clamp, percent, percentage / as_percent
Money rounding: round_money / money_round
Logs and trig: log, ln, sin, cos, tan
Unit conversion: convert(value, "from", "to") / unit(value, "from", "to")
Formula templates: refund_amount, weighted_total

Examples:

stacksona-agent-tools call calculator.evaluate '{"expression":"sum(10, 20, 30)"}'
stacksona-agent-tools call calculator.evaluate '{"expression":"round_money(10.005)"}'
stacksona-agent-tools call calculator.evaluate '{"expression":"percent(15, 200)"}'
stacksona-agent-tools call calculator.evaluate '{"expression":"percentage(30, 200)"}'
stacksona-agent-tools call calculator.evaluate '{"expression":"convert(1, "mi", "ft")"}'
stacksona-agent-tools call calculator.evaluate '{"expression":"convert(100, "c", "f")"}'
stacksona-agent-tools call calculator.evaluate '{"expression":"refund_amount(249.99, 49.99)"}'
stacksona-agent-tools call calculator.evaluate '{"expression":"weighted_total(9, .4, 5, .2, 7, .4)"}'

Supported unit groups include length, mass, volume, time, digital data, and temperature. Temperature conversion supports Celsius, Fahrenheit, and Kelvin. Trig functions use radians.

percent(rate, base) returns a percent-of calculation, so percent(15, 200) returns 30.

percentage(part, total) returns part as a percent of total, so percentage(30, 200) returns 15.

Bounding-box annotation

This tool is deterministic because the caller supplies the box coordinates. The tool applies them exactly as requested and returns a new annotated SVG.

Example:

{
  "tool": "image.annotate_boxes",
  "input": {
    "path": "./image.png",
    "output_path": "./image.annotated.svg",
    "boxes": [
      { "x": 20, "y": 18, "width": 80, "height": 42, "label": "Title", "color": "#ff3b30" },
      { "x": 120, "y": 90, "width": 64, "height": 64, "label": "Logo", "color": "#007aff" }
    ]
  }
}

OCR with boxes

stacksona-agent-tools call ocr.extract_text '{"path":"./receipt.png","include_boxes":true}'

This returns extracted text and, when requested, word-level bounding boxes from Tesseract TSV output.

Example response shape

{
  "ok": true,
  "tool": "calculator.evaluate",
  "result": {
    "expression": "(12.5 * 4) + sqrt(81)",
    "value": 59
  },
  "explanation": {
    "summary": "Safely evaluated the arithmetic expression.",
    "steps": [
      "Tokenized the expression.",
      "Parsed operators and functions with a deterministic grammar.",
      "Rounded the numeric result to precision 12."
    ]
  },
  "proof": {
    "proof_id": "sat_...",
    "input_hash": "sha256:...",
    "output_hash": "sha256:...",
    "result_hash": "sha256:...",
    "canonical_input": "...redacted...",
    "canonical_input_redacted": true,
    "replayable": true,
    "deterministic": true,
    "package_version": "1.0.0"
  },
  "audit": {
    "issued_at": "2026-06-10T00:00:00.000Z",
    "envelope_hash": "sha256:..."
  }
}

Testing

Run the included package tests:

npm test

Run deterministic performance checks:

npm run bench

OCR success tests automatically skip when Tesseract is not installed. The missing-binary behavior is still tested so environments without OCR support fail safely instead of crashing.

Performance notes

High-volume paths are bounded and avoid unnecessary quadratic or full-file memory behavior:

  • json.diff walks JSON once and avoids repeated whole-subtree JSON.stringify comparisons.
  • file.checksum hashes files in fixed-size chunks.
  • file.inspect uses chunked reads for hashes and line counts, plus a small byte sample for binary detection.
  • provenance.c2pa_check scans marker strings in fixed-size chunks with overlap handling.
  • Table, policy, regex, and file tools have configurable input limits.
  • policy.run has an explicit policy value resolution depth guard for nested with, match, and output templates.

Run deterministic performance benchmarks:

npm run bench

The benchmark covers large JSON diffs, table profiling, secret scanning, and policy execution.

Notes on determinism

The package separates deterministic proof data from audit metadata. Timestamps live in audit, not in the deterministic proof body. Sensitive inputs are redacted from proof.canonical_input and Stacksona-compatible event arguments by default. Raw input is still represented by input_hash.

Scope Replayable/deterministic status Integrator note
Calculator, schema, JSON paths, JSON diff, URL checks, table validation, policy strings, policy signatures, secret scanning, risk checks, template rendering, hashing Deterministic Same input and same package version produce the same deterministic result.
date.deadline_status with caller-supplied now Replayable Pass now for audit and replay workflows.
date.deadline_status without now Not replayable The tool uses wall-clock time and marks proof.replayable=false.
file.checksum, file.inspect, provenance.c2pa_check Deterministic for the same file bytes and config File tools are bounded, sandboxable, and use streaming/chunked reads.
ocr.extract_text Deterministic relative to local Tesseract version/configuration Missing Tesseract is returned as a normal tool error response.
image.color_summary, image.average_hash Deterministic relative to local ImageMagick convert version/configuration Missing ImageMagick is returned as a normal tool error response.
image.annotate_boxes Deterministic Caller supplies exact boxes; the tool applies them exactly.
provenance.c2pa_check Lightweight deterministic marker scan Not full C2PA manifest-chain validation.

Use with Stacksona Gate

This package can run independently or alongside Stacksona Gate.

A typical Stacksona flow:

Agent uses @stacksona/agent-tools
↓
Tool returns result, explanation, hashes, and proof
↓
Agent sends the proof envelope into Stacksona Gate
↓
Reviewer approves or rejects with deterministic context attached

@stacksona/agent-tools records what was run and how the result was produced.

Stacksona Gate controls whether the agent should proceed.