2026-08-21 · en
Build a Coding Agent
A coding agent needs a clear control loop, an action vocabulary, and evidence at the finish line.
A coding agent is a control loop that lets a model observe a codebase, request actions, learn from their results, and stop with evidence.
This article explains how I built Froe, a small coding agent. The goal was to build a genuinely usable implementation whose complete behavior can still be understood from the repository.
Froe has six actions, one production model adapter, a run loop, and a command sandbox. It can inspect files, edit code, run checks, and hold an interactive conversation. It also records enough structured information to explain what happened after a run.
The control loop
The smallest useful coding agent has four participants:
- A user supplies a task.
- A model decides what information or action it needs next.
- A runtime executes that action and returns a structured result.
- The loop repeats until the model finishes or the host stops it.
In Froe, that loop lives in src/run.ts.
Give the model a small action vocabulary
Froe exposes six actions from src/action-runtime.ts:
| Action | Purpose |
|---|---|
list_files |
List one directory level. |
read_file |
Read a range from a UTF-8 text file. |
search |
Find literal, case-sensitive text in the workspace. |
apply_patch |
Create, replace, or delete text through exact-match changes. |
run_command |
Run one executable with an argument array. |
finish |
End the run with an outcome and verification records. |
This vocabulary is enough for a practical investigation and edit cycle:
|
Running Froe
Froe requires Node.js 22 or later. Command execution currently requires macOS.
Install the published package:
|
Then run it inside a repository:
|
Run froe without a task to start an interactive conversation. On the first interactive run, it asks for an OpenAI API key and an OpenAI-compatible base URL, then saves them in an owner-readable credential file under the user’s configuration directory.
To work on Froe itself:
|
What I would keep if the project grew
Froe’s first release deliberately omits persisted conversation resume, multiple inference providers, and non-macOS command sandboxes. Those features may be useful, but adding them before the core behavior was coherent would have made the implementation harder to inspect.
That structure leaves clear extension points. A second provider can implement the model interface. A Linux sandbox can implement the command sandbox interface. Stronger verification can be added at the finish boundary. A resume protocol can persist provider-neutral conversation state once its privacy and compatibility rules are defined.