agent-action-guard
v1.2.2
Published
TypeScript runtime for screening AI agent actions as safe, harmful, or unethical.
Maintainers
Readme
Install
npm install agent-action-guardOr with pnpm:
pnpm add agent-action-guardNode.js 20+ · ESM · usable with zero embedding configuration. The runtime compatibility matrix covers Node.js 20, 22, 24, and 26.
On first use, Action Guard can automatically download and cache the default MiniLM ONNX embedding assets. You can also point it at your own local ONNX model or an OpenAI-compatible embedding API.
Why add Action Guard?
An AI agent can decide to call a tool even when the resulting action is unsafe. Action Guard gives you a dedicated checkpoint between the model deciding what to do and your application actually doing it.
- Block before execution — screen tool calls before they reach email, filesystem, API, database, or other side-effecting code.
- Minimal integration — classify an action directly or wrap a function with
actionGuarded(). - Local-first option — use cached ONNX embeddings without sending action text to an embedding API.
- Bring your own embeddings — use a custom ONNX model or OpenAI-compatible endpoint when needed.
- Batch + CLI support — classify multiple actions programmatically or from JSON/JSONL files.
- Built for agent loops — the package contains the runtime guard; training and benchmark tooling stay outside the TypeScript runtime package.
Agent Action Guard vs. Luna and Laya
Laya is a general-purpose local model that can also be used as an action-safety classifier similar to Agent Action Guard. The repository comparison benchmark evaluates Agent Action Guard, gpt-5.6-luna, and Laya on the same HarmActions rows. Local classifiers use CPU execution, and warm-up/model-loading time is excluded from the reported per-action latency.
Run the benchmark from the repository's Python package:
cd python
python scripts/compare_laya_harmactions.py| Model | HarmActions | Accuracy | Precision | Recall | F1 | ms/action | |---|---:|---:|---:|---:|---:|---:| | Agent Action Guard | 97.87% | 97.87% | 100.00% | 97.87% | 98.92% | 19.66 | | gpt-5.6-luna | 90.07% | 90.07% | 100.00% | 90.07% | 94.78% | 3381.72 | | Laya | 51.06% | 51.06% | 100.00% | 51.06% | 67.61% | 815.86 |
The benchmark uses the same HarmActions rows for all classifiers; CPU execution is forced for the local systems to make the latency comparison more consistent.
60-second quick start
1. Check a tool call before it runs
import { isActionHarmful } from 'agent-action-guard';
const action = {
type: 'function',
function: {
name: 'send_email',
arguments: {
to: '[email protected]',
subject: 'Status update',
body: 'Hello',
},
},
};
const { label, confidence } = await isActionHarmful(action);
if (label) {
throw new Error(`Blocked: ${label} (${confidence.toFixed(2)})`);
}
// Safe path: execute the real tool here.A safe action returns label: null. A classified harmful action returns its label plus a confidence score.
2. Guard a function automatically
import { actionGuarded } from 'agent-action-guard';
const guardedSendEmail = actionGuarded(
async function sendEmail(params) {
// Call your real email provider here.
return `sending to ${params.to}`;
},
{ confThreshold: 0.8 },
);
await guardedSendEmail({
to: '[email protected]',
subject: 'Status update',
body: 'Hello',
});actionGuarded() derives the action from the wrapped function name and its object argument. When a harmful classification meets the configured confidence threshold, it throws HarmfulActionError instead of executing the wrapped function.
3. Use a boolean safety gate
import { ensureActionSafety } from 'agent-action-guard';
const safe = await ensureActionSafety(action);
if (!safe) {
// Reject, escalate, log, or request approval.
}Or make harmful actions throw automatically:
await ensureActionSafety(action, { raiseException: true });Batch classification
Use the vectorized batch API when you already have multiple proposed actions:
import { isActionsHarmful } from 'agent-action-guard';
const decisions = await isActionsHarmful(actions, { batchSize: 32 });
for (const decision of decisions) {
console.log(decision.label, decision.confidence);
}CLI included
Installing the package also installs agent-action-guard.
agent-action-guard '{"type":"function","function":{"name":"send_email","arguments":{}}}'Classify JSON arrays or JSONL files in batches:
agent-action-guard --file actions.json --batch-size 32
agent-action-guard --file actions.jsonl --batch-size 32The CLI reports total, safe, and unsafe action counts. Start the local HTTP API with agent-action-guard serve; it binds to 127.0.0.1:8000 by default and exposes GET /health plus POST /v1/classify. Use --host, --port, and --batch-size to configure the server. See the repository USAGE.md for request and response examples.
The built-in HTTP service has no authentication or TLS; other local processes can reach it. For remote access, restrict network access and place it behind an authenticated TLS-terminating proxy. Action text may be sent to the configured embedding provider.
Embedding backends
You do not need to configure an embedding backend to try the package.
| Mode | When to use it |
| --- | --- |
| Zero-config local ONNX | Fastest path to getting started. Default MiniLM ONNX assets are downloaded and cached automatically. |
| Configured GGUF | Use a local file/directory, direct model URL, base URL ending in /, or Hugging Face owner/repo ID. Install node-llama-cpp. |
| Configured ONNX | Use a local file/directory, direct model URL, base URL ending in /, or Hugging Face owner/repo ID. |
| OpenAI-compatible API | Use an existing embedding service or centrally managed endpoint. |
Backend selection follows this precedence:
AAG_EMBED_GGUFconfigured GGUF sourceAAG_EMBED_ONNXconfigured ONNX source- Explicit
EMBED_MODEL_NAME - API configuration via
EMBEDDING_API_KEY,OPENAI_API_KEY, orEMBEDDING_BASE_URL - Automatically downloaded/cached default
sentence-transformers/all-MiniLM-L6-v2ONNX assets
If both model variables are set, GGUF takes precedence. Remote assets are cached under normalized filesystem-safe names derived from their source URLs. Hugging Face repo IDs resolve standard main/model.gguf or main/model.onnx filenames; use a direct URL for nonstandard GGUF filenames/quantizations. Direct ONNX URLs derive tokenizer sidecars from sibling URLs.
For environment variables, tokenizer files, custom endpoints, and configuration examples, see the full USAGE.md.
Public runtime API
import {
ActionClassifier,
HarmfulActionError,
actionGuarded,
ensureActionSafety,
isActionHarmful,
isActionsHarmful,
} from 'agent-action-guard';| API | Purpose |
| --- | --- |
| isActionHarmful(action) | Classify one proposed action and return { label, confidence }. |
| isActionsHarmful(actions, options) | Vectorized classification for multiple actions. |
| ensureActionSafety(action, options) | Return a boolean safety decision or throw on harmful actions. |
| actionGuarded(fn, options) | Wrap a function so harmful calls can be blocked before execution. |
| ActionClassifier | Create/configure a classifier instance directly. |
| HarmfulActionError | Error type thrown by blocking helpers. |
See examples/basic-usage.js for a minimal runnable example.
Where it fits
User request
↓
LLM / Agent
↓
Proposed tool call
↓
┌────────────────────┐
│ Agent Action Guard │ ← classify before execution
└────────────────────┘
↓ safe ↓ harmful
Execute tool Block / escalateUse Action Guard as a runtime safety layer alongside your existing authentication, authorization, validation, rate limits, allowlists, and human-approval policies.
Compatibility
The package supports Node.js 20+ and is tested across Node.js 20, 22, 24, and 26. Runtime dependency compatibility is tested separately across supported versions of @huggingface/tokenizers, onnxruntime-node, and the OpenAI JavaScript SDK.
For contributors:
npm test
npm run lint
npm run test:all-versions
npm run test:dependency-matrix-boundsThe broader dependency matrix is available with:
npm run test:dependency-matrixImportant limitation
Action Guard is a learned classifier, not a complete security boundary. For high-risk systems, combine its decision with deterministic policy checks, strict tool permissions, input validation, least-privilege credentials, and human approval where appropriate.
