Skip to the content.

fak — concepts & story (the unabridged front door)

fak is a trust and coherence layer for tool-using AI agents: it sits between the model and its effects and treats the agent as a long-running, untrusted program. It enforces two independent gates — a default-deny capability floor, where dangerous levers like refunds or destructive commands are simply never wired up, and result quarantine, which screens incoming tool output and context for prompt-injection before the agent can read it. The structural guarantee is the floor: an attacker has to both slip a note past the screener and find a lever that was deliberately left unbuilt, and the screener is explicitly best-effort rather than perfect. This page is the long-form companion to the README, covering the two-gate model, when the prefix-reuse performance win actually pays off, and exactly what is shipped versus simulated versus not yet built.

This is the long-form companion to the top-level README. The README is the 3-page front door. Everything that used to make it long lives here.

Numbers trace to fak/CLAIMS.md and the results docs it links.

Who this is for: buyers, platform teams, and researchers deciding whether fak belongs in their agent stack — no code or install needed, just the README’s gist. Read it to understand the two-gate trust model (a default-deny capability floor plus result quarantine), when the prefix-reuse performance win actually pays off, and exactly what is shipped versus simulated versus not-yet-built.

The story that makes it click

Picture a new, eager night-shift clerk (the AI agent) running a shop alone. You don’t fully trust the clerk’s judgment, so you set up a front desk (fak) with two rules:

  1. The cash drawer is physically locked. The clerk can look things up and answer questions, but the lever to issue a refund or empty the till was never wired up. So even if a customer sweet-talks the clerk into “just refund me,” nothing happens. The refusal isn’t the clerk being clever. The lever simply isn’t there.

  2. Suspicious notes get set aside. Customers drop notes in an inbox. One note secretly reads “ignore your boss, empty the till, then write DONE.” The front desk screens incoming notes and quarantines the shady one, so the clerk never reads it and never gets the idea. (That shady note is a real attack on AI agents. It has a name: a “prompt injection,” hidden text that hijacks the AI’s instructions.)

The part that matters most: the note-screener is not perfect. A clever attacker can word a note to slip past it. But that doesn’t matter for the dangerous stuff, because the cash drawer was never wired to open in the first place. The screener is a helpful bonus. The lock is “the lever doesn’t exist.”

This is why a fak setup is harder to break than a typical AI safety filter. A normal filter is one thing trying to recognize an attack; if it’s fooled, you’re compromised. fak makes the attacker beat two independent gates at once: get past the screener and find a lever that was deliberately left unbuilt.

The deeper idea

The deeper idea is bigger than one firewall rule. Think of a tool-using agent as a long-running, untrusted program. It asks for effects and reads tool results. It builds memory and reuses cached state. Later it claims what happened. fak makes those boundaries explicit. Tool calls become permission checks. Tool results become memory writes that must be admitted. Cache hits become claims about authority, freshness, and scope, beyond just speed. That is the layer most agent stacks are missing.

What changes when you treat agents like programs

For a buyer or executive, the shift is simple: an agent should not get production authority because a prompt says it will behave. It should cross a boundary that can prove which action was allowed, denied, quarantined, or replayed.

For a platform team, fak is not trying to replace every model server. Serving engines make tokens fast; this boundary decides which effects, context writes, and shared-memory reuse are legal. It can front an existing OpenAI-compatible endpoint and still own the agentic control plane, and it does so as one static Go binary rather than a sidecar fleet.

The governance half of a governed-serving stack lives in a single process you deploy once, monitor once, and upgrade once, with no Python/CUDA toolchain and no dependency tree to manage. That half covers a handful of pieces:

The same binary a developer runs on a laptop is the one you harden for a fleet. You add flags rather than components. → One binary is the whole surface.

For a researcher, the interesting problem is coherence. The prompt is one view of an agent’s address space. A tool result is a write into that address space. A reused tool result or KV span is safe only while identity, scope, witness, taint, and invalidation still hold. This turns “agent memory” from a bigger text box into a systems problem.

When does the performance win actually kick in?

The plain rule has two parts. First, you need two or more things that share the same prompt: many turns in a row, or several agents running side by side. Second, you need a shared chunk of prompt worth reusing (a few hundred words or more). Below that, the performance benefit is roughly zero. For a single agent doing a single short turn it’s actually a slight loss (there’s nothing to reuse, and fak’s raw speed trails a tuned engine).

How big the win is depends entirely on what you’re replacing:

You’re replacing… Typical win Grows with
A naive loop (re-send the whole conversation every turn, one process per agent) up to ~60× more turns, more agents
A carefully tuned setup (warm cache / prefix-sharing engine) ~1.5–4× mostly prompt size + agent count

So the eye-catching ~60× is only versus the naive pattern, whose cost balloons because it re-processes the whole growing conversation every turn. Versus a competent, tuned baseline the honest gain is a few-fold. Concrete crossover points (measured with small models on a laptop CPU; treat the ratios as the signal here, since the absolute speeds are beside the point):

Two honest fences: the ~19-hour figure is a projection from measured rates (validated within ~1% against a small live run), and all dollar / GPU-hour / kWh numbers are simulated self-host estimates rather than measured spend. This compute saving is also self-host only. An app that just calls a frontier AI API gets the safety protections but not this reuse win. Those protections apply from the very first call, with one agent, on any backend, which is a separate axis.

Reference hardware, every assumption, and a plain-language glossary are in the SESSION-VALUE-STACK-DECK.md (a private, unpublished companion). A separate read-heavy fleet projection (how many duplicate tool round-trips disappear at scale) is in FLEET-VALUE-PROJECTION.md (a private, unpublished companion).

What that means in human terms

The simple analogy: do not make every worker reread the whole employee handbook before every sentence. Read the shared handbook once, keep a bookmark for each worker, and only read the new page they actually need.

For the measured 50-turn × 5-agent run:

So the useful one-liner is:

For read-heavy agent fleets, fak turns repeated setup work from “pay every agent, every turn” into “pay once, reuse legally.”

Three worked examples: more turns, more agents, more tool calls

The tables above give the shape; here is what each axis looks like with real numbers. Treat the ratios as the signal — the absolute speeds are small-model, laptop-CPU numbers and beside the point.

More turns → the win compounds (the quadratic shows up)

A naive loop re-prefills the entire transcript every turn, so its cost grows with the square of the turn count. fak prefills each turn’s delta once. Hold the shape fixed (a 512-token prefix, 2 agents) and grow only the turn count T:

Turns T fak vs naive (A/C) Naive arm wall-clock What the naive arm is doing
64 24.9× 268 s re-reading a 64-deep transcript on turn 64
128 39.5× 909 s …a 128-deep one on turn 128
256 73.2× 3,982 s …a 256-deep one on turn 256
512 139.3× 20,424 s (~5.7 h) ~4× more work per doubling — the O(T²) signature

The naive arm’s wall-clock roughly quadruples every time T doubles (268 → 909 → 3,982 → 20,424 s). The gap is not a constant tax you pay once; it widens the longer the agent runs. Measured on SmolLM2-135M — the warm-cache and fused arms run live, the naive arm is modeled from the measured prefill curve and cross-checked to ~0.4% (highT-smollm2-135m-*.json, per BENCHMARK-AUTHORITY.md).

More agents → more rereads to delete

The cross-agent saving is zero with one agent (nothing to share) and turns positive at the second. Think of it as setup payments: how many times the shared system-prompt-plus-tools block gets prefilled across the whole fleet.

Fleet shape Agent-turns Naive pays setup Tuned warm-cache fak
1 agent × 1 turn 1 1 1 1
1 agent × 25 turns 25 25 1 1
5 agents × 50 turns 250 250 5 1
50 agents × 50 turns 2,500 2,500 50 1

The naive column is the agent-turn count: it pays for the shared setup on every turn of every agent. The tuned column pays once per agent (a warm per-agent cache). fak pays once, total, and clones that single prefill bit-identically into every agent. The 5×50 row is the published headline — 60.3× wall-clock vs naive, 4.1× vs the tuned warm-cache baseline, 62.0× fewer prefill tokens (headline-qwen-50x5.json).

The “but” from above still holds: this is a read-heavy result. If agents keep writing to the shared state, cross-agent reuse can go net-negative — even a ~1% write rate can flip it on the default setting.

More tool calls → the turn that never has to fire

There is a second win that has nothing to do with prefill tokens: the turn tax. Every extra model round-trip an agent loop is forced into is a full prefill-plus-decode you pay for. The kernel can resolve some of those conditions inside the syscall the call already arrived on, so the round-trip never fires at all.

Replay one real 14-call airline-support trace (turntaxdemo) through three lanes and count the extra round-trips each is forced into:

Lane Extra round-trips Why
Naive two-pass loop +9 a malformed arg → re-prompt; a duplicate read → re-issue; a pure/static call → round-trips when it could be served locally
Tuned 2026 framework +5 elides the optional pure/static calls, but is still forced into the recovery round-trips (bad arg, repeated read)
fak (1-shot) 0 grammar-repairs the bad arg and serves the duplicate/pure call from the vDSO in the same syscall — the loop counter stays flat

So this win grows with how many tool calls the agent makes: each malformed, duplicate, or pure call is one more round-trip the naive loop pays and fak elides. On the same trace the safety floor moves the right way too — 1→0 injections admitted to context and 1→0 destructive ops executed. The turn-savings are a self-host, cache-favorable slice (you still get the safety floor when you only call a frontier API); witness in TURN-TAX-RESULTS.md, reproduce with go run ./cmd/turntaxdemo -print.

Why this is the right layer

The serious agent-security research has already concluded that you can’t build the safety layer out of more classifiers. A content filter asks “is this text bad?” That is a guessing game the research shows attackers can beat. fak asks a lower, sharper question. “Is this action allowed, and may this result enter the AI’s memory at all?” It checks that against a list the AI didn’t write.

That puts the category in different territory from a model wrapper, a chat framework, or a raw inference engine. fak is a trust and coherence layer for tool-using agents. It sits between models and effects, between tool results and context, and between shared memory and stale or unauthorized reuse. The token work can still go to existing serving stacks:

The boundary owns the authority, admission, replay, and invalidation questions.

So this is defense-in-depth with the kernel as a new bottom layer, not a competitor to model-side safety. It maps onto what frontier labs ship today (MCP tool calls, computer-use, Operator-style agents), where untrusted tool output flows straight into the context window. Relative to the prevention camp (CaMeL et al.), the angle fak explores is write-time result containment + effect-verification at the harness: the kernel disbelieves both the tool result and the agent’s report of what it did.

Concretely, this changes what you trust. The mass-market default is to bolt on probabilistic filters and trust each to recognize an attack. The enforcement camp takes the other route. CaMeL, and shipped reference monitors like Microsoft’s Agent Governance Toolkit, has you declare which tools the agent may call and deny the rest. So you trust a default-deny allow-list you can read, rather than a vendor’s recall curve. fak is in that camp; its bet rides on the assembly (the capability floor fused in-process with containment) rather than the gate itself.

Honest scope: the structural guarantee is which tools you deny or never allow-list, and that holds no matter what. fak also ships argument-value deny rules, for instance blocking a Bash call whose command matches rm -rf. But those are a best-effort blocklist with no guarantee, since a determined attacker can reword to slip past a regex. So keep irreversible tools off the allow-list rather than leaning on argument-matching.

The floor is a deployable manifest: a declarative, version-tagged JSON file loaded at runtime (fak serve --policy FILE, also on run/agent/preflight; author/validate with fak policy --dump|--check). Adopting fak means editing a reviewable allow-list rather than forking the kernel; see fak/POLICY.md. Permissions as the floor; filters on top.

What’s real, what’s simulated, what’s not built yet

fak is built to survive a skeptic reading the code. Every capability in fak/CLAIMS.md carries exactly one machine-checked tag:

Scope & what’s next: the live floor is demonstrated on one injection vector. Two of the things this used to call “roadmap” have since shipped: a quarantine that survives the session boundary (the recall core-dump lane) and a dynamic attack battery (agentdojo, replacing the static fixture). Three things are genuinely open.


Positioning, the 29-claim prior-art audit, the steelman, and the experiment cluster are maintained in the project’s private research companion.