Skip to content
About

Working Effectively

The same tool produces a genuine speedup for one developer and a stream of subtle bugs for another. The difference is method. Here is the method.

An AI coding tool only knows what’s in its context: the code it can see, what you told it, what it retrieved. Most bad output is missing context, not a weak model. Feed it deliberately:

  • The relevant files — the code to change and the code it interacts with.
  • The conventions — the patterns, libraries, and style this codebase uses. Many tools read a project file (e.g. an AGENTS.md / rules file) for exactly this — invest in one.
  • The real goal — not just “fix this” but what correct behavior is and why.
  • Constraints — “don’t add dependencies,” “match the existing error handling,” “this path is performance-critical.”
Weak: Add caching to this function.
Strong: Add caching to get_user_profile(). Use the existing Redis client
in lib/cache.py — follow the pattern in get_org_settings(). Key by
user_id, 5-minute TTL, and invalidate it in update_user_profile().

The strong version names the files, the pattern to copy, and the constraints. That’s the job.

  • Be specific about done — inputs, outputs, edge cases, error behavior.
  • Point at an example — “follow the pattern in X” beats describing the pattern in prose.
  • Work in small steps — one coherent change at a time. Small diffs are reviewable; thousand-line diffs are not.
  • Iterate — treat the first output as a draft. Give specific feedback and refine rather than starting over.

The tool produces plausible code. Plausible is not correct. You are accountable for every line you commit, whoever — or whatever — wrote it.

  • Read every line. If you don’t understand it, don’t commit it. “The AI wrote it” is not a code review.
  • Run it. Compile, execute, exercise the real paths.
  • Test it — including the edge cases the tool likely ignored.
  • Watch for the classic failure modes below.
Failure modeWhat it looks like
Hallucinated APIsCalls to methods or libraries that don’t exist
Outdated patternsDeprecated APIs from older code in training data
Plausible-but-wrong logicLooks right, subtly mishandles an edge case
Missing edge casesNo handling for null, empty, error, concurrency
Security gapsUnsanitized input, injection, secrets in code
Convention driftIgnores your patterns; reinvents existing utilities
Confident wrongnessA clear explanation for incorrect code

Plays to its strengths:

  • Boilerplate, scaffolding, config.
  • Tests for existing code.
  • Explaining unfamiliar code or errors.
  • Routine, well-trodden tasks in mainstream languages.
  • First drafts you will rewrite anyway.
  • Repetitive refactors and mechanical translation.

Be cautious — verify hard or do it yourself:

  • Core architecture and design decisions.
  • Security-critical code.
  • Subtle concurrency, performance, or numerical work.
  • Novel problems with little prior art (and little training data).
  • Anywhere a subtle bug is expensive.
  • Niche languages, frameworks, or fast-moving APIs.

A real risk: outsource so much thinking that your own judgment atrophies — and judgment is exactly what’s needed to review AI output. Stay deliberate. Keep designing systems yourself. Understand the code you ship. Use these tools to skip the tedious parts, not the parts that build expertise.

Context is the master skill — supply the relevant files, conventions, goal, and constraints; most bad output is missing context. Prompt specifically, in small reviewable steps. Verify relentlessly: read every line, run it, test the edges, and know you are accountable for all of it. Never let generation outpace your review. Lean on AI for boilerplate and drafts; stay hands-on for architecture, security, and novel work — and keep your own skills sharp.