Skip to content

Coding Agent

Autonomous test-driven development agent with E2B sandbox

Get Code

The coding-agent template is an autonomous test-driven development loop. Given a task description, it plans, writes tests, writes an implementation, runs both inside an isolated E2B sandbox, and iterates on failures until the tests pass or a retry budget is exhausted. Every LLM call runs through Groq for fast inference.

What you’ll build

  • A planner_node that turns a task description into a dev plan and a test plan
  • A test-then-code generation flow: tests are written first, then code guided by those tests
  • An error-analysis loop that reads pytest failures and drives targeted fixes on retry
  • Sandboxed execution - code and tests are synced, dependencies installed, and pytest run entirely inside an E2B sandbox

Requirements

Install

curl -LsSf https://agnt5.com/cli.sh | bash

Setup

Scaffold the project

agnt5 create —template python/coding_agent my-coding-agent
cd my-coding-agent
agnt5 create —template typescript/coding_agent my-coding-agent
cd my-coding-agent

Set environment variables

cp .env.example .env

Get keys at console.groq.com/keys and e2b.dev/dashboard.

Install dependencies

uv sync
pip install -e .
npm install

Start the AGNT5 dev server

agnt5 dev up

How it works

The workflow starts with a planning step that produces a dev plan and a test plan. On the first iteration, a test-generation step writes the test suite, then a code-generation step writes an implementation guided by those tests. A sync step validates syntax locally and writes both files into an E2B sandbox, a dependency-install step installs any third-party imports it detects, and an executor step runs the test suite in the sandbox. If tests fail, an error-analysis step turns the failure output into a structured diagnosis (failed tests, root causes, suggested fixes), which feeds directly into the next code-generation call - the model fixes code with a diagnosis in hand rather than regenerating blind. This loop repeats up to a configurable retry budget; on success, a final step writes a Markdown summary.

Every step is a durable checkpoint, so a crash mid-sandbox-run replays cleanly - completed iterations return their journaled results, and only the in-flight step re-executes. The retry budget is enforced by the workflow, not the model, so there’s a hard ceiling on cost and latency.

Warning:

E2B sandboxes cost money per minute and have startup latency. The workflow reuses the same sandbox across iterations once one is created.

Key files

app.py                          - Worker entry point
src/coding_agent/workflows.py   - coding_agent_workflow: plan, generate, sync, install, execute, decide, retry
src/coding_agent/functions.py   - planner_node, test_generator_node, code_generator_node, error_analyzer_node,
code_sync_node, install_deps_node, code_executor_node, final_response_node
src/coding_agent/tools.py       - E2BSandboxTools: sandbox creation, file writes, command execution
src/coding_agent/models.py      - Plan, GeneratedCode, ErrorAnalysis, SyncResult, ExecutionResult, WorkflowResult
src/coding_agent/prompts/coding_agent_prompts.py - planner, coder, test-generator, error-analyzer, doc-writer prompts
app.ts             - Worker entry point
src/workflow.ts    - codingAgentWorkflow: plan, generate, sync, install, execute, decide, retry
src/functions.ts   - plannerNode, testGeneratorNode, codeGeneratorNode, errorAnalyzerNode,
codeSyncNode, installDepsNode, codeExecutorNode, finalResponseNode
src/tools.ts       - createSandboxTool, writeFileTool, and the E2B sandbox helpers they wrap
src/prompts/index.ts - planner, coder, test-generator, error-analyzer, doc-writer prompts

Customize

Swap Groq for another model. Every LLM call goes through lm.generate(model="groq/...", ...) in functions.py (or the TypeScript equivalent in functions.ts). Change the model string and the corresponding API key.

Replace E2B with a local runner. Swap the E2B sandbox helpers in tools.py/tools.ts for a Docker-based runner with the same create/write/run interface, and the workflow is unchanged.

Tighten the retry budget. Lower max_retries in the workflow call to cap cost for simple tasks. The workflow returns whatever the best result is, or a failure with the last error logs, once the budget is exhausted.

Next steps