AI Agent Programming in Practice: Engineering Fully AI-Generated Code

    As AI coding agents take over implementation, engineering work shifts from writing code to reviewing it. This article breaks down how to make high-volume AI-generated code sustainable: writing executable plans and specs, sharding work across parallel sessions, running unattended nightly batch jobs, building layered automated quality gates, enforcing security governance, and adopting the model through a staged roadmap. It also covers the metrics that matter and the pitfalls to avoid. The core takeaway is that competitiveness comes not from how fast code is generated but from the combination of spec authoring, task sharding, automated verification, and risk governance.

    1. What Is Actually Changing: From Writing Code to Reviewing Code

    A research and development pattern worth watching has emerged in the industry: engineers almost never hand-write implementation code. Every change is generated by AI agents, while engineers handle only requirement decomposition, solution design, and output review. They ship dozens of change requests per day and routinely run multiple terminal and browser-based sessions in parallel to push tasks forward.

    Abstracting these observations one level up yields three conclusions:

    1. Coding is no longer the bottleneck. The model side is stable enough at generating code. The truly scarce resources have become “explaining the problem clearly” and “judging whether the result is correct.”
    2. The bottleneck has moved. It has shifted from typing speed to the quality of requirement definition, the ability to express specifications, review bandwidth, and the degree of acceptance automation. The optimization focus should therefore shift from “making the model write faster” to “making verification cheap.”
    3. Role boundaries are being redefined. Job titles like “software engineer” are expanding in meaning toward “builder” and “delivery orchestrator”: you need to break down tasks and write specs, and you also need to design automated pipelines, define quality gates, and manage risk.

    It is worth emphasizing that this does not mean engineers matter less. Quite the opposite: once the production stage is highly automated, the weight of engineering judgment is amplified. A single wrong architectural decision gets copied many times over into large volumes of generated code, and human review is the one backstop that cannot be replaced.

    2. Prerequisite: Plan First, and the Code Will Be Correct

    One repeatedly validated core principle is “if the plan is correct, the code will naturally be correct.” This is not rhetoric; it has a concrete engineering meaning: a model’s execution ability is stronger than its inference ability. Given a clear goal, it can usually complete the task; but if the goal is vague and constraints are missing, output quality drops sharply as the degrees of freedom increase. The primary source of errors is not “implementation ability” but “specification defects.”

    A high-quality task specification should therefore contain at least the following elements:

    • Goals and non-goals: clearly state what problem this change solves and explicitly what it excludes (to avoid scope creep).
    • Interface contracts: function signatures, input/output structures, error-code semantics, compatibility requirements.
    • Data and state: data structures, migration approach, idempotency and concurrency assumptions.
    • Boundaries and exceptions: handling strategies for nulls, timeouts, retries, rate limiting, and partial failures.
    • Observability: which logs, metrics, and alerts are needed, and how success can be observed externally.
    • Acceptance criteria: executable conditions for judgment, not “looks reasonable.”
    • Rollback plan: how to quickly return to the last known-good state.

    A ready-to-use plan template:

    1. ## Change Plan: <one-line title>
    2. ### 1. Background & Problem
    3. (Current state, scope of impact, consequences of not fixing it)
    4. ### 2. Goals / Non-Goals
    5. Goals: ...
    6. Non-goals: we are not doing this time ... (explicit exclusions)
    7. ### 3. Solution Highlights
    8. - Module boundaries: <which directories/packages may be modified, which are off-limits>
    9. - Interface contracts: <signatures and field definitions>
    10. - Data flow: <input -> processing -> output/persistence>
    11. ### 4. Error Handling & Boundaries
    12. - Invalid input: <behavior>
    13. - Dependency unavailable: <degrade or fail strategy>
    14. - Concurrency / repeated execution: <idempotency guarantee>
    15. ### 5. Acceptance Criteria (Executable)
    16. - [ ] New unit tests cover the main path and at least 3 exception branches
    17. - [ ] Full test suite passes, coverage no lower than baseline
    18. - [ ] Type checking and static analysis introduce zero new warnings
    19. - [ ] Change notes include a before/after behavior comparison and a performance impact assessment
    20. ### 6. Rollback & Risk
    21. - Rollback method: <feature flag / version revert / reverse data migration>
    22. - Main risks: <list them and describe mitigations>
    23. ### 7. Open Questions
    24. - <items requiring human decisions, to be confirmed during review>

    Key practice point: acceptance criteria must be machine-verifiable. Anything that can be covered by tests, type checking, static analysis, or contract validation should never be left to “someone eyeballs it”; only the parts that genuinely involve business trade-offs should consume human review bandwidth. This is what upgrades review from “reading code line by line” to “reading the plan and the evidence.”

    3. Parallelization: The Engineering Prerequisites for Multi-Session Work

    Running multiple terminal sessions or multiple browser-based sessions at the same time is fundamentally task sharding under context isolation: each session has its own independent context, its own working copy, and its own execution environment, with no cross-contamination. For this mode to work, three conditions are necessary:

    • Splittable: there is no cross-writing between tasks. If two tasks both need to modify the core structure of the same module, parallelism will only create conflicts.
    • Isolatable: each task has an independent branch, an independent working directory, and an independent build and test environment, avoiding shared state that contaminates other tasks.
    • Verifiable: each task can be verified independently, without depending on another task’s output to judge whether it is done.

    Recommended sharding dimensions, ordered from lowest to highest probability of conflict:

    1. Shard by test cases: fill in missing assertions for existing tests; this is naturally non-interfering.
    2. Shard by directory/module: one session owns one package and its tests.
    3. Shard by dependency layer: define interfaces and types first, then implement each implementation class in parallel.
    4. Shard by report items: fix security-scan findings, dependency alerts, and coding-standard issues one by one.

    You also need to define the upper limit on parallelism. Parallelism produces a “queue of changes to review,” and review and merge are inherently serial. If generation speed far exceeds review speed, the queue piles up, the probability of conflicts rises, and defect discovery is delayed — at which point system throughput is determined by the slowest link, and blindly adding more parallel sessions only raises rework cost. The sensible approach is to derive parallelism from review capacity and to insist on small, fast merges: keep an individual change within a few hundred lines where possible, so a reviewer can build full context within ten minutes.

    4. Asynchronous and Nightly Batch Processing: Letting Agents Handle Long-Running Tasks

    Building on the parallel mode, a step further is asynchronous autonomous operation: hand batches of tasks to agents to run unattended overnight, while developers monitor progress, spot-check outputs, and approve key checkpoints from mobile devices. Typical scenarios for this kind of workflow include bulk refactoring, dependency upgrades, test completion, syncing documentation and comments, initial triage of logs and alerts, and repetitive defect fixes.

    Technically, it is usually assembled from a few common mechanisms:

    • Scheduled triggers: recurring routine tasks (such as nightly inspection or a daily dependency report).
    • Loop/polling instructions: let the agent keep checking a certain state until a condition is met or a step limit is reached.
    • Event triggers: subsequent actions driven by signals such as code commits, review comments, or test failures.
    • Routine task list: maintain a long-term backlog, and take a few items by priority on each run.

    A sample scheduling script:

    1. #!/usr/bin/env bash
    2. set -euo pipefail
    3. RUN_DIR="/srv/agent-runs/$(date +%F-%H%M)"
    4. mkdir -p "$RUN_DIR"
    5. # Execute the task: plan -> implement -> self-verify -> write report
    6. agent-run --plan ./plans/upgrade-deps.md \
    7. --workspace ./repo-worktree \
    8. --max-steps 120 \
    9. --report "$RUN_DIR/report.json" \
    10. | tee "$RUN_DIR/run.log"
    11. # Hard gate: abort if local self-verification fails; do not enter the commit flow
    12. if ! make verify; then
    13. echo "Self-verification failed; task aborted, awaiting human intervention" | tee -a "$RUN_DIR/failed.flag"
    14. exit 1
    15. fi
    16. # Create the change only when everything passes; wait for human review
    17. create-change --branch "auto/$(basename "$RUN_DIR")" --draft

    Design points:

    • Idempotent: repeated execution of a task must not cause duplicate writes or data corruption; this is naturally well described using a “converge to the desired state” mindset.
    • Interruptible and resumable: long tasks must be able to save intermediate state, so that a single failure does not waste a whole night’s work.
    • Reproducible output: archive each task’s plan, execution log, diff, and report so they can be reviewed within ten minutes the next day. On a general-purpose cloud platform, these artifacts are well suited to being stored in object storage for long-term archival; task distribution can use a message queue, execution environments can be isolated with a container platform, and run traces can be observed uniformly through logging services and monitoring alerts.
    • Failures must flow back proactively: a failed task should not fail silently; it should notify a person through an alerting channel and be prioritized in the next day’s routine check.
    • Least-privilege credentials: credentials for unattended tasks must be short-lived and permission-restricted, and must never be written into logs, plan documents, or prompt content.

    5. Quality Gates: Layered Defense, Not Reliance on Manual Line-by-Line Review

    When almost all code is generated by agents, “having a person carefully read it once” is no longer scalable. The workable approach is to make quality assurance a multi-layer automated defense:

    • L1 Automated verification: type checking, static analysis, unit tests, integration tests, contract tests, reproducible builds. This layer must be fast enough to complete before commit.
    • L2 Structural constraints: directory and module boundaries, dependency-direction rules, automated architectural validation (for example, forbidding lower-level modules from depending upward on higher-level ones), and unified formatting. Architectural consistency is exactly what generated code most easily breaks.
    • L3 Change review: small-batch commits, structured change notes, checklist-based review, and mandatory human approval for sensitive areas — permissions and authentication, payment and billing, data migration, encryption-related logic, and deletion operations.
    • L4 Environment and release: pre-production environment verification, canary release, key-metric monitoring, and automatic rollback on anomalies.
    • L5 Post-incident closure: every production defect should be converted into a test case and a specification item, so the same class of problem is caught at the gate layer rather than relying on human memory at the review layer.

    A pipeline sketch:

    1. stages:
    2. - static: # formatting, types, static analysis, dependency audit
    3. - test: # unit + integration + contract tests
    4. - policy: # architectural rules, human-approval check for sensitive paths
    5. - publish: # build artifacts, canary, metric monitoring and automatic rollback

    6. Security Governance: Designing on the Assumption That Incidents Will Happen

    A recent class of publicly reported lessons is worth heeding for all teams: source-code leaks and accidental deletion of code repositories. What they exposed was not a model problem but that automation flows had been granted overly broad permissions. From this, a set of governance principles can be abstracted:

    • Least privilege: give analysis-type tasks read-only permissions only; write, publish, and delete operations require explicit approval. Keep everyday development accounts strictly separated from organization-level administrator permissions.
    • Deletion protection: enable branch protection, forbid force pushes, require mandatory reviews for critical branches; force a snapshot before deletion operations; establish regular immutable backups, and actually rehearse recovery, defining recovery time objectives and tolerable data-loss windows. A backup that has never been verified by a recovery drill is equivalent to no backup.
    • Secret hygiene: inject credentials through a controlled key-management facility; never put them into the version repository, command-line arguments, or logs and prompt content; rotate them regularly.
    • Complete audit trail: record “who, under what conditions, with what credentials, executed what,” covering agent sessions and command-execution traces, to meet after-the-fact traceability requirements.
    • Supply-chain control: new dependencies require approval, pin exact versions, and run continuous vulnerability scanning and license-compliance checks. Agents tend to pull in third-party libraries that “look appropriate,” and this is the main entry point for new risk.

    7. A Progressive Adoption Roadmap

    It is recommended to advance through four stages, each with clear promotion thresholds, rather than jumping straight to full automation in one leap:

    Stage Mode Human Role Promotion Threshold (example)
    1 Assisted completion, test generation Line-by-line review Build is stable, review defect rate is measurable
    2 Task-level delivery (ticket -> change) Solution design and change review Change failure rate below baseline, no high-severity escapes
    3 Multi-session parallelism Sharding design and conflict arbitration Merge conflicts under control, review does not back up
    4 Nightly asynchronous batch processing Spot-checking and approval of critical paths Complete automated gates, verified rollback chain

    8. Metrics and Common Pitfalls

    Meaningful metrics include: change delivery throughput, change failure rate, mean time to recovery, defect escape rate, review time, and rework count per task. Do not use “lines of generated code” to measure efficiency — it measures only output volume, not value.

    Pitfalls to watch for:

    • Treating agents as “free overtime,” ignoring that their output also needs review, and merely shifting cost from implementation to acceptance.
    • Under-investing in specifications, driving complex changes with a one-sentence requirement, and ending up with rework that far exceeds the time saved.
    • Neglecting context engineering: not maintaining clear architecture documents, interface contracts, and specifications, forcing the model to fill in the blanks by guessing.
    • Directly enabling auto-commit in a non-rollback-capable environment (production databases, the main branch of a shared repository).
    • Piling up technical debt with generated code: duplicate implementations, missing abstractions, comments inconsistent with the implementation, all of which erode maintainability over the long term.

    9. A Checklist for Individual Developers

    • Does each task have a plan document with executable acceptance criteria?
    • Are there shared-write conflicts between parallel sessions?
    • Is there a layered automated gate to replace manual line-by-line review?
    • Are credentials for unattended tasks short-lived and least-privilege?
    • Do critical branches have deletion protection and a backup verified by a recovery drill?
    • Has every production defect been converted into a test case or specification item?

    Conclusion: The competitiveness of agentic programming does not come from “how fast code is generated” but from the combination of four engineering capabilities: specification authoring, task sharding, automated verification, and risk governance. Getting the plan right, making verification cheap, and reducing permissions to the minimum is the fundamental prerequisite for making a high proportion of AI-generated code sustainable.