Week 3 · Lesson 3 of 10

Building with AI Agents - Planning, Context, Validation, and Version Control

0% Complete

Overview

AI-assisted development can follow two very different operating models. In one model, a long-running autonomous coding agent receives a large task and works without supervision. In the other, the human remains in the loop, collaborates on plans, observes implementation, validates behavior, and corrects the direction when necessary.

A RAG system benefits from the collaborative model because many of its important decisions are architectural rather than syntactic. The agent can produce code quickly, but it can also select an outdated API, create a hidden fallback, store credentials insecurely, overengineer a database interaction, or mark a feature complete without validating the critical path. Human supervision is needed to recognize when the code is technically plausible but operationally wrong.

The human does not need to type every line of code. The human needs a working mental model of the system. That includes understanding that the React front end and Python back end are separate processes, that database migrations change the schema, that row-level security is a database boundary, that an embedding dimension must match the stored vectors, and that a trace can reveal whether the model actually called a retrieval tool.

A useful development loop is:

  1. Plan.
  2. Build.
  3. Validate.
  4. Iterate.
  5. Commit.

Planning begins from a product requirements document. The requirements should define the broad stack, module boundaries, in-scope and out-of-scope behavior, and acceptance criteria. They do not need to specify every file or function. Leaving implementation detail open allows the coding agent to explore the codebase and propose a plan for each module.

Plan mode should be read-only. The agent examines the current structure, identifies dependencies, asks design questions, and writes a sequenced implementation plan. The plan should be saved in the repository rather than left only in a conversation. A durable plan gives future agents a record of what was intended and allows the human to review the design before code changes begin.

Before accepting a plan, inspect it for five things:

  • Does it cover the full feature, including back-end, front-end, migrations, and tests?
  • Are security controls located at the correct layer?
  • Can independent work run in parallel?
  • Is the plan small enough for one execution session?
  • Does the validation section prove the acceptance criteria rather than merely run a build command?

The build phase should execute the saved plan. Larger modules can use general-purpose subagents. For example, front-end work and back-end work can proceed in parallel if they have clear contracts. Parallelism is useful when tasks are independent. It is harmful when multiple agents edit the same files, restart the same services, or work from the same mutable checkout without coordination.

Separate branches, checkouts, or Git worktrees are the safer pattern for concurrent agents. Each agent receives an isolated copy of the repository. This prevents one agent's restart script or partial migration from invalidating another agent's test environment.

Context management is critical. Long coding sessions accumulate plans, code excerpts, tool outputs, failed attempts, and repeated explanations. As the context window fills, the agent may become less precise or start repeating mistakes. A status line that shows the active model and context usage makes this visible. A practical threshold is to consider a fresh session when roughly half of the available context is consumed, especially before beginning a large build or difficult bug investigation.

Clearing context is only safe when project memory is stored outside the conversation. A disciplined repository contains:

  • A lean global rules file such as CLAUDE.md.
  • A product requirements document.
  • A progress file.
  • A folder of saved implementation plans.
  • Reusable commands for onboarding, building, validating, starting, stopping, and restarting services.
  • A regression test definition and fixture data.

The global rules file should describe the stack, coding constraints, security expectations, planning conventions, migration instructions, validation requirements, and operational commands. It should remain concise because it may be loaded into every new session.

The progress file should identify what is not started, in progress, completed, or blocked. It should record the active plan, what has already been validated, the exact current failure, and the next action. When a session reaches a high context level, the agent updates this file before the session is cleared. A new agent can then read the repository and continue from a known state.

An onboarding command can automate that handoff. It can instruct a fresh agent to inspect the project tree, read the requirements, read the progress file, review recent plans, examine the Git log, and identify the next task. This avoids replaying a long conversation.

A build command can standardize execution. It can tell the agent to read the entire plan, perform tasks in order, run the listed tests, update progress, and report unresolved issues. Standard commands reduce the chance that a new agent skips validation or forgets the progress file.

Repeated operational prompts should become scripts. Starting the front end and back end manually created recurring confusion. Multiple background processes remained alive, so a restart appeared successful while the browser was still connected to an older server. A correct restart script should terminate all relevant processes and then start one front-end service and one back-end service. The repository should document the exact command that works in the actual shell environment.

Validation cannot be delegated entirely to the coding agent. The agent may say that all tasks are complete while avoiding a difficult browser test or asking the user to run the remaining commands. The operator should require the agent to perform as much validation as possible, then carry out independent manual checks.

For an early application-shell module, validation should include:

  • The login page loads.
  • A test user can sign in.
  • A thread can be created.
  • A message streams to the browser.
  • A second message can be entered after the first response.
  • A stop control cancels a stream.
  • Messages persist to the database.
  • Threads reload after refresh.
  • Dynamic thread titles are generated.
  • Observability traces appear.
  • The expected model API is used.

A tracing failure exposed an outdated Assistants-style API even though a Responses-style API was intended. The original requirement itself contained the outdated choice, so the mistake was not only the coding agent's. This illustrates why the human must review the requirements before execution. An agent can faithfully implement a bad specification.

Browser automation such as Playwright can test authentication and interface flows. Dedicated test credentials can be documented for automation, provided they are clearly test-only. Database checks should verify tables, rows, ownership, vectors, and deletion behavior. Direct queries can confirm whether an SQL tool returned the actual aggregate rather than a fallback result.

Version control is the recovery system for this workflow. Committing only at the end of a large module creates a large change set that is difficult to inspect or reverse. Smaller commits are safer. They can separate schema changes, back-end services, front-end components, tests, and bug fixes. When an agent goes down the wrong path, a focused commit makes rollback practical.

Environment files must be ignored. API keys, service-role credentials, database passwords, and model-provider secrets must not be committed. A remote repository containing private application code should be private. Tags and releases can mark completed phases and include release notes describing capabilities, migrations, and known limitations.

Practical development rules:

  • Save every major plan in the repository.
  • Start large builds with a fresh context.
  • Update progress before clearing a session.
  • Convert repeated prompts into scripts or commands.
  • Use subagents only for genuinely separable work.
  • Use isolated branches or worktrees for parallel agents.
  • Require explicit validation against acceptance criteria.
  • Inspect the database and traces, not only the browser.
  • Commit incrementally and tag stable phases.
  • Challenge designs that move security out of the database layer.

Back to top