Show HN: Scan your AI agents for dangerous capabilities
摘要
该项目由 MakerChecker 提供,旨在成为 AI Agent 的开源安全层。核心功能包括默认拒绝机制、人工审批和加密签名的审计轨迹,确保 Agent 仅按授予的角色运行授予的技能,无法自行审批或超越权限。 Quick Start 提供三步:1. 使用 mc scan 扫描代码,识别并分类所有重大风险操作(如删除数据、转账、执行 shell 命令),并可自动写入治理代码 (--fix);2. 在 embedded 包中导入控制并包装工具,将高风险技能分离至独立角色,确保无法自行审批,所有决策均记录在签名的审计日志中;3. 部署自托管服务器以提供审批收件箱、查询控制台和查询 able 的耐久审计记录,支持离线验证。 所有三个独立包(mc scan、@makerchecker/embedded、server)强制相同控制并使用相同签名的审计格式。支持 LangChain、Claude SDK、TypeScript/Python SDK 等框架的连接器。包含可运行的示例用例(如药监案例处理、肿瘤患者访问等),以及 Apache-2.0 和 AGPL-3.0 等许可说明。
荐读理由
工具mc scan 能扫描已有AI代理代码,分类分出每个工具调用属于什么具体风险(删数据、转钱、shell、泄密),并给出可直接改写成governance代码的片段;导入@makerchecker/embedded后就能给现有LangChain、Claude Agent SDK、CrewAI的每个tool call加一层deny-by-default checkpoint和Ed25519签名审计链,既不在项目里加新依赖也能用
原文
🛡️ MakerChecker
The open-source security layer for AI agents.
Deny-by-default enforcement, human approvals, and a cryptographically signed audit trail — so your agent runs only what it's granted and provably can't approve its own work.
Your agents keep running in their existing framework (LangChain, Claude SDK, CrewAI). MakerChecker sits in front of every tool call as a checkpoint and behind it as a signed ledger: an agent acts only through a role, runs only the skills it was granted, cannot exceed its limits, and cannot approve its own work.
🚀 Quick Start
1 — Scan your code
Find what your agent can already do on its own, classified by risk. No install, nothing leaves your machine:
npx @makerchecker/scan .
It flags every consequential action — deleting data, moving money, running shell commands, exfiltrating secrets — names each against the real incident it resembles, and can write the governance code for you with --fix. → packages/scan
2 — Guarantee its behavior
Import the controls and wrap any tool. The agent can now only run what its role was granted — a call it isn't allowed is denied before it executes:
npm i @makerchecker/embedded
import { createGovernor, GovernanceDeniedError } from "@makerchecker/embedded";
const gov = createGovernor()
.defineSkill("place-order@1", { riskTier: "high" })
.defineRole("agent")
.defineRole("risk-desk")
.grant("risk-desk", "place-order@1") // the agent is NOT granted it — deny by default
.defineAgent("trader", "agent");
// Wrap your tool once. Now the agent structurally can't fire it.
const placeOrder = gov.governedTool("trader", "place-order@1", (order) => broker.submit(order));
try {
await placeOrder({ symbol: "BTC", qty: 10 });
} catch (err) {
if (err instanceof GovernanceDeniedError) console.log(err.code); // "skill_not_granted"
}
High-risk skills go to a separate role, so an agent can never approve its own work — and every decision, allowed or denied, commits to a signed audit log. → packages/embedded
3 — Working with auditors?
Step 2 already writes a signed log. When auditors need a durable, queryable, tamper-evident record — plus a human-approval inbox and a review console — run the self-hosted server:
docker compose up
Every decision is Ed25519-signed and hash-chained: change any row and verification breaks. Export a bundle and anyone verifies it offline — no database, no trust in the process that produced it. → full server setup below
These are three independent packages —
mc scan,@makerchecker/embedded, and the server — that enforce the same controls and write the same signed audit format. Adopt any one on its own.
🔬 Governed Use Cases
Runnable examples of agents doing consequential work behind a human gate:
Pharmacovigilance case processing — an agent triages adverse-event reports, but a medical reviewer signs before an expedited 15-day regulatory report transmits. examples/pv-icsr-processing
Medical-device (MDR) complaint triage — a regulatory officer decides reportability behind a gate before draft reports are generated. examples/mdr-reportability-triage
Oncology patient access — an agent handles benefit matching but is blocked from submitting copay enrollments without a specialist signing. examples/oncology-patient-access
Daily cash reconciliation — a finance agent reconciles transactions but locks at exception gates until a cash officer signs off. examples/daily-cash-reconciliation
🔌 Integrate With Your Framework
Drop-in connectors govern the tools you already have:
LangChain →
packages/connector-langchainClaude Agent SDK →
packages/connector-claude-agentTypeScript / Python SDKs →
packages/sdk·packages/sdk-python
When you run the server, the SDK's governedTool routes each call through a proxy session for centralized authorization and recording:
import { createClient, governedTool, GovernanceDeniedError } from "@makerchecker/sdk";
const client = createClient({ baseUrl: "http://localhost:3000", apiKey: "mk_..." });
const { session } = await client.proxy.openSession({ label: "recon-run" });
const match = governedTool(
client, session.id,
"recon-preparer", // agent whose role grants are evaluated
"txn-match@1", // skillRef: name@version
(input) => matchTxns(input),
);
await match({ statement, ledger }); // throws GovernanceDeniedError if denied
await client.proxy.closeSession(session.id);
🖥️ Self-Hosted Server (optional)
Run the full gateway when you need centralized enforcement across many agents, a human-approval inbox, and a review console. docker compose up brings up Postgres, the server on localhost:3000, and a seeded demo, printing two API keys — an admin key (your agent authenticates runs) and an officer key (a human reviewer approves gated actions).
The seeded pharmacovigilance flow parks at a medical-review gate where the requester is refused as its own approver:
export H='authorization: Bearer mk_...' # admin key
export OFFICER='authorization: Bearer mk_...' # officer key
curl -X POST localhost:3000/api/flows/pv-icsr-processing/runs -H "$H" -H 'content-type: application/json' -d '{}'
curl localhost:3000/api/approvals -H "$H"
# The requester cannot approve their own run — rejected with 403
curl -X POST localhost:3000/api/approvals/<id>/decision -H "$H" -H 'content-type: application/json' \
-d '{"decision":"approved","reason":"self-approval attempt"}'
# A separate officer signs; only now does the action proceed
curl -X POST localhost:3000/api/approvals/<id>/decision -H "$OFFICER" -H 'content-type: application/json' \
-d '{"decision":"approved","reason":"Seriousness confirmed; file 15-day expedited ICSRs."}'
curl localhost:3000/api/audit/verify -H "$H"
Full setup, Kubernetes/Helm, and running with live models: docs/quickstart.md.
🔒 Verifiable Audit Trail
Every decision and tool call commits to a hash-chained log — each event a SHA-256 over the RFC 8785 canonical JSON of the event, chained through prev_hash from genesis and Ed25519-signed. Change any row and verification breaks. Anyone can verify an exported bundle offline — no database, and no trust in the process that produced it:
npx @makerchecker/proof-verifier verify bundle.json
Spec: docs/audit-spec.md.
🗂️ Packages
| Package | License | What it is |
|---|---|---|
packages/scan |
Apache-2.0 | mc scan — finds and classifies what your agent can do. |
packages/embedded |
Apache-2.0 | Importable enforcement primitives — governance in your code. |
packages/proof-verifier |
Apache-2.0 | Independently verify a signed audit bundle offline. |
packages/sdk |
Apache-2.0 | TypeScript client + governedTool for the server. |
packages/sdk-python |
Apache-2.0 | Python client + governed_tool. |
packages/connector-langchain |
Apache-2.0 | Govern LangChain tools. |
packages/connector-claude-agent |
Apache-2.0 | Govern Claude Agent SDK tools. |
packages/server |
AGPL-3.0 | Self-hosted Fastify + Postgres gateway, flow engine, audit writer. |
packages/web |
AGPL-3.0 | React console: approvals inbox, run log, registry. |
packages/shared |
AGPL-3.0 | Domain types, canonical JSON, crypto utilities. |
📄 License & Contributing
Server, Web, Shared: AGPL-3.0.
mc scan,embedded, SDKs, connectors, examples: Apache-2.0 — embed them in closed-source agents freely.Commercial (non-copyleft) licensing: hello@makerchecker.ai.
Contributing: CONTRIBUTING.md · Security: SECURITY.md · Code of Conduct: CODE_OF_CONDUCT.md
这条对你有帮助吗?