I use LLM coding agents on almost all of my projects. Working mainly in Rust on distributed, multi-workspace systems, I rely on them heavily to move fast.

When a project is brand new or small, coding agents feel like magic. Give them a prompt, and they write clean functions in seconds.

However, as soon as I use them on an already-existing, mature Rust workspace—spanning multiple crates, established patterns, strict security boundaries, and asynchronous flows—the magic starts breaking down. Regularly, the agents produce subtle bugs, unwanted stylistic tweaks, or dangerous simplifications.

The most frustrating part isn't syntax errors; Rust's compiler catches those. The real problem is coherence and architectural drift. When hit with a borrow-checker error or a complex trait bound in an existing codebase, the agent takes the shortest path to a green compilation:

  • It changes a carefully scoped pub(crate) struct field to pub.
  • It bypasses a validated smart constructor and parses raw serde_json::Value.
  • It invents a brand-new local helper struct instead of reusing the canonical one from a sibling crate.
  • Worst of all, if an existing test fails because of its shortcut, it sometimes weakens the test assertion just to make the suite pass.

The agent isn't malicious. It is just trying to fulfill my immediate request without understanding the intent, history, and structure of the existing codebase.

Attempt #1: Writing "Human" Documentation (Spoiler: It Didn't Work)

My first instinct was to fix this the way we onboard human engineers onto an existing project: better documentation.

I asked the LLM to generate comprehensive documentation for the repository—descriptions of the modules, high-level sequence diagrams, explanations of the key business rules, and READMEs in every folder.

It didn't help at all. The number of bugs, awkward tweaks, and bypassed boundaries stayed roughly the same.

Looking back, the reason is obvious:

  1. Humans read for onboarding; agents read under task pressure. A human reads a module description once to build a mental model. An agent has a limited attention budget and is trying to edit line 142 of verifier.rs right now.
  2. Prose descriptions restate what the code already says. Telling an LLM "this module handles billing" is just noise in its context window—it can see that in one grep call.
  3. Human docs focus on what the system does, not what is forbidden. Humans infer boundaries socially or through code review. LLMs optimize purely for local completion unless explicitly constrained.

Attempt #2: Asking the Models How They Want to Be Documented

Instead of guessing, I flipped the question. I went to multiple frontier models—OpenAI, Claude, and Gemini—and asked them directly:

"If you have to modify an existing, complex, multi-workspace Rust codebase without breaking its architecture, introducing bugs, or simplifying logic, how should I structure the documentation for you?"

I also threw in a few architectural ideas I wanted to explore:

  • Structuring operational context like on-demand Skills.
  • Organizing project knowledge using a Medallion Architecture (Bronze $\rightarrow$ Silver $\rightarrow$ Gold).
  • Using an Open Knowledge Format (OKF)—a promising structured Markdown + YAML frontmatter approach inspired by Google's work on domain knowledge representation.

I cross-pollinated the answers between Gemini, Claude, and OpenAI over several iterations. Each model pointed out blind spots in the others' designs:

  • One emphasized progressive context loading and a single CLI router so the agent doesn't blow its context window reading everything upfront.
  • Another pushed hard on single-source-of-truth frontmatter and code anchors (// INV-003) placed directly inside the .rs files where the agent's eyes actually look.
  • Another highlighted the gap between prose rules and Rust's type system—adding typestate anchors, "Golden Exemplars" (real files already in the repo to copy), and an explicit Anti-Simplification Covenant.

The Big Realization: Agent Docs Put Very Different Things at the Center

When we write documentation for humans, we put Architecture Views, Module Descriptions, and Happy-Path Flows at the center.

When the LLMs designed documentation for themselves to navigate an existing codebase reliably, they put completely different concepts at the center:

1. Invariants (and What is Explicitly Forbidden)

In human documentation, invariants are usually buried at the bottom of a wiki page, if they are written down at all. For an agent, Invariants (INV-*) are the center of gravity.

More importantly, an agent invariant isn't just a prose sentence like "Grants must be verified." It binds the rule to the compiler:

  • Which Rust type enforces this? (e.g., VerifiedGrant<T> with private fields).
  • What shortcuts are strictly forbidden? (e.g., "Never widen visibility to pub; never add #[derive(Deserialize)] to VerifiedGrant").
  • What regex pattern is illegal in non-test code?

2. Golden Exemplars Instead of Abstract Style Guides

If you tell an LLM in prose how you handle errors or write async handlers, it will still blend your instructions with generic training-data Rust (anyhow everywhere, .unwrap(), ad-hoc tokio::spawn).

Because this script runs on an already-existing repository, it searches the codebase for the cleanest existing implementations and creates Patterns (PAT-*) that point to a single Golden Exemplar file in your repo, paired with a 30-line idiomatic skeleton and a list of "Files Always Touched Together." LLMs are incredible few-shot pattern matchers—give them one concrete exemplar from your own codebase, and the weird stylistic tweaks disappear.

3. Test Contracts (Why You Must Not Touch This Test)

To a coding agent, a failing test often looks like an obstacle to edit around. By wrapping critical existing tests in Test Contracts (TC-*), the metadata tells the agent which invariant the test protects and enforces a baseline check so the agent cannot delete assertions or add #[ignore] to force a pass.

4. Hidden Couplings ("What Breaks at a Distance")

Code analysis tools can trace Rust imports, but they can't see that changing a port number in main.rs, renaming a serialized JSON field, or altering an environment variable will break an external script or another service in the workspace. Couplings (COUP-*) make those invisible wires explicit.

How the Medallion + OKF Pipeline Works in Practice

The resulting script analyzes an existing workspace and builds a meta/ directory using pure Bash and standard UNIX tools (find, grep, jq, yq, and SHA-256 content hashes—no Python scripts, and no Git dependency so it works even in exported archives or sandboxed environments):

Existing Sources (Rust crates, Cargo.toml, tests, schemas) │ ▼ Bronze (meta/_bronze/) --> Raw notes & legacy docs (hidden from agent grep via .ignore) │ ▼ Gold (meta/gold/**.md) --> Single Source of Truth: OKF Markdown + YAML Frontmatter │ (Invariants, Patterns, Contracts, Couplings, Rules, Flows) │ ./meta/bin/build ▼ Delivery Surfaces (Auto-loaded by the Coding Agent) ├─ Root AGENTS.md & GEMINI.md (Global protocol + Anti-Simplification Covenant) ├─ <crate>/AGENTS.md (Local constraints & fast cargo check commands) ├─ .agents/skills/<name>/SKILL.md (On-demand task context packs) ├─ // INV-001: ... (1-line anchors inside the .rs source files) └─ ./meta/bin/ctx impact <file.rs> (1-command deterministic context router) 

Before touching any file, the agent runs a single command:

./meta/bin/ctx impact crates/trust_gateway/src/grant.rs 

In less than a second, ctx outputs:

  • The Risk Tier (T1, T2, or T3) so the agent knows how much ceremony is required.
  • The exact Invariants (INV-*), Wire Contracts (CTR-*), and Hidden Couplings (COUP-*) anchored to that file.
  • Whether any documentation is STALE (checked automatically via SHA-256 content hashes of the anchored Rust files).
  • The Golden Exemplar (PAT-*) to copy so new code stays 100% coherent with existing code.
  • The exact scoped cargo check, cargo clippy, and cargo test commands to run before finishing.

And when the agent finishes, ./meta/bin/validate checks not just the Markdown formatting, but actual codebase conformance: verifying the Cargo dependency graph against forbidden dependencies, scanning source files for forbidden regex patterns, and checking that test assertion counts haven't dropped.

Important Scope Note: Existing Repositories vs. Greenfield Projects (And What's Next)

It is important to be clear about where this script applies today—and where it doesn't yet:

What it does today (Brownfield / Existing Repositories):
This methodology is built to run on an already-existing repository. It mines your current crates, types, tests, and structure so that future changes made by coding agents stay coherent, reliable, and faithful to the architecture you have already built.

What it does NOT do yet (Greenfield / Brand-New Repositories):
It does not yet apply to a newly created, empty repository where you want to instruct an agent up front on the patterns it must follow from day one, or inject the mandatory architectural/security standards required by your organization before any code exists.

The Next Step in This Approach:
Bridging that gap is my next goal—creating a "seed" or "organization-blueprint" mode for new repositories, where you can feed in your organization's mandatory Rust patterns, error-handling rules, security invariants, and crate topology before the first line of code is written, and have the enforcement harness grow alongside the project.

Does It Actually Help? (An Honest Take)

Since deploying this across my existing multi-workspace Rust projects, the jump in coherence and code quality has been genuinely noticeable. The agents respect crate boundaries, reuse existing domain types instead of inventing local tweaks, and stop taking destructive shortcuts when the compiler pushes back.

To be completely honest, I can't claim 100% of the credit goes to this methodology alone. Frontier models have also improved significantly over the past few months, so what I'm experiencing is almost certainly a combination of better models + better-structured context.

However, watching an agent run ./meta/bin/ctx impact, read a P0 invariant anchor, inspect the Golden Exemplar, and write code that fits seamlessly into a 10-crate workspace on the first try has convinced me of one thing: documentation for AI agents is a fundamentally different discipline than documentation for humans.

Try It Out — I'd Love Your Feedback!

I have open-sourced the complete, self-executing methodology script on GitHub:

🔗 Repository: fcn06/generic_rust_workspace_knowledge_generation_script

It is designed as a single self-contained Markdown file. You drop it into your existing workspace, point your coding agent at it (e.g., in Antigravity, Claude Code, Cursor, or Gemini CLI), and let it build the meta/ knowledge base phase by phase, pausing at Phase 3 so you can review the extracted invariants.

I am very much still learning and iterating on this, and I would love to hear from others tackling the same problem:

  1. How are you keeping coding agents coherent on your existing repositories? Are you using nested AGENTS.md files, custom skills, or something else?
  2. What else should be at the center of agent documentation? Are there artifacts beyond Invariants, Golden Exemplars, and Couplings that have worked well for you?
  3. How would you approach the "Greenfield / Organization Blueprint" next step? If you were bootstrapping a brand-new repo with mandatory company patterns for an agent, what would you include first?

Feel free to open an issue, submit a PR, or drop your thoughts in the comments below!