CFAM

Containment-First Agentic Middleware · a GALXEE AI project

Reasoning recommends.
The middleware decides.

Authority, risk, and containment — enforced in sequence and recorded forever. Your agents stay safe even when the model is wrong.

How it works

The agent can only act through the GovernedToolGateway — the single path to any side effect. Every proposed action clears four controls in order (signed manifest → policy → risk screen → sandbox), and each decision is written to a tamper-evident ledger. A refused action never reaches the tool.

Signed Capability Manifest · Ed25519 the authority every layer enforces — allowed tools · endpoints · cost ceiling · time window AI Agent proposes an action (may be wrong or compromised) action GovernedTool Gateway the only path to side effects authority governed 1 Policy Engine deterministic allowlist check outside → block pass 2 Sentry Node multi-signal risk screen risky → escalate pass 3 Isolation Layer sandboxed exec CPU·mem·fs limits bounds blast radius execute ALLOW executes → your tools BLOCK never executes ESCALATE routes to a human Audit Ledger append-only · hash-chained · Ed25519 signed head · externally anchored — every decision recorded

Only an action that clears all three layers executes. Any layer can escalate or block, and every outcome — allow, escalate, or block — is written to the tamper-evident ledger. The Policy Engine is a hard authority boundary (deterministic, not a guess); the Sentry adds defense-in-depth risk screening; the Isolation Layer contains whatever does run. That ordering is the thesis: trust comes from containment, not from trusting the model.

Watch an autonomous agent work a task while CFAM governs every action in real time — each proposed action is checked, decided, and recorded before anything executes. Pick a scenario and watch the gate stack decide, live.

With CFAM vs without — same agent, same task

A controlled comparison: the identical agent plan run with governance off and on. Tools are simulated (no real side effects) — the point is the decision, and the audit trail on the governed side.

✗ Without CFAM
✓ With CFAM

Emergency stop

Halt a single task or everything, instantly. While tripped, the gateway denies every governed action in scope (fail-closed) ahead of policy and blast-radius, until an operator resets it — trip & reset are audited. Try it, then run a mission below.

Governed agent loop

Run a mission above — the model proposes actions and the GovernedToolGateway decides each one before it can run. A refused action never reaches the tool; every decision is written to the Audit ledger.

Industry scenario packs

Each pack ships its own signed manifest — different tools, domains, and cost ceiling. Pick a vertical, then run a governed mission against it.

Gate-by-gate view (single actions)

Pick a scenario above to step through the gate stack.

The governed agent loop routes every model-proposed action through the gateway (simulated tools, real audit); the gate-by-gate view scores single actions against the same engine. Both write to the tamper-evident Audit ledger.

Transaction rollback (saga)

A multi-step plan commits real side effects as it goes. When a later step is refused, CFAM unwinds the committed steps in reverse via each tool's registered compensation — leaving a safe state, every undo audited. This is the REMEDIATE arm of the decision model.

Propose an action

Decision trace

Run an action to see the gate stack and decision.

Authority in force (signed capability manifest)

Outbound data governance (DLP)

Even for an allowed destination, regulated data shouldn't leave in the clear. DLP classifies the payload and redacts, blocks, or flags disallowed classes — after Policy and Sentry, so it can only tighten, never loosen. The same engine runs in the gateway (try the “Sensitive data handling” mission in Scenarios).

Define the capability manifest — the authority every layer enforces. Author it here; on save it's Ed25519-signed and instantly enforced. Then test an action against it and watch the same gate stack decide.

Capability manifest

Code-execution tools (e.g. execute_code) can't be enabled in the public demo — the editor rejects them.

Test an action against this policy

Save a policy, then test an action against it.

Signed manifest in force

Load or save a policy to see the signed manifest and its public key.

Policy-as-code lifecycle

Manifests are authored as a base + per-environment overrides, versioned, and gated before promotion: a candidate is scored against a labeled corpus, and a safety regression (a case that should block now passing) blocks activation.

Don't trust our test data. Use your own.

The credible way to test a detector is on data its authors didn't write. Here's the workflow:

  1. Copy the generator prompt below and paste it into any AI (ChatGPT, Claude, Gemini).
  2. It returns a .jsonl file — one labeled test case per line, a mix of benign actions and attacks.
  3. Load that file here (or paste the lines), then Run dataset.
  4. Read the scorecard: attack recall, false-positive rate, and the exact cases it missed or wrongly blocked.

How it spots its own errors: each line carries a label — category and expected — written by your generator, not by us. The engine decides using only the action (tool, endpoint, cost, payload); it never sees the label. The scorecard then compares the two: an attack the engine allowed is a false negative; a benign action it blocked is a false positive. The engine can't grade itself — the answer key does.

Test data (JSONL — one case per line)

Tamper-evident audit ledger

#tooldecisionstoppedriskreasonentry hash
Each entry's hash covers its content plus the previous entry's hash. Altering any past row breaks the chain from that point — which “Verify” detects. Live-tester actions are recorded here; batch runs are not (they're scored without side effects).

Prove it's tamper-evident

Attack a real hash-chained ledger yourself. Edit any recorded field and re-verify — the chain breaks at exactly that entry. This runs the same verification code the live ledger uses, on a throwaway copy (your real ledger above is untouched).

#tooldecisionriskreasonentry hash
A plain hash chain can't detect tail truncation (deleting the newest entries) — try “Delete last entry”. That's why CFAM also signs the ledger head (Ed25519): in a persistent deployment the signed head catches truncation on load.

SIEM export & alerting

Every ledger decision is mirrored to your SIEM (syslog/CEF, Splunk HEC, Datadog, or webhook) and matched against alert rules that route blocks / escalations / kill-switch / blast-radius to Slack/PagerDuty. Best-effort — a downstream outage never breaks the local tamper-evident ledger.

Exported events (CEF)
Alerts fired

External anchoring (WORM / transparency log)

A plain chain — even a local signed head — can be deleted or rolled back on the same box. CFAM anchors each head to an append-only, hash-chained external log (WORM object-lock / transparency log), so a later ledger shorter than the anchored height is provably inconsistent. This is what catches the truncation the tamper demo above can't.

seqheightledger headanchor hash

Live governance telemetry from the audit ledger — the decision mix, where actions are stopped, what's blocked most, and the tamper-evident integrity of the trail. Read-only.

Decision stream (recent)

no decisions yet

allow   escalate   block

Where actions are stopped

Top blocked tools

Gate performance (measured here)

The governance overhead, measured in this environment on synthetic actions — not an asserted number. Reproduce anytime with python -m cfam.bench (or make bench).

How CFAM's controls map to OWASP LLM Top 10 and the NIST AI RMF — with honest done / partial / out labels and live evidence counted from the audit ledger. This is a control map, not a certification.

OWASP LLM Top 10 (2025)

#RiskCFAM controlStatusLive evidence

NIST AI RMF 1.0

FunctionHow CFAM addresses itStatusLive evidence

Wiring CFAM in front of your agent is a few lines: hand the agent a GovernedToolGateway instead of the real tools. The rule that makes it non-bypassable — the gateway is the agent's only path to a side effect (see docs/ENFORCEMENT.md).

1 · Gate your tools (the essential wiring)
from cfam.engine import CFAM
from cfam.gateway import GovernedToolGateway, ActionDenied

engine = CFAM()                                  # loads your signing key (docs/KEY_CUSTODY.md)
engine.default_manifest("RECEPTIONIST-001")      # or register your own signed manifest (below)

gw = GovernedToolGateway(engine, "RECEPTIONIST-001")
gw.register("send_email", real_send_email, endpoint="https://email.internal")

# Hand the agent the gateway, not the tools:
try:
    out = gw.invoke("send_email", "Confirm Tuesday 2pm to dana@acme-corp.com")
except ActionDenied as e:
    ...   # blocked / escalated at the boundary — the real tool never ran
2 · Author a signed capability manifest
from datetime import timedelta
from cfam.manifest import CapabilityManifest, now_utc

m = CapabilityManifest(
    task_id="RECEPTIONIST-001",
    allowed_tools=["schedule_meeting", "read_calendar", "send_email"],
    allowed_endpoints=["https://calendar.internal", "https://email.internal"],
    allowed_recipient_domains=["acme-corp.com"],
    max_cost=25.0,
    window_start=now_utc().isoformat(),
    window_end=(now_utc() + timedelta(hours=12)).isoformat(),
)
engine.register_manifest(m)   # Ed25519-signs it; every layer enforces it
3 · MCP — govern a tool server
from cfam.adapters import govern_mcp_call_tool

# Wrap your MCP server's call_tool(name, arguments) handler (sync or async):
governed_call_tool = govern_mcp_call_tool(gw, mcp_server.call_tool)

# Point the agent's MCP client at governed_call_tool — a tool call now cannot
# reach the real server without clearing the gate; refusals return an MCP error.
4 · LangChain — govern a tool
from cfam.adapters import govern_langchain_tool
from langchain_core.tools import StructuredTool

governed = govern_langchain_tool(gw, my_tool, cost=0.0)   # raises ActionDenied off-policy
safe_tool = StructuredTool.from_function(
    governed, name=my_tool.name, description=my_tool.description)

agent = create_agent(llm, tools=[safe_tool])   # the agent only ever sees governed tools

Install: pip install . from the repo (deps: fastapi, cryptography, pyjwt). The adapters are duck-typed — CFAM does not pull MCP or LangChain into your install.

When the Sentry escalates — a risk it can neither clear nor condemn — the action is held for a human, never silently run or dropped. Approvers act on it; a notification fires, and if no one responds within the SLA it auto-denies (fails closed). Every outcome hits the audit ledger.

Reviewer console

No actions awaiting review. Click “Simulate an escalation” to hold one.

Resolved

Nothing resolved yet.

Notifications

No notifications yet.

Approve/deny are role-gated (only approver can act). In production the role comes from your IdP via the OIDC relying party; the SLA channel is a pluggable notifier (webhook / Slack / email).

Full user documentation for the CFAM console and a complete, honest reference of every implemented capability. CFAM governs an agent's actions — an agent is handed a GovernedToolGateway and can only act through it; each action clears Policy → Sentry → Isolation and is written to a tamper-evident ledger. Nothing reaches a real tool without passing the gate.

Console guide — every tab

How it works

The architecture overview. The diagram shows the full pipeline: the agent proposes an action, it enters only through the GovernedToolGateway, is checked against the signed capability manifest, then cleared (or stopped) by Policy → Sentry → Isolation, with every decision written to the Audit Ledger. Outcomes are ALLOW (executes), ESCALATE (held for a human), or BLOCK (denied).

Scenarios

The interactive heart of the demo. With CFAM vs without runs the same agent plan governed and ungoverned side-by-side (the incident happens without, is prevented with). Emergency stop trips the kill switch. Governed agent loop runs a model's tool-use loop through the gateway (scripted by default; live LLM when enabled). Industry scenario packs run finance / healthcare / support missions against their own signed manifests. Gate-by-gate steps a single action through the stack, and Transaction rollback shows a saga unwinding a partially-executed plan.

Live tester

Propose a single action (tool, payload, endpoint, cost, recipient) and see the decision, the risk score, and every gate. Shows the manifest in force. The Outbound DLP card classifies a payload and redacts / blocks / flags disallowed data classes (PII, secrets) before egress.

Policy editor

Author a capability manifest with no code; on save it's Ed25519-signed and instantly enforced, then test an action against it. The Policy-as-code lifecycle card composes a candidate from base + environment overrides, scores it against a labeled corpus, and refuses promotion on a safety regression — with per-environment versioning and rollback.

Batch scorecard

“Don't trust our test data — use your own.” Paste JSONL test cases (or generate them with any AI via the prompt) and CFAM reports attack recall, false-positive rate, a confusion matrix, blocks-by-layer, and an explicit list of what it missed. Numbers are measured on your data, never asserted.

Audit ledger

The tamper-evident record of every decision (append-only, SHA-256 hash-chained). Prove it's tamper-evident lets you edit an entry and watch verify() catch the broken chain. SIEM export & alerting streams decisions as CEF and raises routed alerts. External anchoring shows how a WORM/transparency log catches truncation a local chain can't. Download signed report saves an Ed25519-signed session report anyone can verify with the public key.

Metrics

Live governance telemetry from the ledger — decision mix and rates, a decision-stream sparkline, where actions are stopped, top blocked tools, and ledger integrity. Gate performance measures latency (p50/p95/p99) and throughput in this environment (measured, not asserted).

Compliance

Maps CFAM's controls to the OWASP LLM Top 10 and NIST AI RMF with honest done / partial / out-of-scope labels and live evidence counted from the ledger. A control map, not a certification.

Integrate

Copy-pasteable snippets to wire CFAM into your agent: gate your tools, author a signed manifest, and wrap an MCP or LangChain tool surface. The snippets are kept API-accurate by tests.

Approvals

The human-in-the-loop reviewer console. Escalated actions are held, a notification fires, and an approver (role-gated) approves or denies; if no one acts within the SLA it auto-denies (fails closed). Every outcome is audited.

FAQ

Plain-language answers with the full system network diagram — how CFAM sits between the agent and its actions, how it installs, and how it works with any model.

Feature reference — everything implemented

CapabilityWhat it doesStatusWhere
Policy EngineDeterministic allowlist vs the signed manifest (tool · endpoint · cost · time window · recipient domain); denies by default.donecfam/policy.py
Capability ManifestEd25519-signed authorization contract; publicly verifiable with the public key alone.donecfam/manifest.py
Sentry NodeTransparent multi-signal risk model (no ML / no LLM): injection, exfiltration, drift, obfuscation. Bands allow/escalate/block.partialcfam/detectors.py
Isolation LayerCode-exec in a subprocess with CPU/mem/file/time limits + stripped env; egress denied at the container boundary.partialcfam/isolation.py
Audit LedgerAppend-only, SHA-256 hash-chained, persistent (JSONL+fsync), Ed25519 signed head; tamper-evident.donecfam/ledger.py
Governed Tool GatewayThe mandatory, non-bypassable choke point — the agent gets only the gateway; a refused action never runs.donecfam/gateway.py
Framework adaptersDuck-typed MCP (call_tool) and LangChain wrappers so governance applies wherever the agent runs.donecfam/adapters.py
Human approvals + SLAEscalations held for a role-gated approver, notified on a channel, auto-denied (fail-closed) on SLA timeout.donecfam/approvals.py · notify.py
Blast-radius ceilingsCumulative cost / action-count / records / per-tool limits across a task.donecfam/blast_radius.py
Emergency kill switchAbsolute fail-closed stop for a task or globally; checked ahead of policy; trips/resets audited.donecfam/killswitch.py
Outbound DLPClassifies payloads (PII/secrets) at egress and redacts / blocks / flags; only tightens, never grants.partialcfam/dlp.py
Saga / rollbackUnwinds a partially-executed plan in reverse via per-tool compensations; audited.donecfam/saga.py
External anchoringAppend-only WORM / transparency-log anchor of the ledger head; catches whole-file truncation/rollback.partialcfam/anchor.py
SIEM export + alertingMirrors every decision as CEF to Splunk HEC / Datadog / webhook; routed alerts on block/escalate/kill-switch.donecfam/siem.py
Signed session reportEd25519-signed report of decisions + integrity + manifests; independently verifiable, no secret.doneapp.py · /api/report
Offline verifierThird-party checks the ledger chain (+ manifest signature) read-only, with no secret.donecfam/verify.py
Key custodyPluggable KeyProvider: own encrypted keystore (rotatable) now, HashiCorp Vault / KMS seam later.donecfam/keyvault.py
Identity (OIDC)OIDC relying party — validates the customer's JWTs and maps groups to CFAM roles; no user store.donecfam/auth.py
Policy-as-codeBase + env overrides, a pre-activation gate (refuses regressions), per-env versioning and rollback.donecfam/policycode.py
Vertical packsFinance / healthcare / support scenario packs, each with its own signed manifest.donecfam/verticals.py
MetricsRead-only governance telemetry aggregated from the ledger.doneapp.py · /api/metrics
Benchmark harnessMeasures gate latency (p50/p95/p99) + throughput; reports, never asserts.donecfam/bench.py
Compliance mappingOWASP LLM Top 10 + NIST AI RMF control map with honest labels + live evidence.partialdocs/COMPLIANCE.md

done implemented & tested · partial real mechanism, documented limits · out out of scope. No performance/coverage number is asserted — the batch scorecard measures on your data. CFAM is a project of GALXEE AI, built with Threat Tape LLC.

Run & verify it yourself

make serve      # run the console locally (http://localhost:8000)
make test       # run the full test suite
make bench      # measure gate latency/throughput in your environment
make verify     # independently verify a persisted audit ledger

python -m cfam.keyvault init      # create an encrypted signing keystore
python -m cfam.bench -n 3000      # benchmark the gate
python -m cfam.verify             # offline ledger + manifest verification

See the Integrate tab for wiring snippets, and docs/ in the repo for the FAQ, key custody, enforcement model, compliance mapping, and this user guide (docs/USER_GUIDE.md).

A plain-language tour of every part of the system that's actually built — who talks to what, and where each decision gets made. CFAM is one self-contained deployment that runs on your infrastructure, between your agent and the things it can touch.

CFAM · SINGLE-TENANT DEPLOYMENT — runs on your infrastructure Users Operator · Approver Auditor · Read-only Customer IAM OIDC / SAML identity AI Model Provider Claude · GPT · open model AI Agent reasons → proposes actions (may be wrong or compromised) Management & Approval API role-gated via OIDC — operator · approver · auditor · read-only Signed Capability Manifest · Ed25519 allowed tools · endpoints · cost ceiling · time window GovernedToolGateway the only path to side effects — mandatory, not advisory Approval Queue human-in-the-loop on escalate Blast-Radius Ceilings cumulative cost / action limits 1 Policy Engine deterministic allowlist check (signed manifest) outside → block 2 Sentry Node multi-signal risk screen (no ML / no LLM) risky → escalate 3 Isolation Layer constrained subprocess exec CPU·mem·fs limits bounds blast radius Audit Ledger append-only · hash-chained · Ed25519 signed head — every decision recorded Your tools & endpoints email · calendar CRM · APIs code-exec sandbox (your integrations) Offline Verifier python -m cfam.verify sign in request validate JWT reasoning proposes action MCP·LangChain adapter authority pass pass execute the approved action checks ceilings escalate approver acts verify
request / data flow allowed path escalate / approval read / verify

Two streams meet in one deployment. People (left, top) authenticate through your own IAM and reach the role-gated management & approval API. The agent (left, bottom) takes its reasoning from any model provider and proposes actions, which enter only through the GovernedToolGateway — the single door to every real tool. Each action runs Policy → Sentry → Isolation, every decision is written to the tamper-evident ledger, escalations wait for a human, and the whole chain can be verified offline. Nothing reaches your tools without clearing that path.

Start here

How does CFAM get between the agent and the outside world?

It isn't a network proxy. It sits at the tool-invocation boundary: instead of the real tools, your agent is handed a GovernedToolGateway and can only act through it. Every proposed action runs Policy → Sentry → Isolation → Ledger before any side effect — and if any layer says no, the real tool is never called. The one rule: the gateway must be the agent's only path to side effects.

How do I install it?

CFAM is a small Python package plus an optional FastAPI service, packaged as a container and deployed once per customer on your own infrastructure. You author a signed capability manifest, register your tools through the gateway (or wrap an existing MCP / LangChain tool surface with the adapters), point it at your OIDC identity provider, and run it next to your agent. Ledger goes to durable storage. Full steps are in the deployment docs.

How does it work with Claude, ChatGPT, or other models?

It governs actions, not the model, so it's provider-agnostic. The model reasons and proposes tool calls; CFAM decides whether each call executes. Wire it via function-calling, an MCP wrapper, or a LangChain tool wrapper. Switching models changes nothing about your policy. Honest limit: CFAM stops the agent from doing something harmful — it isn't a content filter for what the model says.

How it works

Is CFAM an AI model? Does it use machine learning?

No. The governance path is deliberately deterministic and explainable — no ML, no second LLM. The Policy Engine is an exact allow-list check; the Sentry is a transparent multi-signal risk model where every firing signal carries a weight and a human-readable reason. A rules-based detector will miss novel phrasings, so the Sentry is defense-in-depth on top of the hard policy boundary, never a replacement for it.

What is the signed capability manifest?

The per-task contract: which tools, endpoints, cost ceiling, and time window an agent is allowed. It's Ed25519-signed, so the authority can't be silently edited — every layer verifies the signature before enforcing it. That turns "this agent may only email the customer domain" into a cryptographically anchored fact.

How do I know the audit log wasn't tampered with?

The ledger is append-only and hash-chained: each record commits to the previous one, so any edit, deletion, or reorder breaks the chain. The head is signed to catch truncation of recent entries, and you can verify the whole chain offline at any time with python -m cfam.verify, independent of the running service.

What does the Isolation Layer actually isolate?

Code-execution tools run in a separate process with real OS resource limits (CPU, memory, process count, file size), a stripped environment, an isolated temp dir, and a hard timeout — genuine containment of CPU/memory/filesystem blast radius. Honest scope: full network-egress isolation needs OS namespaces (deny egress at the container boundary today); the production target is gVisor / Firecracker micro-VMs.

Integration & trust

Do I have to rewrite my agent?

Usually no — you re-point your tool layer. If you expose tools via MCP or LangChain, wrap them with the adapters and your agent barely changes; otherwise you route calls through gateway.invoke(...) instead of calling tools directly. The work is "make the gateway the only door," not "rebuild the agent."

What happens on a risky action — can a human approve?

Three outcomes: allow (executes), block (denied; the agent gets a structured refusal it can reason about), and escalate (held in the approval queue for a human). An authorized approver releases or denies it, and that decision is itself recorded. Blast-radius ceilings also cap cumulative spend or action count so many individually-allowed actions can't add up to harm.

Who can change policy or approve actions?

CFAM is an OIDC relying party: it validates your IdP's tokens (issuer, audience, signature) and maps your IAM groups to CFAM roles — operator, approver, auditor, read-only. It owns no user accounts, pins token algorithms (no alg=none), and requires a real expiry. SAML can be added behind the same interface.

Can the agent bypass CFAM?

Only if you give it an ungoverned route to a side effect. The guarantee is structural: the agent holds the gateway and nothing else, so a denied action can't fall through to the real tool. Your job is to ensure there's no second door — a stray API key, a tool registered outside the gateway, raw network access. That invariant is worth pen-testing.

What's the failure mode if CFAM goes down?

It fails closed at the action boundary: no gateway, no governed actions. We treat "agent silently acts ungoverned" as the unacceptable outcome, so the design biases toward denying rather than letting actions through unchecked.

Maturity

How mature is CFAM — is it production-ready today?

It's an honest, working pre-1.0 build, not vaporware: policy engine, signed manifest, multi-signal Sentry, OS-level code isolation, hash-chained ledger, mandatory gateway, MCP/LangChain adapters, human-in-the-loop approvals, blast-radius ceilings, and OIDC are implemented and tested. The road to production is stronger isolation (micro-VMs), richer detection, durable/operational hardening, and packaging. We'll tell you exactly what's GA vs. roadmap for your use case rather than blanket-claim "enterprise-ready."

CFAM is a project of GALXEE AI, built in collaboration with Threat Tape LLC. This console is a demo of the real engine; numbers are measured, never asserted.

Setup / install — cfam.yaml

The browser front-end to the same installer the CLI uses. Edit your cfam.yaml below, then Validate to see exactly what it does and does not enforce, or Generate the deployment artifacts. This calls the same cfam.config schema and cfam.generate generators as python -m cfam.config validate — no logic is duplicated. No secret ever leaves the process: secrets stay references (env:/vault:/kms:) and generated files carry REPLACE_ME placeholders only.