affixio-agent-guard
v0.1.0
Published
Free, local-first guard that checks an LLM agent's tool calls against policy before execution. Simulated local receipts only — not cryptographic attestation.
Downloads
161
Maintainers
Readme
affixio-agent-guard




Stop LLM agents spending money or leaking secrets. 5 lines. No API keys. Runs offline.
Free, local-first guard that checks an LLM agent's tool calls against policy before the tool runs. TypeScript, ESM, Node 20+. No API keys, no cloud services, no network calls.
Why?
Agent demos ship with allowedTools: ['*']. One prompt injection and it calls payments.refund. This blocks it before it runs.
⚠️ This is a developer demo. It does not replace AffixIO's paid production verification, hosted controls, ML-DSA attestations, enterprise audit or payment features. Receipts here are local simulations, not cryptographic attestations.
Install
npm install affixio-agent-guardUsage
import { createGuard, checkToolCall, writeReceipt } from 'affixio-agent-guard';
const policy = {
allowedTools: ['payments.create', 'crm.lookupCustomer'],
allowedHosts: ['api.example.com'],
maxAmount: 500,
blockedSecrets: ['sk_live_', 'AKIA'],
requireApprovalFor: ['payments.refund'],
};
const decision = checkToolCall(
{ tool: 'payments.create', host: 'api.example.com', amount: 120, args: { customer: 'cust_42' } },
policy,
);
// { allowed, reason, receipt }
if (decision.allowed) {
// execute the tool call in your agent runtime
console.log(decision.reason, decision.receipt.requestHash);
} else {
console.warn('Blocked:', decision.reason);
}
// Optionally persist the local simulation receipt
const path = await writeReceipt(decision.receipt); // writes .affixio/receipt-<ts>.json
// Or bind a policy once:
const guard = createGuard(policy);
guard.check({ tool: 'payments.create', args: {} });CLI demo
npx affixio-agent-guard demoShows one allowed mock MCP-style call and one denied call containing a fake secret, writing local simulation receipts to .affixio/.
Policy
| Key | Meaning |
| -------------------- | -------------------------------------------------------------- |
| allowedTools | Tool names the agent may call (exact match) |
| allowedHosts | Hosts tools may contact (exact match; calls without a host pass this check) |
| maxAmount | Maximum permitted monetary amount |
| blockedSecrets | Substrings that must never appear in tool arguments |
| requireApprovalFor | Tools that always require explicit human approval (fail closed) |
Threat model & clear limits
What it does: deterministic, fail-closed policy check of a single tool call; SHA-256 hash (Node crypto only) of the canonical request; local JSON receipts; zero network.
What it does not do:
- Not a cryptographic attestation. Receipts are local, unsigned JSON. Anyone can edit them.
- Not tamper-evident in production. The request hash binds the receipt to the request, but the receipt itself is not signed, timestamped by a trusted authority, or anchored.
- Not enforcement. The guard only returns a decision; your agent runtime must honor it. A compromised runtime can bypass it entirely.
- Not an approval workflow.
requireApprovalFordenies unless you build your own approval step. - Not secret-scanning proof. Only exact substring matches of the patterns you configure.
- No network, keys or cloud. By design, so it cannot verify counterparty identity, authorization chains or real-world state.
Paid upgrade path: when you need production enforcement, replace the local simulated receipt with AffixIO's real proof and authorisation flow — hosted policy controls, ML-DSA attestations and enterprise audit.
Exports
createGuard(policy), checkToolCall(request, policy), writeReceipt(receipt, dir?), runDemo(), plus canonicalRequestHash and all TypeScript types.
Development
npm install
npm test
npm run build
node dist/cli.js demoClean install
If npm test or npm run build fail with sh: 1: vitest: Permission denied / sh: 1: tsc: Permission denied (e.g. after copying the project, when the execute bit on node_modules/.bin binaries is lost), do a clean reinstall:
cd ~/Desktop/affixio-agent-guard
rm -rf node_modules package-lock.json
npm install
npm test
npm run build
node dist/cli.js demoMIT.
