सामग्री पर जाएँ

How to get better code from AI agents: rules, hooks, and docs

How to get better code from AI agents: rules, hooks, and docs

Hello, I'm Luiz. I am a software engineer from São Paulo. I use coding agents every day, and I still do not treat them as smart colleagues. I treat them as interns with infinite stamina and a bad memory.

That is not an insult. It is the only mental model that produces good output.

An agent will not understand your system the way you do. It will pull files into a context window, mix them with patterns it memorized from other companies, and emit something that often compiles. Without guardrails, you get the same failures on a web app, an API, a data pipeline, or a mobile client: burned tokens, code that belongs to a different codebase, and the occasional vulnerability dressed as a helper.

This article is about three ideas: docs, rules, and hooks. They are not a product tutorial. They are how you stop asking the prompt to carry the entire engineering culture.

Searching and thinking are the same move


For a language model, “search the repo” and “think about the problem” are close cousins. Both are ways to stuff tokens into a window and predict what comes next.

When a product says the model is reasoning, it is usually prompting itself: restate the goal, list constraints, sketch a plan. That can reduce sloppy first drafts. It is still not judgment. The model does not know what a good change looks like in your organization unless that definition exists outside the chat.

So a prompt like “fix the slow endpoint” or “clean up this module” is an invitation to roam. The agent will open too many files, copy a popular tutorial, invent a helper that already exists, and skip tests because nobody made tests part of done.

Quality is not a feeling you add at the end. It is context you inject before the first edit, and checks you run after the last one.

What goes wrong without that system


Token waste. Vague goals make the agent wander. Every extra file is latency and money. A short map of the system (“writes go through the repository layer,” “jobs live in this package”) cuts a lot of that search.

Pattern drift. Agents prefer the last similar snippet they saw. That snippet may be from training data, not from your tree. You get a second ORM style, a third error type, a fourth way to publish events.

No taste for good versus bad. The model can write a tight function and a 400-line blob with the same confidence. Taste has to become a checklist: tests, lint, complexity limits, “reuse the existing client,” “do not add a table without a migration.”

Unsafe code. Hallucinated libraries, copied secrets, naive SQL, weak crypto, “temporary” debug endpoints. A sentence in the prompt will not catch that. Scanners and review gates will.

Mixed context. One thread that starts as a bugfix and ends as a rewrite will braid two problems into one diff. Scoped rules help. Starting a new session when the goal changes helps more.

None of this is a frontend problem. It is a context problem.

Three layers: map, standard, inspector


Treat the repository as a factory, on any stack.

  1. Docs (the map). What the system is. Bounded contexts, entrypoints, data stores, how work is supposed to flow.
  2. Rules (the standard). What a good change looks like. Always-on culture, plus conventions that apply only to a folder or language.
  3. Hooks and CI (the inspector). Processes that run when files change, when the agent stops, and when you merge. Text can be ignored. A failing check cannot, if you refuse to ship red.

The chat prompt is only the work order. If there is no map, no standard, and no inspector, the work order has to be a novel. That is how people burn tokens restating the company every morning.

If the three layers exist, a strong prompt is narrow: the goal, the decision that is unique to this task, and what is out of scope. “Done” already lives in the repo.

Docs for agents: a map, not a memoir


Humans like READMEs with history and screenshots. Agents need a map they can load every session without eating the wiki.

Write a small set of sources of truth. The names do not matter. The jobs do:

Kind of docJob
System mapBounded contexts, entrypoints, stores, queues, who owns writes
Runtime and toolingLanguage versions, package manager, how you run and migrate
Domain contractsAPIs, events, schemas, idempotency, auth boundaries
DeliveryHow a change is considered done (tests, review, release)

A payments service, a compiler, and a mobile app can share this shape. Only the nouns change.

Put in

  • Where new code of each kind belongs
  • The one blessed path for I/O (HTTP client, DB access, file storage)
  • Invariants in one paragraph each (“all writes are idempotent,” “jobs are retried,” “PII does not leave this service”)
  • Pointers to deeper specs, not copies of those specs

Leave out

  • Every function signature
  • Archaeology of old incidents unless they are still invariants
  • Secrets, private hosts, personal notes
  • Anything a linter or typechecker already enforces

Docs that try to be complete rot. Rotten docs are worse than none: the agent will follow the lie with high confidence.

A useful test: a fresh agent, given only the map and the rules, should put a new use case in the right layer and reuse the existing ports. If it opens a second database connection from a handler, the map is missing a sentence.

Rules: taste written as text


Rules are the sentences you are tired of pasting into every prompt.

Split them.

Always on when the cost of the mistake is global: keep diffs scoped, do not delete tests, do not commit generated output, define done as green gates, never weaken an assertion to go green.

Scoped when the convention is local: how this language formats errors, how this package talks to SQL, how this mobile module handles navigation, how this pipeline declares schema.

Each rule needs a name, a why, something concrete (command, path, forbidden pattern), and a definition of done.

Quality gating is a rule, not a speech. It says: match the check to the blast radius. A pure function does not need a full-system run. A migration does. A new public endpoint does. Deleting a failing test to “finish” is not allowed.

That is how the agent learns the difference between a patch and a mess. You are not asking it to have taste. You are giving it a spec.

Better prompts are a side effect

After rules exist, a good prompt gets shorter, not longer.

The bad prompt restates culture: be secure, follow our patterns, write tests, watch complexity, do not invent libraries…

The good prompt states the work: which invariant changed, which API, which rollback, what must not move.

Anything unique to the ticket still belongs in the prompt: the product decision, the incident, the schema change, the performance budget. Everything that is true for every ticket belongs in a rule.

Hooks: the standard has to execute


Rules are text. Agents skip text when they are in a hurry. Hooks are programs that run on events: after an edit, when the agent claims it is done, on commit, in CI.

A hook is usually boring:

  1. See which paths changed
  2. Ignore generated trees and dependencies
  3. Run the cheapest honest check for those paths
  4. Fail closed only when you mean it

Fail-open in the editor (report, keep going) avoids a retry storm and a token fire. Fail-closed in CI is where you actually protect main. If every keystroke is a hard stop, the agent loops. If nothing ever fails, red output becomes decoration.

Gate by blast radius

Do not run the universe after a comment change. Teach a menu:

Kind of changeHonest check
Pure logicunit tests for that module
Persistencetests that hit the query or the migration
Contract (API, event, proto)consumer or contract tests
Orchestration / UI flowa few end-to-end paths
Anything mergeablelint, types, secret scan

The menu lives in a rule. A short skill or checklist can make the agent report what ran, what was skipped, and what failed. You get compliance without a four-thousand-token sermon in the chat.

Complexity: the model does not feel cost


Agents do not feel Big-O. They will scan a full table in a loop, load a whole collection into memory, or call a service once per item because the first draft was easy to write.

You need two things: a sentence that forbids the pattern, and a check that can see it.

  • Algorithmic cost. Nested loops over unbounded input, repeated full scans, unbounded recursion. Say what “hot path” means in your system. Prefer a test or a benchmark over a lecture.
  • N+1 I/O. One query or RPC per element of a list, when a single batched call would do. This is the same idea in SQL, HTTP, and object storage.
  • Fan-out. Work that should be one transaction or one job becoming a chatty graph of side effects.

You do not need a research paper in the prompt. You need an invariant and something that fails when the invariant breaks.

Security is not “please be careful”


“Write secure code” does almost nothing.

Put inspection where merges happen:

  • Secrets. Scan for keys and .env files. Rotation is an ops process, not a personality trait you assign to the model.
  • Known bad shapes. Static analysis for injection, unsafe deserialization, SSRF, weak crypto, obvious auth gaps. OWASP is a catalog of those shapes, not a vibe.
  • Dependencies. Hallucinated package names are a supply-chain bug. A lockfile change should be deliberate and reviewed.

If the agent can add a library, the rule is: say why, pin it, and run the same scanners humans run. Vulnerable patterns in your code (string-built SQL, trusting client input, logging tokens) need the same treatment as a bad library.

Tests are executable taste


I still work red → green → refactor with agents.

  1. Write or extend a test that fails for the behavior you want
  2. Allow only the minimum change that makes it pass
  3. Clean up only while it stays green

Name the layers so the agent does not write a full-system test for a date parser:

  • Unit — deterministic logic
  • Integration — modules talking to a real or realistic collaborator (database, queue, filesystem)
  • Contract — producers and consumers still agree
  • Regression — the bug you just killed, pinned so the next chat cannot revive it
  • End to end — a few paths a real user or a real job would take
  • Coverage — a floor in CI, not a religion. A number without assertions is theater

A test is documentation the model can execute. That beats another paragraph of advice.

When output is still bad, fix the layer, not the novel


After the factory exists, a prompt looks like a ticket: goal, unique constraints, out of scope. Culture is already in the repo.

When the agent still ships the wrong thing, do not start by writing a longer prompt. Ask which layer failed:

  1. Map wrong or missing? The agent did not know where the work lives. Fix the doc.
  2. Standard unspoken? Humans knew, the model did not. Add a rule.
  3. Standard ignored? Text lost to speed. Add a hook, a linter, or a test.

That is how the system improves. The scratchpad does not have to grow forever.

A starter set, stack-agnostic


  1. One system map: contexts, entrypoints, stores, invariants.
  2. Always-on rules: scoped diffs, tests as done, no deleting failures, no generated junk in git.
  3. Scoped rules for each language or package that has a real convention.
  4. A hook that checks the files just touched.
  5. A stop menu that runs the smallest honest suite.
  6. CI that is fail-closed: lint, types, tests, secrets, static analysis.
  7. Complexity and I/O rules for the paths that actually cost money.

Then spend tokens on the problem, not on re-explaining the company.

Closing


AI is useful. It does not become a senior engineer because you called it one. It becomes useful when the repository explains itself, when taste is written as rules, and when hooks and CI refuse the first draft.

Build the map, the standard, and the inspector. The prompt can stay small. That is the whole trick.

Profile picture
Luiz Fernando - सीनियर सॉफ़्टवेयर इंजीनियर

पढ़ने के लिए धन्यवाद!

आशा है यह लेख आपको पसंद आया। सवाल या प्रतिक्रिया हो तो सोशल मीडिया पर लिखें। आपका दिन शुभ हो!

Carousel imageCarousel imageCarousel imageCarousel imageCarousel image
आगे / अच्छी चीज़ बातचीत से शुरू होती है

बड़े विचार।
Little Luiz.

कोई उत्पाद जीवित करना है? कोई टीम मज़बूत करनी है? देखें हम साथ क्या बना सकते हैं।

अपना रास्ता चुनें
01Freelance / Products

मेरे पास एक प्रोजेक्ट है

फ़्रीलांस सहयोग, उत्पाद और तकनीकी चुनौतियाँ।

  • उत्पाद खोज से डिलीवरी तक
  • वेब, मोबाइल और बैकएंड इंजीनियरिंग
  • स्पष्ट स्कोप। सीधा सहयोग।
कुछ साथ बनाएँ
02Hiring / Teams

मैं टीम बना रहा हूँ

इंजीनियरिंग भूमिकाएँ और लंबे अवसर।

  • सीनियर फ़ुल-स्टैक इंजीनियरिंग
  • उत्पाद सोच और तकनीकी स्वामित्व
  • वितरित टीमों का अनुभव
अपनी टीम में शामिल करें
03Résumé / Versions
रिज़्यूमे देखें

सामान्य इंजीनियरिंग, हेल्थ-टेक, फ़िनटेक और अधिक के लिए तैयार संस्करण।

  • छह केंद्रित रूप
  • प्रिंट-तैयार PDF
  • हर भूमिका के लिए अपडेट
मेरा रिज़्यूमे पढ़ें
luizepauloxd@gmail.com

ईमेल पसंद है? सीधे लिखें, या यहाँ ड्राफ़्ट शुरू करें।

बताएँ आपके मन में क्या है।

© 2026 Luiz Fernando इरादे से बना। और थोड़ी जिज्ञासा से।ऊपर जाएँ