How Code Agents Close the Loop from Goal to Delivery
This article explains how a code agent turns a natural-language goal into a verified result. It covers task planning, isolated cloud workspaces, auditable tool calls, change review, rollback, and delivery with diffs, command logs, and reusable scripts.
1. Defining the Problem: Completion Tools vs. Task Agents
Code completion tools work at a local scope. Given some context, they predict a code fragment. A task-oriented code agent needs four capabilities.
The first is repository-level understanding. The agent must read directory structures, dependency declarations, build scripts, test entry points, and logs, not just the file currently open. The second is multi-step planning. A feature often touches interfaces, implementation, configuration, tests, and documentation, so it must be split into verifiable substeps. The third is tool use. Reading and writing files, running commands, installing dependencies, and executing tests are controlled actions, not text generation. The fourth is a result loop. Changing code does not complete a task. The agent must also reproduce the problem, check the result against expectations, produce a diff, keep a command trace, and package downloadable artifacts when needed.
Building a code agent is therefore a systems engineering problem. It combines a language model, a workspace, a tool runtime, and auditing and policy controls. It is not a single chat exchange.
2. Architecture: Planning, Execution, and Delivery Layers
A practical implementation usually has three layers.
The planning layer turns a user goal into a task graph. Inputs might be “fix a script error,” “add a page to an existing project,” or “process a spreadsheet in batch according to set rules.” The output is an ordered list of steps: locate the entry point, reproduce the failure, make a minimal change, run self-tests, and organize the deliverables. The plan should state explicit success criteria, such as “the command exits with code 0,” “the test suite passes,” or “the output file fields match the agreed schema.” Without success criteria, execution tends to stop at a result that only looks correct.
The execution layer runs in an isolated workspace. The workspace contains the code tree, a dependency cache, temporary files, and a command sandbox. Each step maps to one or more tool calls: reading files, applying patches, running scripts, and collecting logs. The execution layer must restrict permissions, including network access, file system scope, process duration, and resource limits. These limits prevent a single runaway command from affecting the host.
The delivery layer turns the process into reviewable artifacts. At minimum, it should include file-level diffs, commands with exit codes, summaries of key logs, and a final artifact list such as scripts, processed data, and build outputs. For developers, seeing what changed and what ran matters more than a single final answer.
The three layers connect through a state machine with five states: pending planning, executing, awaiting confirmation, verified, and failed with retry available. The state should be persistent. An interrupted run can then resume, and a person can add a constraint before the run continues.
3. Workspace and Environment: Making “It Runs” the Default
Running an agent on a local computer often creates friction with accounts, keys, dependency versions, terminal settings, and machine availability. Moving execution to a cloud workspace is not about changing the chat interface. It standardizes a reproducible environment.
A typical workspace should do the following. It imports the existing project once, for example by extracting an archive into an isolated directory. It uses a fixed base image with the language runtime, package manager, and common build tools. It installs project dependencies and caches them. It runs commands in non-interactive mode and terminates them on timeout. It writes artifacts and logs to disk so they can be packaged for download after the task ends.
For script fixes and error troubleshooting, the workspace matters because it enables reproduction. The script and the error message go into the same environment. The agent first reruns the original command to confirm the failure, then changes the code or dependencies, then runs the same command again. Without reproduction, a fix is only a guess.
When adding a feature to an existing project, the workspace must keep the original structure. The agent should first scan the project: entry files, route and module boundaries, test directories, and configuration files. Changes should stay local and avoid unrelated refactoring. If self-tests fail, the agent should roll back to the last passing checkpoint instead of stacking more patches on a broken base.
For batch processing of spreadsheets and data, the workspace works like a batch job. The agent writes a processing script, validates it on sample rows, runs it on the full dataset, and outputs the result files along with a reusable script. The success criteria for these tasks should include data checks, such as row counts, primary key uniqueness, and null ratios. “The script finished” is not enough.
4. Tool Design: Let the Model Act, and Keep Every Action Auditable
The core interface of a code agent is its set of tools, not its chat window. Common tool categories include the following.
File system tools list directories, read file segments, search for symbols, and apply unified diffs. Patches are preferred over overwriting whole files because they are easier to review and to resolve when conflicts occur.
Process tools run commands inside the workspace and capture standard output, standard error, and exit codes. Dangerous commands should be blocked by policy. Examples include unrestricted recursive deletion and changes to paths outside the workspace.
Retrieval tools search the repository by keyword or structure. They reduce context bloat by avoiding a full read of the codebase.
Verification tools run tests, static checks, and formatters. Verification should be an independent step, and its results should feed back into the planning layer. The planning layer then decides whether to continue, roll back, or request human confirmation.
Every tool call should produce an audit log that records who ran it, when, with which parameters, and with what result. The log supports troubleshooting and human-agent collaboration. Developers can review diffs and command records without rereading the full reasoning process.
Tool results fed back to the model need noise control. Full build logs can be very long, so the execution layer should extract the failing stack trace, the first error, and the relevant file snippets. The context window is a limited resource, so results should be summarized rather than pasted in full.
5. Planning and Looping: ReAct Is Not Enough, Checkpoints Are Needed
A simple think-act-observe loop tends to get stuck in local optima. A more reliable engineering approach adds checkpoints to the loop.
Write a plan first, then execute in small steps. After each verifiable subgoal, create a checkpoint, such as a workspace snapshot or a patch stack. On failure, roll back and update the plan. Do not retry the same command endlessly.
Make constraints explicit. Examples include “do not change major dependency versions,” “modify only the specified directories,” and “never commit secrets.” Enforce constraints at the tool layer. Writing them only into the prompt is not enough.
Define stop conditions. If the same type of failure repeats, or if the step count or time limit is exceeded, the agent should stop and deliver the current evidence. That evidence includes the commands attempted, a summary of the errors, and the open issues. A partial result with evidence is often more useful than a false claim of completion.
For changes that touch core business logic, the loop should include a human review gate. The agent shows the diff and waits for confirmation before it continues with testing or packaging. Agents speed up repetitive work, but people remain responsible for the outcome.
6. Change Representation: Diffs, Tests, and Artifacts
The quality of a delivery depends on how the changes are represented.
Code changes should be applicable patches that list additions and deletions by file. Each change should include an intent note that explains why it was made and which error or requirement it addresses. Keep formatting changes separate from logic changes.
Command records should be reproducible. Each record should include the working directory, the exact command, the non-sensitive environment variables, and the exit code. Developers should be able to rerun the commands locally or in another workspace.
Test results should be layered. Smoke tests confirm that the main path runs. Regression tests confirm that existing tests still pass. Task-specific assertions check the new feature or data rules. A solution that appears to run but has no tests should not be marked complete.
The artifact list should be explicit. It should include the modified project, standalone scripts, processed data files, and a short usage guide. For batch tasks, the reusable script is often the core deliverable, so the next run does not require a one-off tool written from scratch.
7. Security and Resources: Hard Constraints for Cloud Execution
When an agent runs in an executable environment, security is the first constraint. Apply least privilege. Mount only the task directory. Allow no outbound network access by default, or use an allowlist. Inject secrets through short-lived credentials, and never write them into the repository. Set resource quotas for CPU, memory, disk, and runtime duration. In multi-tenant settings, workspaces must be strongly isolated and destroyed or frozen when a task ends.
Treat prompt injection as a system risk too. Instruction files in a repository, fetched web content, and error messages pasted by users may contain text such as “ignore previous instructions.” Policies at the tool layer must not be overridable by conversation content.
8. Human-in-the-Loop: Lower the Barrier Without Lowering Review Standards
The high barrier to using code agents often comes from a fragmented workflow, not from weak models. Setting up environments, managing keys, configuring terminals, and waiting for machines all add friction. Linking the steps of describing a goal, uploading
