AI Coding Agents in Practice: From Terminal Loops to Engineering Collaboration
This article explains how AI coding agents can move from early code-generation experiments to trustworthy engineering teammates. It covers validation-first development, terminal-based execution loops, context engineering, long-running task state management, failure classification, rollback strategies, permissions and safety controls, team collaboration, common pitfalls, and practical metrics for measuring reliability.
If we look back to the early stage when models first became capable of code generation, AI coding tools were relatively primitive: given a function signature, the model completed the implementation; given an error stack, the model explained the cause; given a test case, the model attempted a fix. At that stage, code capability was more of a language-level skill than an independently working agent.
The real turning point came when teams began placing models inside real software engineering environments. An agent could read project files, modify source code, run checks, and adjust based on execution results. Coding agents then moved beyond chat interfaces for code completion and gradually became execution units capable of participating in development tasks.
This article discusses, from an engineering practice perspective, how a coding agent inside a terminal can grow from an internal experiment into a reusable, governed, and extensible engineering agent. The focus is not proving how powerful a model is, but answering a more practical question: how to make AI coding agents trustworthy, controllable, and sustainably evolvable in real R&D workflows.
1. Start with Reliable Code Capability: Prioritize Validation Loops
Any coding agent should start by doing one small thing correctly, not by autonomously completing complex tasks. Early exploration often begins with basic code generation: ask the model to write a small function, then verify correctness with tests. This may look simple, but it involves several challenges: whether the code semantics are correct, whether boundary conditions are covered, whether it is testable, whether it follows repository conventions, and whether it can run stably.
At this stage, the key is not maximizing generation scale but establishing validation loops. Failed cases matter more than successful ones. Teams need to continuously collect error types and convert them into actionable correction strategies.
A practical failure classification table looks like this:
| Failure type | Typical symptom | Handling action |
|---|---|---|
| Type or variable errors | NameError, TypeError |
Add static checks and compilation validation |
| Missing boundary conditions | Empty lists, zero values, empty strings not handled | Add boundary test cases |
| Misunderstood dependencies | Import failures, version mismatches | Read dependency manifests and configuration notes |
| Repository convention mismatch | Lint or format checks fail | Inject team conventions and formatting tools |
| Unstable tests | Intermittent failures, environment-dependent results | Rerun to confirm, isolate external dependencies |
| Insufficient testability | Missing test entry points or difficult mocking | Add test skeletons before modifying code |
At this stage, the most important capability is not generating a complete solution in one shot, but knowing how to validate a change. The agent should not only propose edits; it must run tests, locate failures, read logs, and determine the source of the problem. In other words, the prototype of an agent should begin with greater verifiability, not greater freedom.
2. The Terminal Loop: Give Agents Observation and Action Abilities
The terminal is the most important early landing point for coding agents. Core facts of software engineering often live in the file system, command output, dependency relationships, build scripts, and test logs. Without an execution environment, a model can only infer from static text. Once connected to a terminal, it gains dynamic feedback and becomes a task executor rather than only a code suggestion provider.
The terminal loop can be abstracted as: read task context, locate relevant files and code fragments, make a modification plan, write or edit files, run build, test, or static checks, read execution results, determine success, failure, or rollback, and then continue correcting or submit the result.
The key is feedback. The first modification proposed by the model may be wrong, but it can discover errors through command output and enter the next correction round. To reduce blind retries, a terminal agent needs a minimal execution checklist.
Minimal Execution Checklist for Terminal Loops
- Read the task description, defect ticket, or user goal.
- Read the most recent failure log and summarize the key error.
- Locate relevant files and symbols, such as functions, classes, configuration items, or test names.
- Modify only the minimum necessary set of files.
- Run tests or static checks directly related to the task.
- Record commands, exit codes, key logs, and the list of modified files.
- Decide whether to continue modifying, roll back, or request human intervention.
The number of files modified in one pass should also have an upper limit. Small-scope defect fixes should generally not exceed three files; medium-sized tasks should not exceed ten files; batch tasks must be split into multiple subtasks and validated in batches. Otherwise, once a failure occurs, the cost of localization and rollback rises quickly.
Each action should record minimal log fields: task ID, timestamp, execution directory, command, exit code, key standard output, key error information, modified files, patch summary, and current step number. This ensures that agent behavior is traceable, reviewable, and auditable.
Below is a minimal example showing the complete command sequence from reading an error log to locating files, modifying a function, and running tests:
# 1. Read the task summarycat tasks/TASK-123.md# 2. Run the failing test and record the logpytest tests/checkout/test_total.py::TestCheckout::test_discount -q > .agent/logs/test_1.log# 3. Extract key errors from the logtail -n 50 .agent/logs/test_1.log# 4. Locate the target functionrg -n "def calculate_total" src/# 5. Locate related testsrg -n "test_discount" tests/# 6. Inspect the target code contextsed -n '40,90p' src/checkout/pricing.py# 7. Modify only one file using a patch toolapply_patch <<'PATCH'*** Begin Patch*** Update File: src/checkout/pricing.py@@- total = price + shipping+ total = price + shipping+ if discount is not None:+ total = max(total - discount, 0)*** End PatchPATCH# 8. Rerun the originally failing testpytest tests/checkout/test_total.py::TestCheckout::test_discount -q# 9. Run neighboring tests to avoid regressionspytest tests/checkout -q
The point of this example is not the specific commands, but how an agent closes the loop: read the task, locate the problem, make a small change, and validate with tests. Terminal tools also expose a key design challenge: models cannot have unlimited permissions. They may read project files, but must not arbitrarily delete critical directories; they may run tests, but must not trigger production commands by mistake; they may modify source code, but must accept permission policies and user confirmation. A terminal agent must quickly move from “what can it do?” to “how can it do things safely?”
3. From Snippet Tasks to Repository Understanding: Context Engineering Becomes Core
When an agent handles a single-point issue in a terminal, context can be relatively simple: one file, one error message, or one code fragment. Real R&D tasks often involve multiple modules, call relationships, test entry points, and long-standing engineering conventions. Fixing an apparently ordinary error may require understanding configuration loading, dependency injection, logging, exception handling, and unit tests at the same time. Insufficient context can lead to locally correct but globally wrong changes.
Therefore, AI coding agents must build repository-level understanding. Context engineering is not about stuffing more files into the model; it is about showing the right information at the right time.
Steps for Context Engineering
Build a code index. The index should at least include function and class definitions, reference relationships, call chains, test mappings, configuration files, and build scripts. Without an index, agents must rely on full-text search, which reduces efficiency and accuracy.
Extract task keywords. Agents need to extract keywords from task descriptions, error stacks, test failure messages, and user input, such as function names, file names, exception types, module names, test names, configuration items, and requirement terms.
Perform layered retrieval. Start with precise information, then expand to fuzzy context. For example, first find function definitions, then find callers; first inspect the failing test, then trace the configuration loading path; first locate the file containing the error, then read related modules.
Prune context. Long context requires summarization, layering, and compression. Files should not be read in full without differentiation; only fragments relevant to the task should be retained. Build configurations, test commands, directory conventions, and common errors should be available to the agent, but not all inserted at once.
Generate a context package. Before making changes, the agent should organize a task context package. It should at least include task goals, candidate files, key symbols, related tests, impact scope, risk points, and open questions.
A simplified context package example:
Task: Fix failing test_discountCandidate files: src/checkout/pricing.py, tests/checkout/test_total.pyKey symbols: calculate_total, discount, shippingRelated test: TestCheckout::test_discountLikely cause: Discount calculation does not account for negative valuesImpact area: Checkout price calculationRisk: May affect other pricing rulesOpen question: How to handle a negative discount value
Context quality determines agent stability. Too little context causes the agent to guess; too much context causes it to lose focus; outdated context causes it to act on wrong assumptions; missing conventions cause it to generate code with inconsistent style.
| Context issue | Symptom | Impact | Governance action |
|---|---|---|---|
| Insufficient context | Only one function is modified, callers are ignored | Locally correct, globally wrong | Add call chain, configuration, and test retrieval |
| Excessive context | Many irrelevant files are read | Attention is diluted, response slows down | Prune by task, summarize, and compress |
| Outdated context | Analysis is based on old branches or old logs | Changes are ineffective or conflicting | Lock commit version and refresh indexes |
| Missing conventions | Code style is inconsistent | Review cost increases | Inject lint rules, directory conventions, and team standards |
Context governance must be designed together with prompt strategies, tool return formats, file indexes, log summaries, and test feedback. A mature agent handles problems like an experienced engineer: inspect the structure first, then the details, and finally perform minimal validation.
4. From Single Edits to Long Tasks: State, Failure Classification, and Rollback
Early agents usually handle short tasks: write a function, fix an error, or add a test. As user trust increases, requirements become longer and more complex: refactor a module, migrate a set of configurations, batch-fix defects, or generate an implementation plan from a requirement ticket. Long tasks raise higher requirements and introduce new risks.
The first risk is state loss. Across multiple steps, the agent must remember goals, constraints, completed actions, and failure causes. Without state management, it may repeatedly modify the same place or drift from the original goal after multiple adjustments.
The second risk is context bloat. As steps increase, logs, diffs, and test results accumulate and may exceed the effective processing range.
The third risk is uncontrollable side effects. Long tasks may modify multiple files, run build scripts, or even call external services. Without permission tiers and rollback mechanisms, recovery can be costly after a wrong policy.
Therefore, long-task agents need task state machines, failure classification, retry limits, checkpoints, rollback scope assessment, and human intervention mechanisms.
Failure classification example:
| Failure category | Example | Automatic retry allowed? | Handling strategy |
|---|---|---|---|
| Compilation errors | Syntax errors, type errors | Limited retry allowed | Read compilation logs and fix syntax |
| Test assertion failures | Expected value does not match actual value | Limited retry allowed | Analyze assertion differences and locate logic issues |
| Missing dependencies | Import failures | Retry allowed but approval required | Read dependency manifests and confirm whether to add dependencies |
| Unstable tests | Occasional timeouts or random failures | Retry allowed for confirmation | Isolate and rerun; avoid blindly modifying code |
| Command timeout | Build or test takes too long | Parameter adjustment allowed | Narrow test scope or increase timeout |
| Policy block | Command hits a denylist | No automatic retry | Transfer to human approval |
| Destructive risk | Deletion, force push, production changes | No automatic retry | Stop and request human confirmation |
Retry limits should also be clear. For example: stop automatic retries if the same type of failure remains unresolved after three consecutive attempts; move to human review if total retries exceed five; never automatically retry destructive risks or policy-blocked operations.
Checkpoint storage can be placed in the task workspace, for example:
.agent/checkpoints/<task_id>/state.jsondiff.patchtest_summary.jsongit_commit_sha.txtenv_info.txt
Checkpoints should record the current step, task goal, modified files, most recent test result, failure category, retry count, and policy state. This allows recovery from the latest state even if the agent is interrupted.
Rollback scope should be limited to file changes produced by the current task. By default, roll back to the most recent checkpoint, revert modified files, and clean up temporary files generated by the task. If the task has already produced external side effects, such as committing code, sending requests, modifying databases, or triggering releases, automatic rollback must not be performed. Human confirmation is required.
Below is a more concrete pseudocode example for long tasks:
def run_agent_task(task):state = load_checkpoint(task.id) or init_state(task)while not state.is_finished():action = plan_next_action(task, state)result = execute(action, policy=state.policy)if result.kind == "success":state.commit_step(result.diff)elif result.kind in ["compile_error", "assertion_failed", "lint_failed"]:state.record_failure(result.kind, result.log_digest)if state.repeat_count(result.kind) >= 3:return rollback_or_review(state)elif result.kind in ["timeout", "network_error", "flaky_test"]:state.record_failure(result.kind, result.log_digest)if state.total_retry_count() >= 5:return request_human_review(state)elif result.kind in ["policy_blocked", "destructive_risk"]:return request_human_review(state)if state.step % 2 == 0 or result.kind in ["rollback", "policy_blocked"]:save_checkpoint(state,dir=".agent/checkpoints/%s" % task.id)return state
The core point of this pseudocode is not the implementation itself, but the essential elements of a long-task agent: planning, execution, failure classification, retry limits, checkpoints, rollback scope, and human intervention. Without these mechanisms, higher autonomy increases risk.
5. Permissions and Safety: Bringing Agents into Real Engineering Environments
When an agent moves from a personal experimental tool to a team environment, security design becomes unavoidable. Coding agents read business code, access configuration information, execute commands, and may even touch build artifacts. If permission boundaries are unclear, they may cause incorrect edits, introduce security vulnerabilities, or break the build environment.
Permission and security controls cannot remain at the principle level; they need executable rules.
Command Allowlist Example
Low-risk commands that may be executed automatically can include:
rg # Code searchfind # File lookupcat # Read text filessed -n # View file fragmentsgit status # View working tree statusgit diff # View changesgit log # View commit historypytest # Run Python testsgo test # Run Go testsnpm test # Run frontend testsruff # Python lintingmypy # Python type checkingeslint # JavaScript linting
Command Denylist Example
High-risk commands should be forbidden from automatic execution by default. They must require human confirmation or be completely disabled:
rm -rf /rm -rf .gitgit push --forcegit reset --hardsudochmod -R 777docker rm -vkubectl deletecurl | shwget | shmv /prod/*DROP DATABASE
Sensitive File Deny Rules
The following files should be denied by default unless they have been desensitized, approved, or are accessed only in an isolated environment:
.env.env.**.pem*.keyid_rsacredentials.json*.p12.npmrcCredential fields in .git/configSecret files in production configuration directories
If the agent only needs to determine whether a configuration exists, it may return only the file name and existence status, not the file content.
Approval Triggers
The agent should not execute automatically and should trigger human approval in the following situations:
- Batch changes exceed 10 files.
- Files are deleted or renamed.
- Dependencies are added or upgraded.
- CI/CD configuration, release scripts, or deployment configuration is modified.
- Database migration files are modified.
- External network requests are executed.
- Production configuration or credentials are accessed.
- Permission, authentication, or encryption-related code is modified.
- Changes are committed or merged into release branches or main branches.
Sandbox Environment Requirements
When running validation and builds, agents should preferably run in an isolated environment:
- Use containers, virtual machines, or temporary workspaces.
- Mount source code as read-only where possible; perform changes through patches or copied workspaces.
- Do not inject production credentials.
- Restrict network access to necessary dependency sources only.
- Limit CPU, memory, and execution time.
- Retain complete command logs and diff snapshots.
- Automatically clean up temporary environments after task completion.
A pre-operation checklist can help agents and engineers perform joint review:
| Check item | Question |
|---|---|
| Change scope | Are only necessary files modified? |
| Command risk | Does any command hit the denylist or perform destructive operations? |
| Dependency impact | Are dependencies added, upgraded, or deleted? |
| Test coverage | Are there corresponding test cases to validate the change? |
| Approval requirement | Is human confirmation needed? |
| Rollback plan | Can the system recover to the most recent checkpoint? |
The closer an agent gets to a real production environment, the more it needs infrastructure-style designs for permissions, logging, monitoring, and recovery.
6. From Personal Tool to Team Agent: Entering Engineering Collaboration
After terminal loops and permission mechanisms mature, AI coding agents begin entering a more complete software engineering process. They no longer wait only for a user to type a request. They can connect to task systems, code hosting platforms, continuous integration pipelines, and review processes. An agent can start from a defect ticket, read the issue description, locate related code, generate a fix draft, run tests, and submit the result as review material for engineers.
Typical changes at this stage include:
- Task entry points expand from chat windows to tickets, incidents, and code review comments.
- Execution environments expand from personal terminals to automated pipelines or isolated workspaces.
- Deliverables expand from code snippets to change notes, impact analysis, test records, and risk assessments.
- Human-machine collaboration shifts from users directing every step to users setting goals, agents executing, and humans approving.
Team adoption also requires shared context. Individual engineers’ memory cannot automatically become team knowledge, but specification documents, test cases, historical defects, code comments, and review feedback can be accumulated as searchable material for agents. The more the agent understands team conventions, the closer its output is to a mergeable state; the less team knowledge it has, the more likely it produces changes that look plausible but do not meet engineering standards.
Therefore, the growth of an agent product is not just a stronger model, but a more complete task environment. When models can access task background, code state, test feedback, permission policies, and team conventions, their behavior becomes closer to engineering collaboration rather than blind code generation.
7. Common Mistakes and Pitfalls to Avoid
When deploying AI coding agents, common mistakes often cause more practical loss than technical difficulties. These issues should be avoided early.
| Common issue | Symptom | Handling action |
|---|---|---|
| Insufficient context | Only local changes are made; callers and configuration are ignored | Add call chains, configuration, tests, and dependency relationships |
| Excessive context | The model reads many irrelevant files | Layer summaries, prune by task, and keep only necessary fragments |
| Outdated context | Changes are based on old branches or old logs | Lock commit versions and refresh indexes and test logs |
| Missing validation | The agent claims completion but does not run tests | Enforce compilation, testing, or static checks |
| Excessive permissions | The agent can read sensitive files or execute high-risk commands | Use allowlists, denylists, least privilege, and approvals |
| Accidental file deletion | The agent executes rm, reset, or batch overwrite operations |
Ban destructive commands and enable snapshots and rollback |
| Accidental production commands | The agent performs release, deletion, or deployment operations | Require human approval for all production operations and isolate them in sandboxes |
| Long-task state loss | The agent repeatedly modifies the same place or drifts from the goal | Use state machines, checkpoints, and task logs |
| Blind retries | The same error repeatedly appears | Set failure classification, retry limits, and human intervention |
| Uncontrollable external side effects | Database changes or API calls cannot be rolled back | Record side effects and prohibit automatic rollback of external operations |
| Dependency leakage risk | The agent reads secrets or tokens | Deny sensitive file access, desensitize data, and audit permissions |
The core of avoiding pitfalls is not making agents more aggressive, but making them more predictable. Agents can take over repetitive, mechanical, and verifiable work, but business goals, architectural choices, security risks, and external deliveries should still be confirmed by humans.
8. Outlook: From Coding Assistant to R&D Execution Layer
As model reasoning, tool calling, and execution environment standardization improve, AI coding agents will continue moving deeper into the R&D execution layer. Possible directions include: from single-file fixes to cross-module refactoring; from static code analysis to dynamic runtime validation; from manual triggering to event-driven execution; from personal assistance to team-level task distribution; and from code generation to composite tasks such as requirement understanding, test design, performance tuning, and pre-release checks.
To observe agent effectiveness, teams can establish metrics such as:
- Validation pass rate: the proportion of agent modifications that pass validation on the first attempt or after multiple attempts.
- Rollback rate: the proportion of tasks rolled back due to failure, risk, or quality issues.
- Human takeover rate: the proportion of tasks handed over to humans because the agent cannot continue.
- Mean time to fix: the average time from task start to validation pass.
- Retry distribution: the average retry count for different failure types.
- Approval trigger rate: the proportion of high-risk operations entering human approval.
These metrics should be treated as observation criteria, not absolute promises. The value of an agent system is not generating more complex code in one shot, but reliably completing tasks in real engineering and making the process explainable, reviewable, and governable.
Conclusion
The growth path of AI coding agents is essentially the transformation from language model capability to software engineering capability. It begins with simple code generation, matures through observation and action loops in the terminal, and becomes production-ready through context governance, permission control, long-task management, and team process integration.
For developers, understanding this path is more valuable than remembering a specific stage product. Future AI coding tools will not only help write code, but participate in defining tasks, executing validation, accumulating experience, and improving overall R&D efficiency. A truly mature coding agent is not the tool that dares to change code most aggressively, but the system that lets engineers confidently delegate repetitive work to it, while providing explainable results and controllable boundaries at critical moments.
