Level 2 · Agents & Sub-Agents

Give the Agent a Task It Can Actually Finish

A coding agent works best when you give it a small, inspectable job with known inputs, real constraints, planned checkpoints, and an unambiguous finish line.

Start With A Finish Line

A coding agent is not just a chatbot that writes snippets. It can read files, edit them, run commands, inspect errors, and sometimes call outside services through tool connections such as MCP, which is a standard way to plug the agent into systems like GitHub, docs, databases, or logs. That extra power makes vague requests more dangerous. If you say, "clean up this app," the agent has to invent the problem, the scope, and the stopping point before it ever touches code.

The better move is to define the finish line first. Write one sentence that says what must be true when the task is done: "The settings page saves notification preferences, reloads them on refresh, and has tests covering success and API failure." That sentence gives the agent a target it can verify. Without it, the agent may keep polishing, refactoring, or chasing unrelated errors because nothing tells it when to stop.

This is the core habit: before asking for edits, turn your request into a small spec. A spec is not a formal document. It is a compact description of the job: inputs, constraints, checkpoints, and definition of done. You are not trying to impress the agent. You are removing choices it should not make alone.

Give Inputs Before Instructions

Once the finish line is clear, give the agent the material it should use. Inputs include file paths, error messages, screenshots, acceptance criteria, related tickets, commands to run, and anything you already know about the codebase. Agents operate inside a context window, which is the working memory of the current conversation plus whatever files or tool results they load. If the right context is missing, the agent fills gaps with guesses.

A useful prompt says where to look and where not to look. For example: "Work only in `src/settings` and `tests/settings`. Use the existing API client. Do not change the database schema. Run the settings test file, then the full frontend test command if the focused test passes." That is much stronger than "fix settings." It narrows the search space and prevents accidental architecture changes.

The tradeoff is that too much context can also hurt. Dumping five pages of background may bury the actual job. Give the agent enough to start, then ask it to inspect and report what it found before editing. A simple checkpoint works well: "First read the relevant files and summarize the implementation plan. Do not edit yet." This catches mistaken assumptions while the cost of being wrong is still low.

Constrain The Agent's Choices

After inputs, specify the boundaries. Constraints tell the agent which decisions are already made: style, architecture, libraries, performance requirements, security limits, and human validation zones. A human validation zone is any area where the agent may prepare a change but a person must review carefully before it ships, such as payments, authentication, data deletion, permissions, or migrations.

Good constraints are concrete. "Follow the existing React Query pattern in nearby files" is useful. "Make it clean" is not. "Do not add dependencies" is useful. "Keep it simple" is only useful if paired with a rule, such as "prefer a local helper over a new abstraction unless three call sites need it." If there are forbidden actions, say so explicitly: no schema changes, no public API changes, no edits outside a directory, no deleting tests to make a suite pass.

This is also where you decide what the agent may decide on its own. For a small UI bug, you might let it choose the implementation. For a cross-cutting refactor, you may require it to propose options first. The point is not to micromanage every line. The point is to reserve judgment calls for the human and delegate mechanical execution to the agent.

Use Sub-Agents For Parallel Clarity

When a task has independent parts, a single agent can get anchored on its first idea. Sub-agents are separate agent runs given narrower jobs. They can inspect different modules, review the same design from different angles, or produce competing implementation plans. For a first-time user, think of sub-agents as temporary specialists: one checks tests, one checks API behavior, one checks UX edge cases.

Use them only when the work can be split cleanly. "Launch sub-agents to inspect authentication, billing, and settings for shared preference-loading patterns" is a good use. "Launch sub-agents to build the whole feature together" is usually chaos unless the modules are isolated and the output contracts are clear. Each sub-agent needs its own mini-spec: scope, files, question to answer, output format, and stopping condition.

The failure mode is parallel rework. Three agents can spend tokens producing overlapping guesses. Avoid that by making their outputs decision-oriented: "Return file references, risks, and a recommended approach. Do not edit." Then merge the findings into one implementation spec before any code changes. Parallelism is useful when it improves clarity, not when it creates more cleanup.

Make Verification Part Of The Spec

A task the agent can finish must include how it proves the work is done. Verification can be a test command, lint command, build command, manual browser check, log inspection, or a second review pass. Agents can run tools, but they need to know which signals matter. "Run tests" is weaker than "Run `npm test -- settings`, then `npm run typecheck`; if either fails, fix failures caused by this change and report unrelated failures separately."

Add fallback rules for anything longer than a quick edit. Tell the agent what to do if tests are missing, a command fails for environment reasons, a generated asset is wrong, or the fix touches unexpected files. Set retry limits: "Try two fixes for the same failing test, then stop and explain the blocker." This prevents the common loop where an agent keeps changing code without improving confidence.

The finished prompt should read like a small work order: goal, inputs, constraints, checkpoints, verification, and definition of done. That may feel slower than typing a vague request, but it is faster than reviewing a wandering diff. The agent's power is execution. Your leverage comes from giving it a task shaped tightly enough that execution can actually end.

Key takeaways

  • Define done before the agent edits anything: what behavior must work, what files may change, and how success will be checked.
  • Give the agent focused context: relevant files, commands, errors, and constraints, not a vague request or a giant background dump.
  • Use checkpoints before edits for unfamiliar code, especially when the agent needs to inspect architecture or infer intent.
  • Reserve human judgment for subjective or high-risk areas such as security, payments, permissions, migrations, and product taste.
  • Use sub-agents for independent research or review, then merge their findings into one implementation spec before code changes.
  • Verification is part of the task, not an afterthought: include test commands, fallback rules, retry limits, and stopping conditions.