@auxdynamics/mastguard-agent-sdk
v0.3.0
Published
Runtime AI agent security SDK for MastGuard — prompt injection detection, scope enforcement, tamper-evident audit logging, and policy-based guardrails.
Maintainers
Readme
@auxdynamics/mastguard-agent-sdk
Runtime AI security SDK for MastGuard — wraps any LLM call with prompt injection detection, scope enforcement, and tamper-evident audit logging.
Installation
npm install @auxdynamics/mastguard-agent-sdk5-Minute Quickstart
Three lines to get monitoring (monitor mode never blocks — it just audits):
import { wrapOpenAI, MastGuardShield } from '@auxdynamics/mastguard-agent-sdk';
const shield = new MastGuardShield({ apiKey: process.env.MASTGUARD_API_KEY!, organizationId: 'org-abc123', agentId: 'my-bot', mode: 'monitor' });
const openai = wrapOpenAI(new OpenAI(), shield); // use `openai` exactly as beforeEvery chat.completions.create() call is now threat-scanned and written to
MastGuard's tamper-evident audit trail. Flip mode: 'block' when you're
ready to enforce.
Full Quickstart
import { MastGuardShield } from '@auxdynamics/mastguard-agent-sdk';
const shield = new MastGuardShield({
apiKey: process.env.MASTGUARD_API_KEY,
policy: 'standard',
agentId: 'my-customer-support-bot',
organizationId: 'org-abc123',
});
const response = await shield.protect(
() => openai.chat.completions.create({ model: 'gpt-4o', messages }),
{ sessionId: req.user.id, toolCalls: pendingToolCalls }
);
if (!response.allowed) {
console.log('Flagged:', response.violations);
}Pass a thunk (
() => client.create(...)) rather than a started Promise. Inblockmode, input-level threats are evaluated before the LLM is invoked — if the request is blocked, the LLM call never happens. A bare Promise is still accepted for backward compatibility, but it has already started the call by the timeprotect()sees it.
Pre-Call vs. Post-Call Blocking
Pre-call blocking for input-level threats (prompt injection, scope violation, token budget). Post-call blocking for output-level threats (data exfiltration, harm classification).
| Stage | Threats evaluated | LLM invoked on block? |
| --- | --- | --- |
| Pre-call (before dispatch) | Prompt injection (direct), scope violation (tool-call parameters), token budget threshold | No — the call is never made (thunk callers) |
| Post-call (response required) | Data exfiltration, AgentHarm output classification, multi-step attack chain continuation | Yes — the response is withheld and MastGuardBlockedError is thrown |
Authentication
Get your API key from https://app.mastguard.io/dashboard/developer (Developer page → Create API key).
Pass it as apiKey in ShieldConfig or set the MASTGUARD_API_KEY environment variable. Every request the SDK makes — both event ingest and policy fetch — authenticates with the X-API-Key header.
Configuration
| Option | Type | Required | Default | Description |
| ---------------- | ---------------------- | -------- | ---------------------------- | --------------------------------------------------------- |
| apiKey | string | Yes | — | MastGuard API key from dashboard |
| policy | string | Yes | — | Policy name: standard, hipaa, or enterprise |
| agentId | string | Yes | — | Unique identifier for this agent |
| organizationId | string | Yes | — | Your MastGuard organization ID |
| endpoint | string | No | https://api.mastguard.io | Override API base URL (staging / self-hosted) |
| mode | 'block' \| 'monitor' | No | 'block' | block enforces policy; monitor logs only |
| timeout | number | No | 3000 | Ingest API timeout in milliseconds |
Shield Methods
shield.protect(llmCall, options)
Wraps any LLM call — evaluates the request before dispatch (pre-call
layers) and the response after (post-call layers) against your configured
policy. In block mode, a violation at either stage throws
MastGuardBlockedError; for pre-call violations the LLM is never invoked.
const result = await shield.protect(
() => openai.chat.completions.create({ model: 'gpt-4o', messages }),
{
sessionId: 'session-xyz', // required — ties events to a session
toolCalls: [...], // optional — pending tool calls to inspect
userId: 'user-123', // optional — for per-user audit trails
metadata: { env: 'prod' }, // optional — attached to audit records
}
);Returns ShieldResult<T>:
| Field | Type | Description |
| ------------ | -------------------- | ------------------------------------------------ |
| data | T \| null | The original LLM response (null if blocked) |
| allowed | boolean | true if the call passed all policy checks |
| violations | ViolationRecord[] | List of policy violations found (empty if clean) |
| auditId | string \| undefined| Tamper-evident audit record ID |
| sessionId | string | Session ID echoed back for correlation |
Detection Layers
| Layer | Rule ID | What It Detects | Research Basis |
| ------------------ | ----------------- | ---------------------------------------------------------- | ---------------- |
| Prompt Injection | RULE-INJ-001 | Direct instruction-override attempts in user input | arXiv:2510.22620 |
| Indirect Injection | RULE-INJ-002 | Instructions embedded in tool outputs or RAG results | arXiv:2510.22620 |
| Scope Violation | RULE-SCOPE-001 | Tool calls outside the agent's declared policy | arXiv:2510.22620 |
| Data Exfiltration | RULE-EXFIL-PII-*| PII, credentials, API keys in LLM responses | arXiv:2510.22620 |
| Multi-Step Attack | RULE-CHAIN-001 | Sequential tool calls matching known attack chains | arXiv:2603.11214 |
All detections are run by ThreatDetector and evaluated against your policy by PolicyEngine. Events are logged via AuditLogger with SHA-256 chain hashing for tamper evidence.
MCP Integration — MastGuardMCPProxy
Industry-first MCP-native security layer: every MCP tool call is policy-checked before it reaches the MCP server, audited, and the response is scanned for data exfiltration before your agent sees it. Existing MCP clients need zero config changes.
import { MastGuardMCPProxy, MastGuardBlockedError } from '@auxdynamics/mastguard-agent-sdk';
const proxy = new MastGuardMCPProxy('http://localhost:9000/rpc', {
apiKey: process.env.MASTGUARD_API_KEY!,
organizationId: 'org-abc123',
agentId: 'mcp-agent',
// Local rules; server-side "mcp_tool_scope" policy rules also apply.
toolScope: [
{ tool_names: ['read_file', 'search_docs'], action: 'allow' }, // allowlist
// or: { tool_names: ['delete_database'], action: 'deny' } // denylist
],
});
try {
const result = await proxy.proxyRequest('read_file', { path: '/docs/a.md' }, { sessionId: 'sess-1' });
} catch (err) {
if (err instanceof MastGuardBlockedError) {
// Denied by mcp_tool_scope policy, or the response leaked credentials/PII.
}
}What happens on every proxyRequest:
- Policy check before forwarding —
mcp_tool_scoperules (local + server-side policy). Denied →MastGuardBlockedError, the MCP server is never contacted. - Audit — logged to MastGuard (
event_type: mcp_tool_call/mcp_tool_blocked). - Forward — standard JSON-RPC 2.0
tools/callto the MCP server. - Response scan — exfiltration + indirect-injection detection; critical findings throw before the output reaches the caller.
- Logged with latency + SHA-256
output_hash— visible in the AgentShield dashboard's MCP Monitor tab.
Integration Examples
// OpenAI
import OpenAI from 'openai';
import { wrapOpenAI } from '@auxdynamics/mastguard-agent-sdk';
const openai = wrapOpenAI(new OpenAI(), shield);
const res = await openai.chat.completions.create({ model: 'gpt-4o', messages });
// Anthropic
import Anthropic from '@anthropic-ai/sdk';
import { wrapAnthropic } from '@auxdynamics/mastguard-agent-sdk';
const anthropic = wrapAnthropic(new Anthropic(), shield);
const msg = await anthropic.messages.create({ model: 'claude-sonnet-4-6', max_tokens: 1024, messages });
// Azure OpenAI
import { AzureOpenAI } from 'openai';
import { wrapAzureOpenAI } from '@auxdynamics/mastguard-agent-sdk';
const azure = wrapAzureOpenAI(new AzureOpenAI({ endpoint, apiVersion }), shield);
// MCP (see MCP Integration above)
const proxy = new MastGuardMCPProxy(mcpServerUrl, config);Streaming is fully supported: stream: true returns a live AsyncIterable.
In monitor mode chunks pass through in real time and the assembled response
is audited afterwards; in block mode the stream is buffered, scanned, and
replayed only if clean.
Troubleshooting — Top 5 Errors
| Error | Cause | Fix |
| --- | --- | --- |
| MastGuardBlockedError: ... prompt_injection | The input tripped an injection rule in block mode | Inspect err.violations[].evidence; sanitize the input or run monitor mode to tune policy first |
| ingest non-200: 401 Unauthorized | Invalid/revoked API key | Create a fresh key at app.mastguard.io → Developer; pass it as apiKey (X-API-Key header) |
| ingest non-200: 429 | Free plan 50K monthly event cap, or the 10K/min ingest rate limit | Upgrade to Pro (2M events included) or batch/reduce event volume |
| policy fetch error: AbortError | Policy fetch exceeded timeoutMs (default 5s) | The SDK fails open to the default policy; raise timeoutMs or check egress to api.mastguard.io |
| protect() blocked but my LLM was still called | You passed a started Promise, not a thunk | Pass () => client.create(...) — pre-call blocks then prevent the call entirely |
MastGuard SDK vs. LangSmith vs. Arize vs. Helicone
| Capability | MastGuard SDK | LangSmith | Arize (Phoenix) | Helicone |
| --- | --- | --- | --- | --- |
| Primary job | Runtime security + governance enforcement | LLM tracing/evals | ML/LLM observability + evals | LLM proxy analytics/cost |
| Pre-call blocking (call never happens) | ✅ thunk-based intercept | ❌ | ❌ | ⚠️ rate/spend limits only |
| Threat detection (injection/exfiltration/harm) | ✅ 5 rule layers, client-side | ❌ | ⚠️ eval-time only | ❌ |
| MCP tool-call policy + audit | ✅ MastGuardMCPProxy | ❌ | ❌ | ❌ |
| Tamper-evident audit chain (SHA-256) | ✅ | ❌ | ❌ | ❌ |
| Compliance reporting (GDPR/HIPAA/EU AI Act…) | ✅ platform-generated | ❌ | ❌ | ❌ |
| HITL review routing | ✅ platform | ⚠️ annotation queues | ⚠️ labeling | ❌ |
| Tracing/latency analytics | ⚠️ basic (latency, tokens) | ✅ deep | ✅ deep | ✅ deep |
Use LangSmith/Arize/Helicone for debugging quality and cost; use MastGuard when an auditor, regulator, or CISO needs proof of control.
Error Handling
import { MastGuardBlockedError } from '@auxdynamics/mastguard-agent-sdk';
try {
const result = await shield.protect(() => llmCall(), { sessionId });
// result.violations may contain 'flag'/'log' findings even when allowed
} catch (err) {
if (err instanceof MastGuardBlockedError) {
for (const v of err.violations) {
console.error(`[${v.severity}] ${v.category}: ${v.description}`);
// v.action is 'block' | 'flag' | 'log'
// v.evidence contains the raw matched content
}
} else {
throw err;
}
}In block mode, a policy violation throws MastGuardBlockedError — pre-call
violations throw before the LLM is invoked; post-call violations throw after,
withholding the response. In monitor mode, nothing is ever blocked —
violations are logged to MastGuard and returned in result.violations,
letting you evaluate policy impact before enforcing it.
TypeScript
Full TypeScript support is included — no @types package needed. CJS and ESM builds are both shipped.
import type {
ShieldConfig,
ShieldResult,
ViolationRecord,
ToolCallRecord,
ProtectOptions,
EvaluationResult,
PolicyTier,
ShieldMode,
Severity,
ViolationAction,
} from '@auxdynamics/mastguard-agent-sdk';Related Packages
This package handles runtime AI security monitoring.
If you need to integrate with the MastGuard governance platform (audit logs, HITL queues, webhooks, compliance dashboards), use the companion SDK:
License
MIT © AuxDynamics Inc.
