Why functional programming for coding agents works
A workflow note on functional programming for coding agents: declared inputs, scope ledgers, and receipts that keep Cursor agent diffs reviewable.

Functional programming for coding agents means giving every run declared inputs, declared outputs, and no quiet side effects in between. That habit is what keeps an agent's diff reviewable, because a reviewer can check the change against a contract instead of replaying a chat from memory. With Cursor, Anysphere's AI code editor, the failure that pushed us here was small: a routine dependency lookup carried credentials into the transcript, and a style preference turned into a security problem in one keystroke.
Hidden state is where the surprises live. When trust is high and review pressure is real, the thing that breaks first is not model capability, it is the story a reviewer can tell about what just happened.
See where hidden state actually bites
We keep logging the same four failures, and each one is hidden state wearing a different jacket.
The first is recursive handoff blur. Chained agents return tidy summaries that quietly omit the paths a child touched, so the parent's picture of the run drifts from the truth like a game of telephone. The fix is to treat children like pure functions: every child returns paths touched, commands run, and the tests that prove a guard held. No side channels.
The second is the review queue where CI is green and a reviewer still asks why this approach, with no written answer anywhere. The reasoning lived in the session, and the session is gone. A three-line decision stub in the PR template fixes it: constraints considered, alternatives rejected, verification proof.
The third is Cursor scope fog. The .mdc rule language sounds precise until two reviewers argue about what it meant. Cursor's agent docs give you the mechanism, but the contract is yours to write.
The fourth is permission creep in Claude Code, Anthropic's coding agent. On a shared laptop, bash approvals become muscle memory, which is global mutable state in human form.
Write a scope ledger before the run starts
The cheapest receipt is a five-line ledger you paste into the parent chat before an agent does anything. It reads like a function signature for the run: goal, allowed paths, forbidden paths, verification command, merge owner.
Once that ledger exists, review stops being a debate about what the prompt meant and becomes a quick check of the ledger against the diff. That is a faster and far less political conversation.
Here is the companion file we keep at the repo root so every tool starts from the same boundaries.
---
description: Delegation boundary snapshot (adapt globs to your repo)
globs:
- "**/*"
alwaysApply: false
---
- Cursor: keep scopes explicit in `.mdc`; forbid undeclared MCP domains.
- Claude Code: cite `CLAUDE.md` precedence before expanding bash scope.
- Codex: ensure `AGENTS.md` carries replay-friendly verification notes for CLI runs.
Connector scope deserves the same treatment. The MCP specification exists so a server can state its capabilities up front rather than have an agent discover them mid-run. Claude Code's getting started guide covers the file mechanics for the supremacy clause described below.
Pin down precedence in CLAUDE.md
The top of CLAUDE.md should answer one question plainly: when rules disagree, which one wins? State which hooks take priority, which folders require human eyes, and where temporary overrides live.
Write that once and sessions stop inventing policy mid-run. Shared laptops stop quietly accumulating approvals that nobody remembers granting.
John Ousterhout names the underlying trap in A Philosophy of Software Design: complexity is dependencies plus obscurity. Agents handle dependencies fine. Obscurity defeats them, and undeclared state is obscurity in its purest form.
Check artifacts, not vibes
Review gets fast when every question maps to something written down. We run each agent PR past this short gate.
| Gate | Question |
|---|---|
| Rules precedence | Which .mdc, SKILL.md, or CLAUDE.md governed behavior? |
| Connector truth | Which MCP servers fired, and were they expected? |
| Reviewer path | Can someone unfamiliar trace intent without chat replay? |
| Risk routing | Were red folders touched, and who approved? |
Before merge, the reviewer walks one strip:
- Red-folder paths received explicit human acknowledgement.
- Scopes in the PR body match folders in the diff.
- Primary-doc links were smoke-checked after publishing edits.
- MCP connectors mentioned, if any, list owners.
If your repo cannot state its boundaries plainly, agents will guess, and guessing scales poorly. Functional discipline shrinks the guessing surface; it does not remove the need for owners. When the boundaries carry real risk, we hand teams the NIST AI Risk Management Framework. This is the kind of contract thinking we cover in our agentic coding governance topic, and it pairs with the same approach to specs for coding agents.
Common questions
-
Does functional programming for coding agents reduce review time?
Yes, because declared inputs and outputs shrink what a reviewer has to reconstruct. When a run starts from a five-line scope ledger and ends with a child receipt of paths touched and tests run, the diff gets checked against a contract instead of against someone's fuzzy memory of the chat. The reviewer reads faster and second-guesses less.
-
What goes in a scope ledger?
Five lines in the parent chat: goal, allowed paths, forbidden paths, verification command, and merge owner. That single block turns review from a debate about what the prompt meant into a quick check of the ledger against the diff. It is the same idea as a function signature, applied to a whole agent run.
-
How do I stop bash approvals becoming muscle memory in Claude Code?
Write a supremacy clause at the top of
CLAUDE.mdstating which hooks win, which folders require human eyes, and where temporary overrides live. Once precedence is written down, sessions stop inventing policy mid-run, and shared laptops stop collecting silent approvals nobody remembers granting. The clause is the boundary; the human acknowledgement is the receipt. -
Is this only useful for big teams?
No. A solo engineer benefits the first time an agent touches a folder they meant to keep off-limits. The ledger and the supremacy clause take a few minutes to write and pay off on the very next run, long before headcount makes them mandatory.
Start here
Paste a five-line scope ledger into the parent chat of your next agent task before the run begins. If you want the full receipts-first operating model behind this piece, our training walks teams through it before the next style debate eats a sprint.
Related training topics
Related research

Cursor Composer layers in agentic coding
A field guide to Cursor Composer layers in agentic coding: decision stubs, scope ledgers, and precedence files that keep work reviewable.

AI coding tools that last past the demo
AI coding tools last when their output survives review: CLAUDE.md precedence, replay sandwiches, connector cards, and child receipts, applied in practice.

AI coding wrappers that hold up under review
A governance guide to AI coding wrappers: the repo contracts Cursor, Claude Code, and Codex need so agent work stays reviewable.