A native, in-process SDK for a3s-sentry — the Rust L1/L2/L3 judge embedded via
napi-rs, the same model as @a3s-lab/code. You
build the judge from one ACL config and evaluate observer events in-process — no daemon, no
subprocess (beyond what L3 itself spawns).
npm install @a3s-lab/sentryimport { Sentry, egress, toolExec } from "@a3s-lab/sentry";
// `create` takes an ACL config file path or ACL content.
const sentry = Sentry.create("sentry.acl");
const d = sentry.evaluate(egress(1, "169.254.169.254", 80)); // cloud-metadata SSRF
if (d?.verdict === "block") {
console.log(d.reason, d.action); // -> "...", { kind: "DenyEgress", target: "169.254.169.254" }
}
// judge AND write the deny-file the kernel guards read:
const r = sentry.evaluateAndEnforce(toolExec(2, ["/usr/bin/ncat", "host", "4444"]));
console.log(r?.decision.verdict, r?.enforced); // "block", "/path/exec.txt"
// Stop after L2 and preserve an unresolved escalation for a durable external L3 worker. This runs
// on the napi worker pool, so a slow L2 request does not block Node's event loop.
const fast = await sentry.evaluateThroughL2(toolExec(3, ["bash", "-c", "base64 -d | sh"]));
if (fast?.stageStatus === "escalated") {
console.log(fast.escalationCause, fast.effectiveDecision);
}A sentry.acl carries everything (see config.rs for the schema):
fail_closed = false
speculate = "high"
llm { url = "http://llm:18051/v1", model = "glm", timeout_s = 30 } # L2 (optional)
agent { bin = "a3s-code", skills = "./skills" } # L3 (optional)
deny { egress = "egress.txt", exec = "exec.txt" } # sinks (optional)
rules = [
{ name = "no-netcat", on = "ToolExec", match = "(?i)\\bnetcat\\b",
verdict = "block", severity = "medium", reason = "netcat", action = "deny-exec" },
]Event builders: toolExec, egress, fileAccess, dns, sslContent, securityAction — each
returns the observer event JSON evaluate takes. evaluate returns null for an unparseable event,
and a Decision ({ verdict, tier, severity, reason, action? }) otherwise — including allow.
evaluateThroughL2 returns a promise containing l1Decision, optional l2Decision,
effectiveDecision, stageStatus, and optional escalationCause. It never invokes L3, never
resolves an outstanding escalation through fail_closed, and ignores speculative L3 settings.
npm install
npm run build:debug # napi build → index.js + index.d.ts + a3s-sentry.<platform>.node
npm testRequires a Rust toolchain (it compiles the embedded judge). The published package ships the prebuilt
native binary per platform, so consumers need only npm install.