AI Coding in Practice: From Tool Literacy to Multi-Agent Engineering
A practical guide to getting real engineering results out of AI coding agents. It explains how CLI-based agents changed the game (a longer execution loop, not better code generation), why repository verifiability matters far more than model choice, and how to establish four baselines (install, build, test, diagnose) together with tiered permissions and sandboxing. It then covers reusable operating patterns (plan mode, controlled autonomous execution, permission configuration as code, Git workflows, context lifecycle management, multimodal input), how to turn project rule files into maintained engineering assets, and how to extend an agent with reusable skills, local hooks, protocol-based integrations, and a lead-agent/sub-agent topology. The article closes with a three-stage case study for delivering an internal tool from zero, a table of frequent mistakes, and a go-live checklist. The takeaway: efficiency gains come from a more verifiable repository and clearer collaboration rules, not from a stronger model.
1. First, Get the Positioning Right: What CLI-Based AI Coding Agents Actually Changed
1.1 Three leaps in tool form factor
Over the past three years, AI-assisted coding has gone through three form factors, each of which pushed the human’s unit of operation one level higher:
- Code completion: mostly line-level and function-level suggestions, with the human confirming chunk by chunk inside the editor. Clear payoff, but zero intrusion into the engineering workflow.
- Chat-based IDE: centered on a chat window. The AI can read and write the currently open files, but its field of view is basically limited to the editor and a few index results.
- CLI-based coding agent: the AI runs inside your terminal and therefore has repo-level vision by default. It can list directories, read multiple files, run tests, execute builds, read errors, change code, and rerun — closing the loop.
The essential change in the third stage is not “better code generation.” It is that the execution loop got longer. In the first two stages, the human was the only executor: the AI proposed, the human copied, ran, read the error, and asked again. In the CLI agent stage, that whole stretch of running, observing, and correcting can be handed to the agent itself, while the human retreats to a position of defining the task, reviewing the result, and owning responsibility.
1.2 What it really does for you is not “writing code”
A common misunderstanding is to treat these tools as “a smarter completion engine.” A description closer to reality: it is a general-purpose engineering assistant that can execute tasks inside your repository. The code it writes is only one of its outputs. The rest include:
- Locating problems: tracing from an error message back to the root-cause file.
- Generating scaffolding, migration scripts, and configuration files.
- Batch refactoring: renames, replacing deprecated APIs, unifying error handling.
- Adding tests, writing documentation, writing commit messages.
- Reading logs and metrics, forming hypotheses, and verifying them.
In other words, what it takes off your plate is the grunt work of “moving through the codebase and closing the loop.” That determines the core skill: not writing prompts, but breaking work into small verifiable tasks and making the repository itself capable of being verified automatically.
1.3 Context is the new scarce resource
Whatever model service you use, the available context window is a limited and expensive resource. What actually determines output quality is not how large the window is, but whether what’s inside it is valid information. Three typical ways context gets wasted:
- Noise: dumping the entire directory tree, huge log excerpts, and dependency source code unrelated to the task, all at once.
- Redundancy: the same information restated repeatedly in the conversation but never written down to a file.
- Staleness: the repository has already been refactored, the rule file still lists the old command, and the agent, following it, inevitably fails.
One practical principle follows: context is not chat history, it is working memory. Anything with long-term value — conventions, commands, acceptance criteria, diagnostic conclusions — should be externalized into files in the repository promptly, rather than left in the conversation waiting to be compacted away.
2. Environment Setup: Consume the Uncertainty Up Front
The success or failure of AI coding depends about eighty percent on the verifiability of the repository, not on the choice of model. The agent’s strength is fast generation; its weakness is that it does not know your project’s implicit conventions. So environment setup has exactly one goal: make correct behavior automatically checkable.
2.1 The baseline of four “ables”
| Baseline | Requirement | Consequence of a gap |
|---|---|---|
| Installable | One command installs dependencies, no interactive prompts | The agent gets stuck in the dependency stage, retrying repeatedly |
| Buildable | One command compiles/packages, with structured error output | Cannot distinguish syntax errors from logic errors |
| Testable | The suite can run in full, can run a single test, and has clear exit codes | The agent cannot verify itself and has to guess |
| Diagnosable | Lint / type check / formatting run with one command | Style and type problems keep getting carried into commits |
Once these four baselines are in place, the agent’s self-correction ability rises sharply: it runs the tests, sees a failure, reads the stack trace, changes the code, and reruns — that loop is itself the strongest quality guarantee. Conversely, if tests cannot run, the agent degenerates into “changing code by imagination,” and it will often quietly weaken your test assertions to make things go green. That behavior is the one to watch for.
2.2 Permissions and sandboxing: draw the boundary before granting power
Granting access does not mean “full open.” It means tiered access. Three tiers are a sensible design:
- Read-only / confirm by default: file writes and command execution require human confirmation.
- Auto-execute allowlist: read-only query commands, test commands, and formatting commands may run automatically.
- Explicitly forbidden: pushing to a remote, force-overwriting, deleting data, modifying CI configuration, running scripts that download from the network.
In engineering terms, at least three hard constraints must hold: no automatic pushing, no destructive operations, and no touching credentials. All secrets are injected via environment variables or a secret management service; plaintext never appears within the agent’s field of view.
2.3 Connecting to cloud-side infrastructure
The agent does the coding and verification locally, but delivery still lands on the cloud. Only generic product categories are needed here — no vendor lock-in required:
- Object storage: holding build artifacts, large files, and model weights.
- Container platform: providing a reproducible runtime consistent with local, avoiding “runs locally, fails in production.”
- CI/CD pipelines: moving the exact set of checks the agent ran locally (install, build, test, lint) over to the remote side as a second line of defense.
- Log service and monitoring/alerting: giving the agent a source of production facts so it diagnoses based on real metrics rather than guesswork.
For example, when a platform such as Baidu AI Cloud provides the container platform and log service as the delivery foundation, the local agent handles “generate + self-test” while the pipeline handles “re-verify + release,” and both sides should run the same set of checks so that no gate exists on only one side.
3. Core Working Modes: Five Reusable Operating Patterns
3.1 Plan mode: discuss the approach before touching anything
For tasks that cross files and modules, letting the agent start coding immediately is the most expensive option. The correct approach is to have it produce a plan first: which files are involved, in what order changes will be made, where the risks are, and how the result will be verified. You review the plan’s soundness and confirm before execution begins.
A decent plan should contain: task boundaries (what is in scope, what is not), impact surface (which callers are affected), verification method (which command to run, what result to expect), and a rollback path. The planning stage costs almost nothing in execution terms, yet it blocks most directional errors before any code is touched.
3.2 Controlled autonomous execution: let it run, but only inside the cage
Given complete baselines and tightened permissions, you can let the agent run the “change — run tests — correct” loop continuously, reducing human round trips. Three preconditions apply: tests exist, diffs are reviewed, and the work is on an isolated branch. Without any one of them, automation amplifies errors instead of converging them.
In practice, “small steps, many of them“ is the recommended approach: advance one verifiable goal at a time and commit as soon as it passes, instead of letting the agent finish a large feature in one shot.
3.3 Permission management: write the rules as configuration, not as reminders
Verbal constraints (“don’t touch the config files”) fail easily in long sessions. The reliable approach is to solidify the constraints:
- Path level: allow modifications under
src/andtests/; forbidinfra/andci/. - Command level: allow
test,lint,build; forbidpush,reset --hard, and package-publishing commands. - Behavior level: forbid modifying existing test assertions, forbid introducing undeclared dependencies, forbid writing plaintext credentials.
These constraints belong in version control, shared by the team, and treated in review exactly like code.
3.4 Version control: let the agent “understand Git,” but you decide when it lands
Agents are naturally suited to the mechanical parts of version control: inspecting changes, organizing commits, writing well-formed commit messages, generating branch descriptions. But distinguish “able to operate“ from “should operate automatically“:
- Commit: can be automatic, but must be small and focused — one commit, one thing.
- Push: must be triggered by a human, and only to feature branches.
- Merge, rebase, force push: forbidden by default, handled by a human.
There’s a simple test for whether a change set is healthy: can the commit message explain why the change was made? If the agent can only write “modified several files,” the task boundary was too wide and should be split and redone.
3.5 Context and lifecycle management
In long sessions, context is gradually polluted by history. Practical measures:
- One session per task: open a session for a task, close it when the task ends.
- Converge periodically: when the agent starts “forgetting” early conventions, the context has been compacted — restart the session and write the key conventions into the rule file.
- Externalize information: diagnostic conclusions, command lists, and known pitfalls all go into repository documentation.
- Avoid restating: don’t say “as mentioned earlier”; point at the file path directly.
A useful self-check signal: if you need to correct the same convention a third time, the problem is not the model but your context management.
3.6 Multimodal input: let the agent “see” the problem
Beyond text, the agent can obtain more sources of facts through general-purpose capabilities: screenshots and UI images (frontend layout problems, style misalignment), browser or desktop operation (reproducing a user path, verifying end-to-end flows), and voice input (quickly dictating a task, especially useful when describing something you’re looking at). The value of these entry points is reducing the cost of describing the problem — turning “there’s an error here, a red dialog box, the button is in the bottom-right corner” directly into locatable input is far faster than repeatedly typing and pasting logs.
Mind the boundary: operations on production systems, real user data, and write operations against external services should default to human execution, even when the tooling is capable of them.
4. Context Engineering: Treat Project Rule Files as Engineering Assets
4.1 Layered structure
Don’t pile the rules into one giant file. Three layers are recommended:
- Global: personal preferences that span projects (language, answer style, default command habits).
- Project: tech stack, directory responsibilities, core commands, coding conventions, forbidden actions.
- Module: supplementary rules placed in subdirectories, activated automatically when you enter that directory (for example, a frontend directory describing component conventions, a backend directory describing layering and error-code conventions).
The benefit of layering is loading on demand: when handling a frontend task, you don’t have to carry the full set of database migration conventions.
4.2 What to write, and what not to
Should write (information you cannot quickly infer from reading the code):
- One-shot commands:
install/build/test/lint/dev. - Directory responsibilities and where new code belongs.
- Hard conventions: naming style, error-handling approach, logging rules, commit rules.
- Acceptance criteria: what counts as “done” (tests pass + lint passes + docs updated).
- Forbidden actions: files that must not be changed, dependencies that must not be introduced, commands that must not be run automatically.
Should not write (information directly readable from code, dependency manifests, or commit history — or already out of date):
- Per-function explanations.
- Version numbers, transient state, descriptions of in-progress tasks.
- Long stretches of architectural theory.
Example rule file (illustrative):
# Project Rules## Commands- Install dependencies: `pnpm install`- Run tests: `pnpm test`- Single test: `pnpm test path/to/file.test.ts`- Type check: `pnpm typecheck`## Directory conventions- Business code: `src/modules/<domain>/`- API layer: `src/api/`, only parameter validation and protocol conversion- Tests: same directory as the file under test, named `*.test.ts`## Hard constraints- Wrap errors in `AppError`; never throw bare strings- No new third-party dependencies without review- No modifications to any file under `infra/` or `ci/`- No plaintext credentials in code or commits## Definition of done1. `pnpm typecheck` and `pnpm test` both pass in full2. New logic has test coverage for the main path and at least one error path3. The commit message explains the motivation, not the list of changes
4.3 Maintain the rule file like code
The typical failure mode for a rule file: commands changed, directories were reorganized, the tech stack was upgraded — but the file was not updated. Put it into the normal workflow: any change that affects build, test, or directory structure must update the rule file in the same commit. Make this a review checklist item and the accuracy of the rule file will hold up over time.
5. Extending Capability: From “Can Chat” to “Engineerable”
5.1 Packaging reusable skills
When a class of task recurs (for example, “add a CRUD endpoint following team conventions” or “generate a migration script and verify it”), it is worth solidifying into a reusable unit, typically with three parts:
- Description: applicable scenarios and input requirements.
- Steps: an executable checklist.
- Verification: the commands to run once it’s done.
The value of packaging is not just saving prompts. More importantly, it turns tacit experience into an explicit standard, so newcomers can obtain a consistent output.
5.2 Hooks: shift quality gates left to local
Hooks are scripts triggered automatically on specific events (after a file write, before a command runs, before a commit). A typical use:
#!/usr/bin/env bash# Pre-commit gate (illustrative)set -euo pipefailpnpm typecheckpnpm lint --max-warnings 0pnpm test -- --run# Block commits that appear to contain plaintext credentialsif git diff --cached | grep -nE '(api[_-]?key|secret|password)\s*=\s*["'"'"'][^"'"'"']{8,}'; thenecho "Possible plaintext credential detected; commit blocked" >&2exit 1fi
The point of hooks is to turn “remember to run the checks” into “impossible not to run them.” When the agent knows the checks are automatic and mandatory, it also tends to get things right the first time rather than relying on humans to fix things afterward.
5.3 Protocol-based integration with external systems
An agent’s capability boundary is determined by how many facts it can read. Using an industry-standard context access approach (an open standard such as the Model Context Protocol family), you can connect external systems: requirements and issue trackers (to get acceptance criteria), monitoring and logging (to get production facts), documentation and knowledge bases (to get design decisions), and internal platform APIs (to get environment information).
Two integration principles: read-only first and least privilege. Giving the agent a query-only read-only credential is far safer than handing it an all-powerful token.
5.4 Multi-agent collaboration: a lead agent orchestrates, sub-agents work in parallel
When a task can be split into mutually independent subtasks, a “lead agent + sub-agents” structure works well:
- The lead agent handles decomposition, assignment, aggregation, and final decisions.
- Sub-agents complete a single task in an isolated context: code review, test backfill, documentation generation, log analysis, dependency research.
There are two benefits: context isolation (a sub-agent’s exploration doesn’t pollute the main context) and parallel speedup (multiple subtasks advance at once). The cost is higher coordination overhead, so this only fits scenarios with clear task boundaries that can be verified independently. A typical combination: the lead agent changes code, one sub-agent reviews the diff and security implications, another backfills tests, and the lead agent finally runs the full gate set and aggregates results.
5.5 Cost and pace
Efficiency gains usually come with higher call volume. Control measures include: concentrating exploratory questions into a few sessions, preferring file paths over pasting large blocks of content, using a cache-friendly stable prefix to reduce repeated input, and solidifying high-frequency tasks into scripts instead of repeated conversation.
6. Conversation Strategy, Common Mistakes, and a Mental Model
6.1 Three strategies for effective conversation
- One task, one acceptance criterion. Don’t ask for a refactor and a new feature in the same round; give a decidable completion condition (which command passes, which behavior matches expectations).
- Evidence first, conclusions second. Have it read the relevant files and reproduce the issue once before changing code. Asking it to explain the root cause before offering a patch noticeably reduces band-aid fixes.
- State the prohibitions explicitly. Instead of “be careful,” say “don’t touch
infra/, don’t modify existing test assertions, don’t add dependencies.”
6.2 A checklist of frequent mistakes
| Mistake | How it shows up | Fix |
|---|---|---|
| Treating context as chat history | Key conventions stated once, then compacted and forgotten | Move them into the rule file |
| Rule file written as a catch-all | Hundreds of lines of generalities, very low hit rate | Write only what cannot be inferred from code, split by layer |
| Granting access without a baseline | Tests don’t run, so the agent changes code by guessing | Complete the four baselines first: install, build, test, diagnose |
| One giant refactor | A change of thousands of lines, impossible to review or roll back | Split into small verifiable commits |
| Blindly accepting the diff | Adopting changes without reading them | Review diffs one by one, focusing on tests and configuration files |
| Using the agent to “turn tests green” | Assertions weakened so tests pass | Explicitly forbid changing existing assertions; a failure must be fixed at the root |
| Credentials entering context | Pasting logs or config files containing plaintext secrets | Route everything through environment variables or secret management; never paste credentials |
| Ignoring permission tightening | Auto-execution and auto-push left on long term | Grant access in tiers; push and destructive operations require a human |
6.3 A more useful mental model
Treat the agent as a highly capable new colleague who knows nothing about your project’s conventions: it reads fast, writes fast, doesn’t mind repetitive work, but it doesn’t know your directory conventions, doesn’t understand your implicit norms, and won’t be held accountable for a production incident. How would you onboard such a person? Clear onboarding docs, explicit task boundaries, mandatory review steps, and self-checkable acceptance criteria — those actions are exactly the best practices for working with an AI coding agent. Your level of management determines the ceiling of its output.
7. Case Study: Delivering an Internal Tool from Zero to One in Three Stages
Take “delivering an internal data dashboard service” as an example of stage-based progress.
Stage one: establish a minimal verifiable loop (one session)
The goal is not features but being able to self-verify. Have the agent complete scaffolding initialization, a health-check endpoint, and one end-to-end test, and confirm that all four commands — install, build, test, lint — work. Produce the first version of the rule file at the same time. The value of this stage: every subsequent iteration is built on a trustworthy baseline.
Stage two: iterate in feature slices (multiple short sessions)
Split requirements into mutually independent slices: data ingestion → aggregate queries → frontend rendering → access control → caching. Give each slice its own session, follow the fixed loop of “plan — execute — test — commit,” and give each slice a feature branch, a sequence of commits, and a review. Update the rule file in sync as directories change. If a slice involves parallel subtasks (for example, backfilling tests and writing API documentation at the same time), bring in sub-agents.
Stage three: gates, observability, and documentation
Enable pre-commit hooks (type check, lint, test, credential scanning) and reuse the same check set in the pipeline; connect logging and monitoring, and configure alerts on key metrics; write the typical problems you diagnosed into project documentation; and package recurring tasks into reusable skills.
After all three stages, what the repository holds is not “a piece of AI-generated code” but an engineering asset that others can take over, that can be verified automatically, and that can keep evolving.
8. Go-Live Checklist
- The four baselines work: install, build, test, diagnose.
- Permissions are clearly tiered; push and destructive operations are forbidden by default.
- The rule file is layered and contains only information that cannot be inferred from code.
- Pre-commit hooks and pipeline gates check the same items.
- Credentials are injected uniformly via environment variables or secret management.
- Task granularity satisfies “one session, one verifiable goal.”
- Key diagnostic conclusions and conventions have been externalized into repository documentation.
- High-frequency tasks are packaged as reusable skills or scripts.
- Sub-agents are enabled only when parallel exploration is genuinely needed, avoiding unnecessary coordination cost.
The efficiency dividend of AI coding never comes from a “stronger model.” It comes from a more verifiable repository and clearer collaboration rules. Tools will keep changing and form factors will keep iterating; get these two things right, and you can pick up the capability of whatever comes next, quickly.
