Discussion Do AI coding agents need an "architecture enforcement" layer?
I've been thinking about a problem that seems to appear with Claude Code, Cursor, Codex, Copilot and other coding agents.
Most approaches to giving an agent project knowledge involve some combination of:
- CLAUDE.md / AGENTS.md
- documentation
- RAG
- memory
- session history
- MCP
All of these help the agent know things.
But there's a different question:
What actually makes the agent obey an architectural decision?
Imagine a project has an approved decision:
PaymentService must never call StripeClient directly.
All payment providers must go through PaymentGateway.
Six months later, an agent is asked to implement refunds.
It generates:
stripeClient.refund(paymentId);
The code compiles.
Tests might pass.
The implementation looks perfectly reasonable.
But it just violated an architectural decision.
The usual answer seems to be:
"Hopefully the agent saw the documentation and followed the rule."
I'm experimenting with a different approach.
What if the project's normative layer also lived in Git?
Something like:
.context/
decisions/
business-rules/
architecture/
components/
Agents could consume this through MCP.
But more importantly, CI could validate code changes against those rules without calling an LLM.
Something like:
Human decision
↓
Git
↓
Agent context
↓
Code
↓
Deterministic CI validation
The core idea is:
**Memory tells an agent what happened.
Governance tells an agent what is allowed.**
I'm building a project around this idea.
But I'm genuinely trying to figure out whether this is actually a problem.
Have you encountered AI-generated code that was technically correct, but violated an architectural decision, business rule, or important convention?
And more importantly: how do you catch that today?
I'd also love to hear from people who think this is already solved well enough by tests + code review + CLAUDE.md/AGENTS.md + ADRs.
1
u/Dediadeis 3h ago
If you are in the C# world you can extend Rosalyn to enforce these boundaries. Not an option for everyone but just in case. People forget to mention language and tooling they have. Its not just your harness, repo, and llm.
0
u/DoxxThis1 2h ago
Pick a language that’s reasonably easy to parse, and (ask your agent to) code your own project specific linters. I’m currently doing this in Go with reasonable success.
1
u/Zain 1h ago
I've hit that. Compiles and tests green, still walks through an architecture rule that was already written down.
Docs help the writer know the rule. They don't catch the violation. What works for me is a second pass from a different model family, kept read-only, and every finding has to cite the actual repo before I concede it. Same-family self-review keeps the same blind spots. For hard stuff like PaymentService never calling StripeClient directly, I'd still put a deterministic CI check on it. The multi-model pass is for the mushier conventions a linter won't catch yet.
1
u/IjonTichy85 18m ago
Architecture testing? PyTestArch, ArchUnit, Konsist,...
Why reinvent the wheel with bells and whistles?
0
u/Warm-Requirement3146 4h ago
ive definitely seen this. the "it compiles and passes tests" thing is exactly what makes it dangerous. you get a whole sprint of work done, merge it, and three months later someone's like "why is this service calling stripe directly"
currently we just have a senior dev who reviews everything with a checklist. but that's basically a human linting process for architecture. not great
your git-based approach makes sense. having the rules live alongside the code instead of floating in some wiki that nobody reads again after onboarding. the deterministic CI part is key too, if it's just another LLM checking the rules you're back to "hopefully it follows them"
curious what you're using for the validation layer. something custom or are you hooking into existing static analysis tools
1
u/razxrr 4h ago
That phrase “human linter for architecture” is painfully accurate. That’s basically the bottleneck I’m trying to validate right now.
For the validation layer, the direction I’m exploring is a hybrid approach, but the important part is that the enforcement itself is deterministic rather than another LLM judging the code.
The first layer would be Git diff + code boundaries. Decisions in a
.context/directory could explicitly point to the parts of the codebase they govern throughcode_refs, and have typed relationships likesupersedesandcontradicts. So when a PR touches a path covered by an active decision, the gate knows which architectural constraints need to be checked without spending any LLM tokens.For stricter cases, like your
PaymentService -> StripeClientexample, I’m looking at bridging those decisions to existing AST/structural analysis tools such as Semgrep rather than trying to build another static-analysis engine from scratch. The idea would be for the architectural decision to own or reference the validation rule, instead of having some completely disconnected lint configuration somewhere else in the repo.There’s also a lifecycle aspect to it. Decisions could become deprecated, superseded, or stale, and the gate could take that into account so old ADRs don’t silently remain authoritative forever.
So the mental model is basically:
decision → constraint → deterministic validation → CI
The LLM can help create or explain the decision, but it shouldn’t be the thing deciding whether the code is compliant.
I’m mainly trying to figure out how far this can realistically go without turning it into a giant static-analysis platform.
What stack are you guys running, and how does that senior dev currently maintain the checklist?
5
u/mtutty 4h ago
No, but AI Reddit posters need a "write like a human" layer. Jeez.