DEV Community

Cover image for Build Laravel Agentic Apps Faster
gtapps
gtapps

Posted on

Build Laravel Agentic Apps Faster

I’ve been adding always-on Claude Code agents to several Laravel applications. I kept running into the same problem: a single business operation often needed separate implementations for Laravel AI, Laravel MCP, HTTP, Artisan, and queues.

So I built laravel-agentic and decided to open-source it. It's my go-to now when building any laravel app, to make it immediately agentic ready ;).

The idea is simple: define an action once, then expose it through whichever surfaces you need.

#[AgentAction(
    name: 'refund-invoice',
    needsApproval: true,
    surfaces: [
        Surface::Mcp,
        Surface::AiTool,
        Surface::Http,
        Surface::Cli,
        Surface::Job,
    ],
)]
class RefundInvoice
{
    public function authorize(
        ActionContext $context,
        RefundInvoiceInput $input,
    ): bool {
        return $context->user()->can(
            'refund',
            Invoice::find($input->invoiceId),
        );
    }

    public function handle(
        RefundInvoiceInput $input,
        ActionContext $context,
    ): RefundResult {
        // Refund logic
    }
}
Enter fullscreen mode Exit fullscreen mode

That single definition is now callable, with the same validation, authorization, approval, and audit behavior (tests/ParityTest.php holds all five surfaces to it), via:

Surface How
laravel/mcp tools/call refund-invoice on the server above
laravel/ai Agentic::tools() inside any agent's tools() iterable; Agentic::tools($only, $user) pins an explicit principal instead of the ambient guard
HTTP POST /agentic/actions/refund-invoice (GET allowed for readOnly); opt-in, off by default (agentic.http.enabled)
CLI php artisan agentic:action refund-invoice '{"invoiceId":42,"amount":99.5}' --as=1
Queue RunAction::dispatch('refund-invoice', $args, $userId)

For consequential operations, needsApproval pauses an authorized action before execution and waits for human consent:

  1. Laravel Agentic validates the input and runs authorize().
  2. If approval is required, it creates an approval request and stops before executing the action.
  3. Your application handles the ApprovalRequested event and delivers the request through your UI, Slack, email, or another channel.
  4. After approval:
    • Laravel AI resumes the paused tool call through its native approval system.
    • MCP, HTTP, and CLI callers repeat the same action with the same principal and arguments.
  5. The single-use grant is consumed and the action executes once.

Laravel Agentic provides the approval state, argument binding, expiry, enforcement, and audit trail. Your application provides the human-facing approval channel.

It builds on top of laravel/ai, laravel/mcp, and spatie/laravel-data.

Let me know what you guys think

GitHub: https://github.com/gtapps/laravel-agentic

Top comments (0)