rekhu

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

  1. 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 local in the Rekhu Assistant card. The key is shown once.
  2. Install the package. Require it and run the install command with the key. It checks the key with Rekhu, writes REKHU_ASSISTANT_KEY to .env, publishes config/rekhu-assistant.php and creates resources/rekhu/help.
  3. Add the chat. Put the tag in your layout, before </body>. The chat button appears for signed-in users.
  4. Mark the first action. Let Rekhu propose them with the scan, or put #[Tool] on a controller method. See Actions and the scan.
  5. Check what the assistant sees. Run rekhu:assistant as 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