Rekhu Assistant
Rekhu Assistant: Laravel
Install rekhu/assistant-laravel, add the chat to your layout, mark the first action and choose the setup for your front end.
What this package does
rekhu/assistant-laravel runs the chat on your Laravel server. It adds the chat routes, signs the user in with your own session or token, offers only the actions and pages that user may use, and runs your routes as that user, through their middleware, form requests and policies. It needs no tables of its own; conversations are kept in your cache, or in one table for the conversation history.
It works with PHP 8.2 or newer and Laravel 10.48 to 13.
Install in five steps
- Get a key. In your Rekhu account, open Projects → New project, choose Laravel app (monolith or multi-tenant) and name it. Turn on its assistant on the Assistant tab, and on the Connection tab add a key for
localin the Rekhu Assistant card. The key is shown once. - Install the package. Require it and run the install command with the key. It checks the key with Rekhu, writes
REKHU_ASSISTANT_KEYto.env, publishesconfig/rekhu-assistant.phpand createsresources/rekhu/help. - Add the chat. Put the tag in your layout, before
</body>. The chat button appears for signed-in users. - Mark the first action. Let Rekhu propose them with the scan, or put
#[Tool]on a controller method. See Actions and the scan. - Check what the assistant sees. Run
rekhu:assistantas one of your users. It shows your credit, the actions, pages and help topics that user can reach, and tests the connection.
composer require rekhu/assistant-laravel
php artisan rekhu:assistant-install --key=agk_…
php artisan rekhu:assistant:scan
php artisan rekhu:assistant --user=1
{{-- resources/views/layouts/app.blade.php --}}
<body>
{{ $slot }}
<x-rekhu-assistant />
</body>
Or mark an action in the code:
use Rekhu\Assistant\Attributes\Tool;
class OrderController extends Controller
{
#[Tool('Reorder a past order: the same product and address as a new order; the quantity can be changed')]
public function reorder(ReorderRequest $request, Order $order)
{
// your own code, as for the form on the order page
}
}
Then sign in, open the chat and ask "order my last business cards again".
Choose your setup
The package runs the chat on your server in every setup. What differs is how the chat is added and how the user signs in.
| Your app | The chat | Sign-in |
|---|---|---|
| Blade | <x-rekhu-assistant /> |
the session |
| Livewire | <x-rekhu-assistant />, inside @persist |
the session |
| Inertia (Vue or React) | the Blade tag, or the web widget for router navigation | the session |
| An API for Nuxt, Next or a mobile app | the web widget, or Flutter | a token (Sanctum, Passport or your own) |
Blade and Livewire
The Blade tag uses the user's session and the page's CSRF token, and the package serves the chat's script itself: no npm and no build step. Attributes override the config for one layout:
<x-rekhu-assistant name="Shop assistant" greeting="Hi! How can I help with your order?" color="#0f766e" />
With Livewire's wire:navigate, keep the chat on the page while users navigate:
@persist('rekhu-assistant')
<x-rekhu-assistant />
@endpersist
An API with its own front end
Put the chat behind your API guard, and allow the front end's domain in config/cors.php ('paths' => [..., 'rekhu/assistant/*']):
REKHU_ASSISTANT_MIDDLEWARE=api,auth:sanctum
REKHU_ASSISTANT_FRONTEND_URL=https://app.example.com
When your front end is one of Sanctum's stateful domains and only api/* is exempt from CSRF, put the chat under it with REKHU_ASSISTANT_PATH=api/rekhu/assistant. The front end then mounts the web widget with the user's token.
Laravel does not know the pages of a Nuxt or Next front end, so list them under pages.frontend.list in the config, or give them from code:
use Rekhu\Assistant\RekhuAssistant;
RekhuAssistant::pagesUsing(fn ($user) => ! $user ? [] : collect(config('shop.pages'))
->filter(fn ($page) => $user->can($page['permission']))
->all());
Your own routes
The package registers its routes at rekhu/assistant. To put them in your own route file, with your own prefix and middleware, turn that off with REKHU_ASSISTANT_ROUTES=false and register them yourself:
// routes/api.php
use Rekhu\Assistant\RekhuAssistant;
RekhuAssistant::routes(['middleware' => ['api', 'auth:sanctum']]);
Who may use the chat
The chat's middleware (REKHU_ASSISTANT_MIDDLEWARE, web,auth by default) decides who reaches it. Add your own rule, and tell the package how your app checks rights when it is not can: middleware:
use Rekhu\Assistant\RekhuAssistant;
public function boot(): void
{
RekhuAssistant::accessUsing(fn ($user) => $user->can('use-assistant'));
RekhuAssistant::authorizeUsing(fn ($user, $route) => $user->isAbleTo($route->getName()));
RekhuAssistant::tenantUsing(fn ($user) => $user->team); // a multi-tenant app: usage per tenant
}
authorizeUsing only decides what the assistant offers. Every call still runs through the route's own middleware.
Configuration
| Environment variable | Default | Purpose |
|---|---|---|
REKHU_ASSISTANT_KEY |
the app key, written by rekhu:assistant-install |
|
REKHU_ASSISTANT_MODEL |
empty | the model that answers, by its name in your Rekhu account; empty uses the default |
REKHU_ASSISTANT_NAME |
Assistant |
the assistant's name in the chat and its answers |
REKHU_ASSISTANT_MIDDLEWARE |
web,auth |
who may use the chat |
REKHU_ASSISTANT_GUESTS |
false |
the public chat for visitors |
REKHU_ASSISTANT_REPORTS |
true |
"Report a problem" under each answer |
REKHU_ASSISTANT_LOG |
true |
the chat log in storage/logs/rekhu-assistant-YYYY-MM-DD.log |
REKHU_ASSISTANT_DEBUG |
local only | the developer view under each answer |
config/rekhu-assistant.php also holds instructions (your own rules, in plain words), greeting and color, quick (questions a user can click in a fresh chat), max_tokens (16000) and max_steps (8), the public chat's caps under guests, and the conversations settings.
How the assistant behaves for your users (tone, the words of your trade, what it never does) belongs in the project's Knowledge in your Rekhu account. It reaches the assistant on every call, without a deploy.
Reselling to your customers
After every answer, AnswerCompleted fires with what it used: the user, the tenant, the conversation, the model, the input, output and cache tokens of all its model calls, and the actions it ran. Charge a plan's credit there:
use Rekhu\Assistant\Events\AnswerCompleted;
use Rekhu\Assistant\RekhuAssistant;
Event::listen(AnswerCompleted::class, function (AnswerCompleted $e) {
AssistantTurn::create([
'tenant_id' => $e->tenant['id'], 'user_id' => $e->user?->getAuthIdentifier(), 'model' => $e->model,
'input_tokens' => $e->inputTokens, 'output_tokens' => $e->outputTokens, 'calls' => $e->calls,
]);
});
RekhuAssistant::modelUsing(fn ($user, $request, $scope) => $user?->team?->plan?->assistant_model);
modelUsing picks the model per plan, by its name in your Rekhu account; null falls back to REKHU_ASSISTANT_MODEL. For white-label chats, brandUsing() gives each tenant its own name, logo and colours, and REKHU_ASSISTANT_REKHU_BRAND=false keeps Rekhu's name out of the chat.
Commands
| Command | What it does |
|---|---|
rekhu:assistant-install --key=agk_… |
checks the key, writes it to .env, publishes the config, creates the help folder |
rekhu:assistant --user=12 |
your credit, and the actions, pages and help that user can reach |
rekhu:assistant:scan |
proposes actions in assistant/actions.php |
rekhu:assistant:try list_orders --user=12 --locale=ar |
runs one action as that user, exactly as the chat does |
rekhu:assistant:check --user=12 |
finds unclear actions and results too long to read; fails in CI on problems |
rekhu:assistant:test --user=12 |
asks the questions in assistant/questions.php and checks each used the right action |
make:assistant-tool OverdueInvoices |
a Tool class in app/Assistant/Tools |
Next
- Actions and the scan: what the assistant may do, and how to describe it well.
- The web widget: the chat in a Vue, React, Nuxt or Next front end.
- Conversation history: earlier conversations in a list next to the chat.