Open Source Update: Raucle Goes Apache-2.0 and Ships the Trust Layer

Six weeks ago I published a post about moving from statistical detection to cryptographic proof for AI agent accountability. The project was called raucle-detect, it was licensed under AGPL-3.0, and it shipped the core capability receipt primitive: a signed, content-addressed record of every policy-gated action an AI agent takes.

A lot has changed since then. The project is now called raucle (not raucle-detect), it’s licensed under Apache-2.0 (not AGPL), and it has shipped four new modules that make those receipts work across organisational boundaries. The paper is under submission at IEEE Security & Privacy 2027. Microsoft accepted the upstream contribution into their Agent Governance Toolkit. And the whole thing went through nine rounds of adversarial security review that found three fail-open bugs I’m glad we caught before someone else did.

This post is the update.

Why Apache-2.0

The AGPL decision was deliberate. I wanted a copyleft licence that forced anyone building on the work to publish their modifications. That’s a reasonable instinct for a security project where transparency matters.

But after talking to potential adopters, the feedback was consistent and I couldn’t ignore it. Security teams inside banks, cloud providers, and enterprise platforms told me the same thing: AGPL creates legal review overhead that kills adoption before anyone tries the technical integration. Their legal teams have a reflexive policy against touching AGPL code. Whether that reflex is well-calibrated or not, it’s real, and it means the code doesn’t get evaluated.

Apache-2.0 solves this. It’s permissive, it includes an explicit patent grant, and it’s the licence that most enterprise infrastructure already runs on. The goal is adoption. If the choice is between “copyleft and nobody uses it” and “permissive and it becomes the reference implementation,” I’ll take the second one every time.

The trademark is held separately. Apache-2.0 section 6 doesn’t grant rights to the “Raucle” name, so the project controls that independently. If you fork it, you call it something else.

The dual-licence apparatus is gone too. No CLA, no commercial licence lever. Contributions are Apache-2.0 inbound equals outbound, with a DCO sign-off. That’s simpler for everyone.

The rename: raucle-detect is now raucle

The library outgrew the name. When I started building, the project was a prompt-injection detector. Then it added provenance receipts. Then capability tokens. Then an SMT-backed policy prover. Then a gate. Then a trust registry, cross-organisation handshake, agent passports, and compliance evidence packs. Detection is one module now, not the product.

pip install raucle-detect is now pip install raucle. The old import path keeps working through a deprecation shim for one transition cycle. The CLI is raucle instead of raucle-detect. Environment variables are RAUCLE_* instead of RAUCLE_DETECT_*. The wire formats are unchanged. Every existing receipt still verifies. The iss identifier on the provenance receipt stays frozen as "raucle-detect/provenance" because that’s committed to the spec, the cross-language test vectors, and all five reference ports.

The Go module path is a breaking change, unfortunately. Go modules can’t alias a renamed declared path, so Go consumers need to update their import from github.com/craigamcw/raucle-detect/reference/provenance-go to github.com/craigamcw/raucle/reference/provenance-go. Everything else is wire-compatible.

The platform trust layer

The capability receipt solves the problem of proving what one agent did. But the real question regulated industries ask is harder: how does one organisation verify another organisation’s agent was authorised to do what it did?

That’s a cross-organisation trust problem. Today, most answers involve some kind of federation, a shared identity provider, or bilateral key exchange. None of those scale to the kind of ad-hoc agent-to-agent interaction that’s coming.

Raucle v0.21.0 ships four modules that address this directly:

Agent Trust Registry. An append-only, hash-chained, operator-signed directory of issuer keys. Organisation B can verify Organisation A’s capability tokens by resolving the shared registry. Revocation is fail-closed. Rollback is detected via a signed freshness anchor, so a verifier can reject a stale signed snapshot that omits a later revocation. The CLI is raucle registry init|publish|list|resolve|revoke|verify.

Cross-organisation handshake. A signed request/accept/ack exchange between two organisations’ agents, with trust resolved from the registry. No prior key exchange needed. Signed acknowledgement receipts, responder-side replay rejection, and the verification function requires a real anti-replay binding by default.

Agent passport. An issuer-countersigned, registry-anchored identity document that wraps an agent’s capability statement. One portable artifact that any framework, LangChain, CrewAI, MCP, A2A, Agent Framework, can verify offline before enforcing scope. Fail-closed on malformed input, including hostile-but-signed bodies.

Compliance evidence packs. Maps a signed receipt chain to EU AI Act, ISO/IEC 42001, and SOC 2 controls. I want to be honest about what this is: it’s an evidence map, not a conformance attestation. Controls report SATISFIED, PARTIAL, or OUT_OF_SCOPE. SATISFIED requires cryptographic verification of the underlying chain. If the chain doesn’t verify, the control doesn’t pass.

These four modules went through nine rounds of iterative adversarial security review before merging. An independent auditor ran find, fix, re-verify cycles until the code was clean of HIGH and MEDIUM findings. Every fix landed with a regression test.

Three fail-open bugs that could have been bad

During the post-relicense security sweep, three fail-open issues surfaced. Each one was found by actually exercising the shipped integration paths, not by reading code. Each one is the kind of bug that doesn’t show up in a unit test until you write the test that would have caught it.

The LangChain integration was fail-open on DENY. LangChain’s callback manager swallows handler exceptions unless the handler sets raise_error. The Raucle callback handler didn’t. So when the gate raised CapabilityDenied on a blocked tool call, LangChain logged it as a warning and the tool executed anyway. The gate was advisory. The fix is raise_error=True and run_inline=True, both load-bearing and commented. End-to-end tests now run the real tool.run() dispatch path, and the langchain extra is part of the dev dependencies so CI exercises it.

The MCP server accepted missing required arguments as a clean verdict. A tools/call omitting a schema-required argument silently scanned the empty string and returned CLEAN/ALLOW. The server now enforces each tool’s declared inputSchema.required and returns isError when a required argument is missing.

The gate leaked internal exception text in DENY reasons. The caller-visible denial reason included the raw exception text. Now it’s generic, with the full traceback logged server-side only.

All three are fixed. All three have regression tests. I’m mentioning them because I think transparency about security bugs is more useful than pretending they didn’t happen. If you’re evaluating the project, you should know what was found and how it was fixed.

Microsoft Agent Governance Toolkit: merged upstream

On 27 May 2026, my contribution to Microsoft’s Agent Governance Toolkit was merged. PR #2610 adds proof_artefact and verification_pointers to AGT’s BackendDecision, carrying raucle’s proof metadata through AGT’s audit chain.

The strategic posture is with AGT, not against it. Microsoft has the distribution and the customer relationships. AGT is MIT-licensed and covers in-process default policies well. What AGT doesn’t have is mechanised soundness proofs, offline-verifiable receipts, or SMT-verified policy completeness. Raucle slots into AGT’s ExternalPolicyBackend protocol as the thing you reach for when your regulator demands a cryptographic record AGT can’t produce.

Raucle also ships a drop-in FunctionMiddleware for the Microsoft Agent Framework directly. 9/9 tests passing against agent-framework 1.6. If you’re already on the Microsoft stack, the integration is about ten lines of glue.

Five reference implementations, byte-for-byte

The provenance receipt specification now has five reference implementations: Python, TypeScript, Go, Rust, and C#. All five ship the same JSON test-vector file in CI. Every implementation must reproduce every published vector byte-for-byte, both the JWS string and the SHA-256 of that string. Every implementation must successfully verify every published signature.

During the hardening pass, a cross-language signing bug was found by cross-model review. Python and Go sorted object keys by Unicode code point. TypeScript and C# sorted by UTF-16 code unit. Identical for BMP/ASCII, so every shipped test vector passed. But divergent for non-BMP, any signed object with an emoji or astral-plane key would hash to different bytes across languages. All five are now unified on UTF-16 code-unit ordering per RFC 8785 / JCS section 3.2.3. Byte-neutral for all existing BMP material, so no signature or ID churn.

This is the difference between a protocol and a library. A protocol is something other people target. The five-language conformance contract is what makes the receipt format actually targetable.

The security hardening, in brief

Between v0.15.0 and v0.20.0, the project went through six security-focused passes. Two independent adversarial audits, a SonarQube static analysis pass, a cross-model Codex review, and the nine-round trust-layer review. No receipt wire-format changes. Five-language byte-identity preserved throughout.

Some of the fixes that matter:

  • Agent-id privilege escalation: agent matching required a bare prefix, so a token for agent:billing authorised agent:billing-evil. Now requires exact match or a dot-delimited descendant.
  • Constraint bypass by omission: value constraints were skipped when the named field was absent. Alias or omit an argument and you bypass the policy. Now positive constraints are enforced on present-and-required fields.
  • ReDoS: an 82-second pathological scan is now 0.01 seconds through per-pattern length caps, bounded wildcard spans, and a per-scan wall-clock budget.
  • Feed fetching is HTTPS-only, blocks private/loopback/metadata IPs, pins the validated IP against DNS-rebind, rejects redirects, and caps body size.
  • The prover no longer returns PROVEN for queries reading forbidden tables via EXCEPT/INTERSECT/MINUS. Unknown SQL grammar or policy keys now force UNDECIDED instead of PROVEN.

The fail-closed redesign in v0.17.0 flipped the entire prover/gate/verifier from “enumerate bad” to “fail-closed by construction.” Anything the system does not explicitly model now hits a conservative verdict: gate denies, prover returns UNDECIDED, mint/verify rejects. A single executable Modelled Language Registry drives the runtime allowlists, and a CI drift guard fails if any consumer’s modelled set diverges.

Where the project is now

On PyPI, pip install raucle gets you v0.22.0 with optional extras for rules, server, ML, compliance, proof, and the Microsoft Agent Framework adapter. The core package is Apache-2.0. The five reference implementations are MIT. The provenance receipt specification is CC-BY-4.0.

The paper is under submission at IEEE Security & Privacy 2027. The draft, the Lean 4 mechanisation, and the benchmark harness are all in the repository under paper/.

The benchmark numbers haven’t moved: 100% block rate on attacker-controlled tool calls across 720 LLM-driven attempts on the AgentDojo banking suite. +27 to +58 percentage-point advantage in benign task completion versus the strongest contemporary text-side defence at equivalent security. 69 microseconds per-call gate latency at p50 on commodity x86_64 hardware.

Integrations cover the Microsoft Agent Framework (drop-in FunctionMiddleware), the Agent Governance Toolkit (ExternalPolicyBackend), LangChain (CallbackHandler), AutoGen, and an MCP gateway pattern. There’s also an Azure AI Foundry sidecar deployment under Bicep and APIM policy for anyone on that stack.

The detection layer ships 180+ compiled signatures across 10 categories: prompt injection, jailbreaks, data exfiltration, data loss, MCP tool poisoning, RAG poisoning, agent attacks, evasion, output leakage, and tool abuse.

What I’m asking for

Three things, same as last time but more specific.

Break the proofs. The three Lean 4 theorems are in paper/lean/. They close with zero sorrys. If you can read Lean, try to break them. A theorem that someone outside the project has tried to break is worth more than one that nobody has.

Write real-world policies. The evaluation runs against AgentDojo’s pre-registered policy files. The hardest problem in production is authoring policies for real tools: banking APIs, healthcare records systems, payments networks. Contributing policy templates for tools you have integrated, with explanations of the threat model behind each, is the single most useful thing for the community right now.

Try it against a real agent. If you are running a production LLM gateway, install raucle, wire it into your agent, and tell me what broke. I am especially interested in cases where the schema fragment your tool uses falls outside the supported decidable subset, or where the gate’s eight checks are the wrong eight for your deployment, or where your auditor has a specific evidence requirement the receipt format does not cover.

The repository is at github.com/craigamcw/raucle. Star it, file an issue, send a pull request, or open a discussion thread and tell me what your real-world friction looks like.


Raucle is open source under Apache-2.0. The IEEE Security & Privacy 2027 paper draft, the Lean 4 mechanisation, the AgentDojo / InjecAgent benchmark harness, and the five reference implementations all ship in the same repository. The project was previously released as raucle-detect under AGPL-3.0; it was relicensed to Apache-2.0 in v0.19.0 and renamed to raucle in v0.22.0.