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
}
}
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:
- Laravel Agentic validates the input and runs
authorize(). - If approval is required, it creates an approval request and stops before executing the action.
- Your application handles the
ApprovalRequestedevent and delivers the request through your UI, Slack, email, or another channel. - 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.
- 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
Top comments (0)