Automating the Build-Test-Fix Loop with AI Agents in Laravel
This article details a fully automated AI agent workflow for Laravel using Laravel Boost and OpenCode CLI, where specialized agents autonomously handle building, testing, diagnosing failures, and fixing code in a persistent queue-driven loop until tests pass, with human review only at the end.
The article opens by illustrating the repetitive manual workflow developers endure when using AI coding tools: prompt AI, copy code, paste into editor, run tests, copy errors, paste back to AI, ask for fixes, and repeat. The author argues that in this loop, humans act as mere couriers between AI and the development environment, while the AI passively awaits instructions.
The core proposal is to restructure this workflow by introducing an orchestrator that drives a fully autonomous cycle: Build → Test → (Fix → Test)* → Review → Complete. Humans intervene only at the final review stage. Two Laravel‑ecosystem tools enable this:
Laravel Boost – a Composer dev dependency that exposes the project’s real context (database schema, routes, logs, Artisan commands, version‑matched docs) to AI agents via the Model Context Protocol (MCP). It does not make decisions; it only provides accurate context.
OpenCode CLI – a terminal‑based environment where multiple specialized agents (builder, tester, debugger, fixer, reviewer) run with strict tool permissions (read‑only vs. read‑write).
Key Terminology
Agent : AI program with a defined role and tool permissions.
MCP (Model Context Protocol) : Bridge letting AI query live project data.
CLI : Command‑line interface for agent execution.
Job/Queue : Laravel’s async task mechanism for background processing.
Orchestrator : State‑driven scheduler that decides the next legal transition based on the current task status.
Manual Setup & Agent Definitions
After installing Boost ( composer require laravel/boost --dev and php artisan boost:install), the MCP connection is configured in opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"laravel-boost": {
"type": "local",
"command": ["php", "artisan", "boost:mcp"],
"enabled": true
}
}
}Verification: opencode mcp list should show laravel-boost as connected.
Agents are defined as Markdown files under .opencode/agent/. Example builder.md:
---
description: 负责新功能开发的构建智能体
mode: primary
tools:
write: true
edit: true
---
你是构建智能体(Build Agent)。
编写代码前,必须先通过 Laravel Boost 工具理解应用结构。
禁止假设数据库结构,永远先校验表结构。
所有新功能都必须编写对应的测试用例。
工作完成后,仅返回如下格式的 JSON:
{"status": "success", "files_changed": [...], "summary": "..."}The tools.write: true grant permits file modifications; other agents (debugger, reviewer) receive read‑only access to enforce separation of concerns.
Persistent State Machine
Because the loop runs unattended, every step’s progress is stored in an ai_tasks table:
Schema::create('ai_tasks', function (Blueprint $table) {
$table->id();
$table->string('type');
$table->string('status')->default('pending');
$table->text('prompt');
$table->json('result')->nullable();
$table->unsignedTinyInteger('iteration')->default(0);
$table->timestamps();
});Status flow:
pending → building → testing → (fixing → testing)* → reviewing → completed / failed. A multi‑state machine (not a simple boolean) enables resume‑after‑crash, real‑time UI progress, and precise orchestration.
Abstraction Layer: AgentRunner Interface
To avoid scattering OpenCode calls throughout business code, an AgentRunner interface is defined and implemented by OpenCodeAgentRunner, which uses Symfony’s Process component with a 600‑second timeout and JSON output. The container binds the interface in a service provider.
Queue Jobs per Stage
Each phase is a separate ShouldQueue job, dispatched by the previous job:
BuildFeature – runs the builder agent, saves result, updates status to testing, dispatches RunTests.
RunTests – executes php artisan test --compact (300s timeout). On success: status → reviewing, dispatch ReviewFeature. On failure: status → failed, dispatch AnalyzeFailure with raw error output.
AnalyzeFailure – structures the error into JSON (failed test name, error message) and invokes a read‑only Debug Agent that returns root cause, affected files, recommended fix, and regression risk.
FixFeature – receives the analysis, runs the fixer agent, increments iteration, sets status back to testing, and re‑dispatches RunTests.
Critical rule : after a fix, the status must return to testing; never mark complete without a fresh test run. The only proof of correctness is the test suite passing in the real environment.
Orchestrator: State‑Driven Scheduler
Instead of a linear chain, an AgentOrchestrator uses a match expression on $task->status to dispatch the next legal job. This makes branching (e.g., failure → analyze → fix → retest) trivial and allows inserting new stages (security scan, compliance check) without rewiring the whole flow.
Retry Limit & Circuit Breaker
A constant MAX_ITERATIONS = 5 in RunTests stops infinite loops. After five failed fix‑test cycles, the task status becomes needs_human_review, alerting a developer. This also caps API costs.
Tests Passing ≠ Done
The article warns that green tests can mask wrong business logic (e.g., an authorization policy that only checks isAdmin() instead of project membership). Therefore, a mandatory human review stage is non‑negotiable, especially for auth, finance, or security‑sensitive code.
Concurrency Safety via Permission Isolation
To prevent race conditions when multiple agents run in parallel, file permissions are strictly partitioned:
Research, Review, Security agents: read‑only.
Builder, Fixer agents: read‑write.
This mirrors the tools.write: true setting in agent definitions.
Rejecting the “God Agent”
The author strongly advises against a single monolithic agent. Instead, apply the Single Responsibility Principle: Planner, Builder, Tester, Debugger, Fixer, Reviewer – each with a narrow context and toolset. This reduces hallucination risk and keeps reasoning chains auditable.
Seven Day‑One Non‑Negotiables
Hard retry limit.
Timeouts on every agent command.
Role‑based file permission isolation.
Tests must pass before entering review.
Human sign‑off before production merge.
Log every agent’s reasoning trail, not just final output.
Protect .env and other secrets; sandbox agent execution.
System Topology & Conclusion
The final architecture places the developer at the top, delegating to a Laravel‑queue‑based orchestrator that coordinates specialized agents running inside OpenCode, which in turn consume context from Laravel Boost via MCP, all operating on the actual Laravel application. Boost never decides when to test or fix; the orchestrator owns that control flow.
The article concludes that the industry question has shifted from “Can AI write correct Laravel code?” to “Can we let AI run its own feedback loop autonomously?” The answer, demonstrated with the TaskFlow case study, is yes—provided we enforce persistent state, hard iteration caps, and treat passing tests as a signal, not a finish line.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Open Source Tech Hub
Sharing cutting-edge internet technologies and practical AI resources.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
