PavelZanek.com
article Article

June 7, 2026

Vibe Coding in Laravel: AI Agents Need Guardrails

Vibe coding may sound like a shortcut to finished code, but in a production Laravel project speed alone is not enough. AI agents are most useful when their output is checked by types, static analysis, tests, and human review.

Vibe Coding in Laravel: AI Agents Need Guardrails

When people say vibe coding, some hear the future of software development and others hear technical debt. I understand both reactions. AI agents do save me time, but only when they operate inside clear rules, automated checks, and human review. Without that, speed can become a trap rather than an advantage.

This article is primarily about Laravel because that is where I have the clearest AI workflow and the strongest guardrails. But the principle is not limited to Laravel. It applies to other frameworks and smaller technology stacks as well: the less structure your framework and ecosystem give you, the more discipline you need to provide yourself.

I do not want to dismiss the term just because it is provocative. Vibe coding captures an experience many developers now recognize: you describe an intention in natural language and the model quickly returns a diff that looks surprisingly useful. For a prototype, an internal tool, or the first shape of an idea, that can be excellent. For a long-lived project, the second half of the story matters more: discipline.

Vibe coding is not a bad word, but without control it is a risk

The naive version of vibe coding relies on a quiet assumption: if the model output looks convincing, it is probably correct. That is where the difference between a toy workflow and professional engineering begins. Code is not just text that needs to run. It is an agreement about future maintenance, security, readability, domain rules, and the ability to change the system later without unnecessary regressions.

That is why I do not interpret production vibe coding as “accept all” and “ship it”. That workflow may feel fast, but it pushes costs into review, debugging, and long-term maintenance. The model is not accountable for a production bug. The developer and the team that approved the change still are.

A more useful framing is to treat AI as a very fast assistant with limited trust. It can propose a solution, remind you of framework idioms, find related files, prepare a test skeleton, or speed up repetitive refactoring work. It cannot decide on its own whether the change fits the application architecture, business logic, and operational risk profile.

A framework changes the risk, not the principle

I use Laravel as the main example in this article because it offers a strong ecosystem: routing, validation, Eloquent, queues, scheduler, authentication, testing tools, Pint, Larastan, Pest, Rector, and Laravel Boost. But the same thinking also applies to Symfony, Nette, Django, Rails, Next.js, and other frameworks. A framework does not guarantee quality by itself, but it gives the project structure, conventions, and places where mistakes are easier to find.

That matters in vibe coding. When an agent generates code inside a framework, it has a better chance of staying within known boundaries: route, controller, request, service, model, migration, test. When I let the same agent work in a project without a framework, some of those boundaries need to be created manually. That is not wrong, but it raises the responsibility of the person writing the prompt and reviewing the result.

Vibe coding without a framework

Vibe coding without a framework is not automatically a bad idea for me. In fact, it can be very effective for small things. I sometimes use plain Node.js or Python, or an almost framework-free stack, when I need a small internal tool, script, parser, import, export, proof of concept, or tiny application with clear boundaries and no expectation that it will grow into a complex long-term system.

  • a simple CLI script or one-off utility,

  • a small internal data-processing tool,

  • a quick parser, import, or export,

  • a proof of concept for validating an idea,

  • a small app without user roles, payments, or complex operations.

In those cases, a framework can sometimes add more overhead than value. If the application has a few files, a clear input, a clear output, and a low impact when something fails, a simple stack can make sense. Even then, I still want basic discipline: readable structure, simple tests or verification scenarios, clear run instructions, and diff review.

But once an application deals with users, authentication, authorization, databases, forms, emails, files, queues, payments, APIs, or long-term maintenance, I would quickly reconsider a no-framework approach. Not because nothing can be built without a framework, but because frameworks provide ready-made answers to problems that otherwise need to be solved manually again.

In a production Laravel project, I do not hand responsibility to the model

What interests me about AI is not the idea that it programs instead of me. The real value is that it reduces friction in work that used to be unnecessarily slow. When I need to understand an unfamiliar part of a codebase, an agent can inspect routes, controllers, requests, policies, models, and tests, then return a first map of the territory. When I work on a refactor, it can suggest smaller steps. When I write tests, it can surface scenarios I might otherwise discover later.

But that does not mean I outsource judgment. In maintained codebases, the hard part is often context: why something was designed in a particular way, which historical decision led to it, which integrations must not break, and where the domain has unwritten rules. A model can find a lot of that context, but it cannot carry the consequences of a bad decision for me.

So I prefer to talk less about magic and more about process. An AI-generated proposal is only the beginning of a change. It becomes useful only after it goes through the same path as any other code: formatting, static analysis, types, tests, coverage, and finally a human reading the diff.

How I use AI agents in Laravel in practice

I most often use an AI agent as a fast exploration tool. I ask it to inspect a feature, summarize the request flow, identify where input is validated, where side effects happen, and which tests already exist. That can take a capable developer a meaningful amount of time, especially in a project they do not fully hold in their head. An agent can often produce a useful first picture much faster.

The second use case is drafting changes. Here the size of the task matters. Instead of asking it to rewrite a whole module, I prefer smaller prompts: propose a new Form Request, add a feature test for this scenario, check whether a service returns a consistent type, or prepare a refactor of one method without changing behavior. The smaller the unit of work, the easier the output is to review.

The third area is tests and intent documentation. AI is useful for finding edge cases, naming tests, and quickly creating the first version of test data. But a test suggested by a model is not automatically a good test. It must verify the real behavior of the application, not merely confirm the implementation the model just produced.

Guardrails change with the stack

In Laravel, my guardrails are relatively clear: Pint, Larastan/PHPStan, Pest, Rector, code coverage, type coverage, and manual review. In another stack, the tools will be different, but the principle stays the same. In a TypeScript project, a similar role may be played by strict TypeScript, ESLint, Prettier, Playwright, and a test runner. In Python, it may be Ruff, mypy, pytest, and a simple module structure. In a small no-framework tool, it may be a set of input and output examples, a smoke test, and a clear README.

The fewer ready-made rules a framework gives me, the more rules I need to create myself. That is the most important general rule for me. Vibe coding is not safer merely because it produces a smaller application. It is safer when the impact of a mistake is small and when there is a fast way to verify the result.

Guardrails: the less blind trust, the more room for AI

The paradox is that AI helps me more precisely because I do not trust it blindly. If I know every change will pass through a set of checks, I can be more ambitious about what I ask it to draft. Guardrails are not a brake. They are the boundaries that allow the workflow to move faster without sending every mistake directly to users.

In Laravel projects, a few tools fit this workflow particularly well. Laravel Pint removes style noise and keeps diffs readable. Larastan and PHPStan catch type problems, missing return values, and issues that might otherwise hide behind Laravel “magic”. Pest verifies behavior, architecture, type coverage, and code coverage. Rector helps with safe refactors and gradual tightening of the codebase.

The important part is that these tools are not adjacent to AI. They are part of the same workflow. The agent may produce the first proposal, but it should not pass just because its answer sounded confident. An analyzer, a test runner, and a review process do not care about confidence. The change either passes or it goes back for correction.

Laravel Boost gives the agent better context

Laravel Boost deserves special attention in this workflow. I do not see it as a magic layer that turns a model into a senior developer. I see it as a practical way to give the agent better context. That matters in Laravel because an answer that is correct for one framework version or stack may be wrong for another project.

Boost helps by exposing Laravel-specific rules, documentation that matches installed package versions, and information about the application. Instead of relying on generic guesses, the tool can work from more concrete knowledge. That reduces common AI mistakes such as suggesting a pattern from the wrong major version or missing a convention the project already uses elsewhere.

Better context is still not the same as responsibility. Boost can reduce nonsense, improve the idiomatic quality of suggestions, and speed up discovery. It does not decide whether a particular architectural change is a good idea, whether it matches the domain, or whether it is worth the future maintenance cost.

The critics are often right

Criticism of AI coding should not be dismissed as people failing to understand the future. Many concerns are valid. AI can produce code that looks functional but is harder to maintain. It can increase review load. It can introduce security problems. It can generate a solution that passes the happy path but breaks an edge case.

That is exactly why I do not defend blind AI usage. If someone criticizes vibe coding in the sense of “copy, paste, deploy”, I largely agree with them. That workflow belongs closer to prototyping than production applications. The disagreement starts when all AI-assisted development gets treated as the same thing.

Disciplined use of AI agents is a different category. It does not say the model is always right. It says the model can quickly produce a proposal that must pass strict validation. It does not say review is unnecessary. It says review can be more effective when the diff is smaller, formatted, covered by tests, and accompanied by a clear explanation of intent.

A practical pipeline for AI-assisted changes

My ideal pipeline for an AI-assisted change in Laravel is simple. The agent first proposes the smallest reasonable change. Then automated checks run. Rector verifies or performs mechanical refactors. Pint normalizes style. Larastan and PHPStan run static analysis. Pest verifies behavior and type coverage. Coverage shows whether the change has test support. Only then does it make sense to read the diff manually and decide whether it should move forward.

In practice, this does not have to stay as an abstract pipeline. In my composer.json, the workflow is split into two layers: commands that fix code, and commands that verify before merge that a change passed refactoring checks, linting, static analysis, type coverage, architecture tests, and unit/feature tests:

{
  "scripts": {
    "ide:models": [
      "@php artisan ide-helper:models --reset --write"
    ],
    "refactor": [
      "rector",
      "pint  --parallel"
    ],
    "lint": [
      "pint --parallel"
    ],
    "test:refactor": [
      "rector --dry-run --ansi"
    ],
    "test:lint": [
      "pint --test"
    ],
    "test:types": [
      "phpstan analyse --memory-limit=2G --error-format=table --ansi"
    ],
    "test:type-coverage": "pest --type-coverage --min=100",
    "test:arch": "pest --testsuite=Arch --parallel --processes=8 --ci --colors=always",
    "test:unit": "pest --testsuite=Unit,Feature --parallel --processes=8 --ci --colors=always --coverage --min=98",
    "test": [
      "@composer test:refactor",
      "@composer test:lint",
      "@composer test:types",
      "@composer test:type-coverage",
      "@composer test:arch",
      "@composer test:unit"
    ]
  }
}

This example matters because it does not rely on a single AI-generated diff that merely looks convincing. refactor and lint help fix mechanical issues quickly, while test chains several independent checks together. If an agent produces a change, it has to pass Rector dry-run, Pint, Larastan/PHPStan, type coverage, architecture tests, and finally regular unit and feature tests with a coverage threshold.

It is not about the framework, it is about responsibility

If I had to summarize my position in one sentence, it would be this: AI saves me time, but it does not remove my responsibility. Laravel is the main example in this article because it has a strong ecosystem of guardrails. But the same thinking applies elsewhere. In a framework, without a framework, in Node.js, Python, or another stack, someone still needs to understand the result, verify it, and be responsible for it.

The future I care about is not blind vibe coding. It is closer to agentic engineering: clear intent, good context, small steps, automated checks, and a person who reads the diff and makes the decision. For a small framework-free utility, the control layer can be simple. For a production application, it needs to be much stronger. The better my guardrails are, the more room I can give AI. And the less I trust it blindly, the more safely it saves time in practice.

hub Related content

Related content

Additional content from this site connected to this article.

hub

Laravel Boost

Laravel Boost starts to make sense when an AI agent should stop answering in general terms and work with a real Laravel application instead. It helps the agent understand package versions, routes, database schema, configuration, and documentation, so suggestions are less detached from the project. It is still only support for the developer, but in a larger codebase it can remove a lot of manual lookup work.

Tool arrow_forward
hub

Rector

I see Rector as a tool for the point where manual refactoring stops making economic sense. It can scan a PHP codebase, apply mechanical changes, and help with language or framework upgrades without forcing a developer to hand-edit thousands of tiny details. Its real value appears when it is part of a controlled process, not blind automatic rewriting.

Tool arrow_forward
hub

Laravel Pint

Laravel Pint solves one quiet but important problem: the team no longer has to keep discussing PHP code formatting. It is built on top of PHP-CS-Fixer, ships with sensible Laravel defaults, and works well both for local fixes and CI checks. Its biggest value appears when code style stops being a code review topic.

Tool arrow_forward
hub

Larastan

I use Larastan as a way to bring static analysis into a Laravel project without ignoring Eloquent, facades, and the dynamic parts of the framework. It does not replace tests or review, but it can catch type errors, incorrect return values, and small problems that would otherwise appear only when the application is running.

Tool arrow_forward
hub

Pest PHP

Pest PHP is a modern testing framework for PHP with a simple and readable syntax. It is not only a nicer way to write tests, but a tool that lowers the friction of testing regularly and fits naturally into the Laravel ecosystem. It helps most when tests are a normal part of development, not a separate chore at the end.

Tool arrow_forward
alternate_email

Let's stay in touch

Subscribe to get the latest Laravel and infrastructure insights straight to your inbox.