Building a Terminal AI Coding Agent Workflow from Scratch
This guide walks through how to set up a terminal-based AI coding agent as a production tool: choosing the right model access pattern, wiring in context files, tools, and reusable skills, running unattended jobs, and extending automation all the way to browser and mobile-device verification. You'll learn the perception-execution boundaries that cap an agent's usefulness, the three model integration modes and when to use each, the security and governance questions to answer before going live, and a phased rollout plan with metrics that actually matter.
0. Start With a Judgment: An Agent’s Ceiling Is Set by Its “Perceive-Act” Boundary
Before the step-by-step, here is the judgment that runs through this entire guide: how far an agent can automate depends on what it can “see” and what it can “touch.”
The model itself is just a reasoning core. It has no inherent knowledge of your repository layout, how your tests run, why your page renders blank, or why your real device crashes. What actually determines output quality is the set of perception and execution channels you build around it. These capabilities split cleanly into three layers:
| Layer | Capability | Common Implementation | What Happens Without It |
|---|---|---|---|
| Information | Retrieval, web scraping, reading docs | The model’s built-in retrieval, search engine / web-fetch tool services | Falls back to training data alone; can’t answer “latest” or “current version” questions; tends to fabricate APIs from memory |
| UI | Opening pages, clicking, filling forms, assertions, screenshots | Browser automation drivers based on the W3C WebDriver standard protocol | Can’t operate web systems without an open API; can’t do end-to-end verification |
| Device | Installing packages, launching apps, simulating input, reading logs | Mobile debugging channel (an industry-standard debugging bridge protocol) | Can’t verify real-device behavior; the mobile delivery chain breaks |
Only when all three layers stack up do you get a genuinely usable closed loop: retrieve the facts → change the code → verify in the UI → confirm on the device → persist the conclusion back into project context. Miss any one layer and the agent can only reach the “looks correct” level, while engineering delivery demands “verified as correct.”
Once you understand this layering, every install, integration, and extension step that follows has a clear purpose: they aren’t configuration items, they’re ways to fill a specific capability gap in one of these layers.
1. What a Terminal Coding Agent Is: Positioning and Boundaries
Traditional code completion works “at the editor’s cursor,” with a field of view limited to the current file plus a little context. A terminal coding agent (referred to below as “the agent”) works with a different unit: the entire workspace plus an executable shell. This difference produces three fundamental shifts:
- Field of view expands from file to repository: It can grep on its own, read dependency manifests, trace call chains, and inspect commit history, enabling structural changes that span multiple files.
- Feedback expands from static to dynamic: It can run builds, execute tests, read errors, and fix them, forming a “hypothesize—execute—observe—correct” loop.
- Interaction expands from completion to delegation: You describe intent and constraints and it plans the steps; you review results while it handles the repetitive work.
You also need a clear-eyed view of its boundaries. It excels at: well-scoped bug fixes, repetitive refactors, filling in test coverage, writing scripts and configuration, log and error analysis, generating docs and comments, and cross-module consistency changes. It is not suited for: designing features whose requirements aren’t yet thought through, unattended execution of high-risk operations involving money, permissions, or data deletion, and architectural decisions that demand a long-term maintenance commitment. Writing these boundaries into your team conventions is more valuable than assigning blame after the fact.
2. Pre-Deployment Prep: Runtime, Accounts, and Directory Conventions
2.1 Runtime Environment
Most terminal agents are delivered as JavaScript runtimes (installed via an official install script or a package manager). Three principles are worth following:
- Prefer a Unix-like environment (Linux, macOS, or a Linux-compatible layer/container on Windows). The reason: agents lean heavily on
grep,find,sed, pipes, and redirection, and cross-platform differences in path and permission semantics cause a lot of meaningless failures. - Use a dedicated user and working directory; don’t operate on production repositories directly as root. Give the agent its own workspace, and mount read-only reference repos separately from production repos.
- Pin the version and runtime, and record it in the team’s environment notes to avoid “it works on my machine” drift.
2.2 Accounts and Credentials
You need two kinds of credentials: an API key for the model service (kept in environment variables or a local credential file, never committed to the repo), and credentials for tool services (such as a code-hosting platform token, a browser session, or device debugging authorization). Inject all credentials via environment variables, and defend on three fronts simultaneously: .gitignore, log redaction, and CI secret management.
2.3 A Minimal Working Verification
After installation, don’t rush to wire it into real work. First confirm the pipeline with a minimal closed loop:
# Placeholder command name aic, representing your agent's CLI entry pointaic --versionaic doctor # Check runtime, configuration, and tool-service connectivityaic -p "List the build configuration files in the current directory and explain each one's purpose" --output-format json
If it reliably produces structured output, then the runtime, model channel, and workspace reading are all working. Only then move on.
3. The Core Step: Three Model Integration Modes
This is the step that turns an agent from a “demo” into a “production tool.” Terminal agents typically specify the model service URL, key, and model name through a set of environment variables, so any service exposing a standard chat/completions-style interface can be connected, including mainstream model services, self-hosted inference, and cloud-hosted inference. The difference isn’t “whether it can connect” but “how it connects.” Each of the three modes fits a different scenario.
3.1 Direct Mode: Lowest Cost, Fastest Results
Point the agent’s configuration directly at a single model service endpoint.
export AGENT_BASE_URL="https://<your-model-service-url>/v1"export AGENT_API_KEY="<your-key>"export AGENT_MODEL="<model-name>"export AGENT_MAX_TOKENS=8192
- Pros: No extra components, lowest latency, shortest troubleshooting path (a single hop).
- Cons: Switching models means editing environment variables; configuration drift when multiple terminals/projects coexist; usage and cost scattered across many places with no unified observability.
- Fits: Individual developers, prototype validation, and single projects that stay fixed on one model long-term.
3.2 Gateway Routing Mode: Split Traffic by Task Dimension
Insert a self-hosted gateway between the agent and the model service, and let the gateway pick the backend model based on task type, context length, and sensitivity.
# Illustrative routing policy; field names depend on your gateway implementationroutes:- name: long-context-review # Whole-repo reading, cross-file refactorsmatch: { task: "plan|refactor", min_context: 100000 }backend: provider_a/large_ctx- name: code-edit # Everyday code changesmatch: { task: "edit|test" }backend: provider_b/coder- name: batch-cheap # Bulk docs, comments, formattingmatch: { task: "doc|format", batch: true }backend: provider_c/small
- Pros: One config serves all terminals and CI; keys live only on the gateway side; call logs, token usage, and failure rates are observable in one place; model upgrades only touch routing, not the business side.
- Cons: One extra hop of latency; the gateway itself must guarantee availability and rate limiting, or it becomes a single point of failure.
- Fits: Multi-person teams, multiple repositories, and scaled scenarios that need cost and quality governed together.
3.3 Aggregation Proxy Mode: Unified Entry + Failover
An aggregation proxy adds another layer on top of the gateway: parallel multi-provider integration, health checks, automatic degradation, failure retries, result caching, and quota management.
Agent ──> Aggregation Proxy ──┬── Provider A (primary)├── Provider B (backup, auto-failover)└── Self-hosted inference (sensitive data / offline)│└── Unified telemetry: tokens / latency / failure reasons / cost attribution
- Pros: Highest availability (automatic switchover on single-point rate limiting or failure); sensitive tasks can be forced through a private deployment channel; cost accounting and capacity planning backed by real data.
- Cons: Highest operational complexity; you must handle protocol differences, streaming-response compatibility, and inconsistent context lengths.
- Fits: Organizations embedding the agent into a product pipeline or with hard availability requirements.
3.4 Selection Guidance
| Mode | Onboarding Cost | Operational Cost | Observability | Recommended Scenario |
|---|---|---|---|---|
| Direct | Very low | Very low | Weak | Individual, prototype, single project |
| Gateway routing | Medium | Medium | Strong | Unified team access, quality tiering |
| Aggregation proxy | Medium-high | High | Very strong | Production pipeline, multi-provider redundancy |
A pragmatic evolution path is: start with direct mode to get the loop working, upgrade to gateway routing once the team grows beyond three people, then add aggregation and failover when the agent enters the delivery pipeline. You don’t have to do it all at once, but externalize keys and endpoint configuration from day one to leave room to evolve.
If the team wants to reduce the operational burden of self-hosted inference, it can consider cloud-hosted model services (for example, the model service capabilities offered by Baidu AI Cloud), combined with general capabilities such as object storage, logging, and monitoring/alerting to keep records of calls and observe usage. For scenarios with strict data-compliance requirements, prefer a private deployment or a dedicated instance.
4. Turning the Agent Into a Workbench: Context, Tools, and Skills
Once the model is connected, the difference in output quality mostly comes from “how much it understands about your project” and “what it can call.” Three things handle these: context convention files, a tool integration protocol, and reusable skills.
4.1 Context Convention File: A Project-Level “Onboarding Handbook”
The conventional practice is to place a plain-text context file (commonly named something like AGENTS.md) in the project root; the agent reads it automatically on startup. It solves the waste of “having to re-explain the same thing every time.” A recommended structure:
# Project Context## Tech stack and versions- Language/runtime version, package manager, build tool## Common commands- Install deps / local run / single test / full test / static checks / format## Directory conventions- Responsibilities of each top-level directory; where new code goes; what is generated and shouldn't be edited## Code standards- Naming, error handling, logging, comments, commit message format## Verification requirements- Which commands must run after changes; the E2E verification entry URL and test accounts## Prohibited actions- Directories/files that must not be modified; commands that must not be run; dependencies that must not be introduced
Three tips for writing this file well: First, only write information that can’t be guessed; don’t restate general best practices, since the longer it is, the more likely it gets ignored. Second, commands must be real commands that can be copied and run directly; “run the tests” is useless, a complete command is what works. Third, manage it in layers: global conventions go in user-level config (personal preferences, general standards), project conventions live in the repo (evolve with code, shared by the team), subdirectories can hold local conventions (such as a special build method for a specific microservice), and temporary in-session constraints are stated directly in conversation. The closer the layer, the higher its priority.
4.2 Tool Integration Protocol: Letting the Agent “Touch” External Systems
A standardized tool integration protocol (commonly an open spec like the Model Context Protocol) exposes external capabilities to the agent in a unified way: a “tool service” declares which tools it has, plus each tool’s input schema and description, and the agent invokes them autonomously when needed. There are two main deployment shapes:
- Local process: A local subprocess started with the session, suited to tools that need access to local resources, such as the filesystem, shell, database clients, and browser drivers.
- Remote service: A separately deployed service endpoint, suited to queries against shared internal systems, ticketing, monitoring data, and knowledge-base retrieval.
Production-grade integration requires four things; missing any one exacts a price in real use:
- Least privilege: Only mount the tool services the current task needs; restrict file read/write to authorized directories; disable delete, push, and deploy tools by default.
- Allowlist and confirmation: Set tiered confirmation policies for write operations, network requests, and command execution; high-risk actions require a human to approve.
- Timeouts and retries: Every tool call needs a timeout ceiling, especially browser and device tools; otherwise a single stuck page can hang the whole session.
- Audit: Record “who called which tool with what parameters at what time, and whether it succeeded.” This is both a troubleshooting basis and a compliance requirement.
{"mcpServers": {"filesystem": {"command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/srv/work/repo"],"env": { "READ_ONLY_ROOTS": "/srv/reference" }},"browser": { "url": "http://127.0.0.1:8931", "timeoutMs": 30000, "tools": ["navigate","click","fill","screenshot","console_logs"] },"device": { "url": "http://127.0.0.1:8932", "timeoutMs": 60000, "tools": ["list_devices","install","launch","tap","logcat"] }}}
4.3 Reusable Skills: Turning Repeated Processes Into Assets
When a certain kind of task keeps recurring (pre-release checks, scaffolding a new module from the team template, generating API docs, diagnosing a class of production errors), don’t re-describe it every time. Package it as a “skill”: a directory holding a description file (when to use, prerequisites, steps, acceptance criteria), with scripts, templates, and reference samples attached when needed. The agent automatically loads the matching skill when it identifies the task.
The judgment rule: if the same intent appears three or more times in a week, it should become a skill. The payoff of a skill isn’t just saving prompt tokens; it’s turning “a senior colleague’s tacit experience” into an explicit asset that can be versioned, reviewed, and handed off.
5. High-Frequency Daily Operations and Effective Collaboration Habits
At the command level, there’s very little you actually need to memorize (using aic as the placeholder CLI entry point below):
aic # Enter an interactive sessionaic "fix issue #123" # Start with an initial taskaic --plan "refactor the user auth module" # Produce a plan first, don't touch code (plan mode)aic --resume # Resume the previous sessionaic --add-dir ../shared # Add an accessible directoryaic -p "Summarize the root-cause distribution of failed builds over the last 30 days" --output-format json > report.json
More important than commands are collaboration habits. These few can significantly change output quality:
- Plan before acting. For cross-file changes, have it output a step list and impact surface first, confirm, then execute. This step catches most directional rework.
- Enforce a verification loop. State clearly in the prompt “after the change, run this test command; if it fails, read the logs and keep fixing until it passes, then report” rather than letting it “make the change and tell me.”
- Commit in small steps and review diffs section by section. Keep one change within a single understandable semantic unit; before committing, read the diff yourself, focusing on whether it quietly changed unrelated code or added unnecessary dependencies.
- Use sub-agents for parallelism. Dispatch independent investigation tasks (reading logs, checking dependency usage, searching historical implementations) to sub-agents running in parallel, keeping only conclusions in the main context; this effectively delays context bloat.
- Manage context actively. In long sessions, periodically have it output a summary of “current conclusions + open items + next steps,” then start a new session from that summary; this is more stable than continuing to probe inside an overlong context.
- Prefer rollback over arguing. When you find the direction is wrong, use version control to revert to a clean state and restate the constraints, rather than repeatedly correcting course on top of the wrong context.
6. Scheduling and Always-On: From “Human-Triggered” to “Pipeline-Triggered”
An agent’s value is amplified in unattended scenarios. There are two ways to achieve it:
One is an in-session loop guard. Most agents provide a mechanism to repeat periodically (for example, as /loop 30m <task>, which makes it re-run the same intent automatically after a set interval). This suits “watch one metric until it converges” tasks: waiting for a build to go green, waiting for load-test targets to be met, waiting for the error rate in logs to fall below a threshold.
The other is non-interactive batch plus external scheduling. The -p (print/non-interactive) mode executes once, emits structured results, and exits, which naturally fits scripts and pipelines:
#!/usr/bin/env bashset -euo pipefailexport AGENT_BASE_URL="${GATEWAY_URL}" AGENT_API_KEY="${GATEWAY_TOKEN}"aic -p "Read the pending-release entries in $(pwd)/CHANGELOG, generate release notes from the team template, and write them to release-notes.md" \--allowedTools "Read,Write,Bash(ls:*),Bash(git diff:*)" \--output-format json > /var/log/agent/release.json# Only continue after validating the resultjq -e '.summary.errors == 0' /var/log/agent/release.json
Four necessary production companions: run in containers (fixed, reproducible environment), persist results (write JSON/Markdown reports to object storage for traceability), collect logs (integrate with a logging service for unified search), and alert on failure (integrate with monitoring/alerting to notify the responsible person on consecutive failures). Automation without observability just hides the risk, which matters most in unattended scenarios.
7. The Ultimate Closed Loop: Dual-End Automation Across UI and Device Layers
Finished code changes don’t mean delivery is complete. A true closed loop requires the agent to open the page itself, click through the flow, and check real-device behavior.
7.1 UI Layer: Browser Automation
Through a browser driver tool service based on the W3C WebDriver standard protocol, the agent gains the ability to navigate, locate elements, click, type, execute scripts, take screenshots, and read console and network requests. Four key practices to use it well:
- Observability over operation. Auto-screenshot and archive every key step, and collect console errors and failed requests; when something fails, this evidence is far more useful than three words like “click timed out.”
- Keep selectors stable. Prefer test-specific identifiers (such as
data-testid) and semantic-role locators; avoid relying on style class names or absolute XPaths that change automatically. The agent’s success rate at guessing selectors is far lower than if you just tell it. - Wait explicitly, not with fixed sleeps. Wait for an element to become visible or for the network to go idle, rather than sleeping a fixed number of seconds; this determines whether the script is stable on slow networks.
- Headed for debugging, headless for running. Use headed mode locally to observe actual behavior, and headless mode in pipelines for throughput.
7.2 Device Layer: Mobile Real-Device Automation
Through a tool service on the mobile debugging bridge protocol (device debugging channel), the agent can list connected devices, install and launch app packages, simulate taps/swipes/input, capture runtime logs, and view the current UI hierarchy. Engineering essentials:
- Authorization first: The device must enable debugging authorization and complete host-side trust; pipeline machines should use a fixed debugging key to avoid manual confirmation every time.
- Put the app identifier and Activity/entry point into the project context, otherwise it has to guess how to launch every time.
- Log capture is the main troubleshooting tool: Combine it with filters to capture only the target process and key levels, otherwise the log volume will instantly drown the context.
- Be clear about real-device vs. emulator differences: Performance, sensors, vendor-customized permissions, and signing/certificate installation all differ; conclusions involving these must be re-verified on a real device.
- Predefine a strategy for permission dialogs: The permission dialog on first install is the most common interruption point for automation.
7.3 What a Dual-End Closed Loop Looks Like
A typical complete task chain runs like this:
Intent: "Fix the coupon-stacking bug on the checkout page and verify on a real device"├─ Info layer: retrieve requirement docs and historical commits, locate the relevant code├─ Code layer: fix the calculation logic, add unit tests and edge cases├─ Build layer: run unit tests + static checks; if it fails, read logs and self-correct├─ UI layer: start the local server → open the checkout page in the browser → construct a multi-coupon scenario → assert the amount → screenshot for evidence├─ Device layer: install the test build → run the same path on a real device → capture logs to confirm no anomalies├─ Regression layer: run the existing E2E suite once to confirm no new failures└─ Output layer: generate a change description + evidence attachments + risk list, submit for human review
Along this chain, the model only needs to understand the intent and constraints; it plans which verification path to take on its own. Your job is to lock in each layer’s tools, commands, and acceptance criteria ahead of time through configuration and skills.
7.4 Common Failure Modes and Countermeasures
| Failure Mode | Root Cause | Countermeasure |
|---|---|---|
| Element location fails | Fragile selectors, page not ready | Test-specific identifiers + explicit wait conditions |
| Steps drift further off course | Context drowned by long logs | Return only conclusions and evidence summaries per step |
| Stuck on permission/login | Session expiry, two-factor challenge | Preset session state, dedicated test accounts |
| “Incidental” changes pile up | Unclear constraints, missing scope limits | Explicit no-change list in the context file |
| Silent failure when unattended | No result validation or alerting | Structured output + exit-code checks + alerting |
8. Security and Governance: Five Questions to Answer Before Going Live
- Credential boundary: Keys go only through environment variables or a secrets-management service; sensitive information in context files, logs, and reports must be redacted before being stored or uploaded.
- Data flow: Which code and data may be sent to an external model service? For scenarios involving user data, core algorithms, or unpublished business data, choose a private deployment or dedicated instance, and define an explicit “may be sent externally / may not” list at the organizational level.
- Permission tiering: Divide tools and commands into five levels—read-only, write-to-workspace, execute-commands, access-network, and operate-external-systems—and tighten each in turn; delete, force-push, deploy, and database-change operations are disabled by default or require a second human confirmation.
- Isolated execution: Run unattended tasks in containers or one-off sandboxes, restricting filesystem and network egress; don’t run automation on machines holding production credentials.
- Auditability: Keep complete call and operation records (tool, parameters, time, result), serving both troubleshooting and compliance review.
9. Rollout Roadmap and Measuring Impact
- Week 1: Get direct-mode integration and a minimal closed loop working; write the project context convention file; confirm build/test commands can run in one shot.
- Weeks 2–4: Integrate filesystem and browser tool services; distill 3–5 high-frequency skills; establish a diff-review and commit standard; wire in call logging.
- Month 2: Upgrade to gateway routing and split models by task; connect the non-interactive mode to the pipeline (generating release notes, bulk refactors, dependency-upgrade sweeps).
- Month 3 and beyond: Add device-layer real-device verification; introduce aggregation and failover; build cost attribution and a quality dashboard.
Don’t measure only “how much code was generated.” More meaningful metrics are: average task delivery time, first-pass rate (the share merged without rework), number of review rework rounds, token cost per task, and the failure rate of automated steps. These are the metrics that credibly tell you whether to expand capabilities, tighten permissions, or change the integration mode.
Closing: Get Your Hands Dirty and Work Along the Capability Boundary
A tool’s value isn’t in how advanced it is, but in whether you’ve actually embedded it into your daily workflow. This guide moved from environment setup to model integration, from context and tool extension to scheduled execution and dual-end automation, and it fundamentally did one thing: gradually filling in what the agent can “see” and what it can “touch.”
Real capability growth comes from continuously working along the boundary: first use it to get one small thing done without your supervision, then extend an inch on each side of that thing. Looking back six months later, you’ll find the change isn’t “it got smarter,” but that your workflow was reorganized once—the repetitive parts handed to it, the judgment left to yourself.
