Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама
Новини 09 жовтня 2026

Laravel AI SDK на практиці: агент, що стоїть за There There

Фрік Ван дер Гертен (Freek Van der Herten) у своєму дописі поділився досвідом використання нового Laravel AI SDK у There There - хелпдеску, який команда Spatie створює для себе. Після двох десятиліть власної підтримки клієнтів вони вирішили більше не миритися з компромісами в інструментах і зробити той, яким хочуть користуватися самі.

Роль AI у There There

Найцікавіша частина проєкту - AI. Його використовують не для заміни агентів підтримки, а для того, щоб вони працювали швидше. Людина читає тікет, думає й натискає кнопку, а модель підтягує релевантну історію, готує чернетку відповіді, ставить теги та закриває дублікати. Зараз There There перебуває в закритому бета-тестуванні, а заявку на ранній доступ можна подати на there-there.app.

Весь AI-шар збудований на Laravel AI SDK.

Клас агента

Усе починається з класу агента - у Spatie він називається ThereThereAgent. Він визначає, яку модель використовувати, як виглядає системний промпт, які інструменти (tools) може викликати модель і яку історію розмови відтворювати. Ось скорочена версія:

use Laravel\Ai\Attributes\MaxSteps;
use Laravel\Ai\Attributes\Temperature;
use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Contracts\Conversational;
use Laravel\Ai\Contracts\HasTools;
use Laravel\Ai\Promptable;

#[Temperature(0.3)]
#[MaxSteps(10)]
class ThereThereAgent implements Agent, Conversational, HasTools
{
    use Promptable;

    public function __construct(
        protected Workspace $workspace,
        protected User $user,
        protected ?Ticket $contextTicket = null,
        protected array $conversationHistory = [],
    ) {}

    public function model(): string
    {
        return config('ai-pricing.default.name');
    }

    public function instructions(): string
    {
        return view('prompts.ai.there-there-agent-system', [
            'workspace' => $this->workspace,
            'user' => $this->user,
            'contextTicket' => $this->contextTicket,
        ])->render();
    }

    public function tools(): iterable
    {
        return [
            new ChangeTicketStatusTool($this->workspace),
            new AssignTicketTool($this->workspace),
            new AddNoteToTicketTool($this->workspace),
            new ManageTicketTagsTool($this->workspace),
        ];
    }
}

Тут цікаві кілька речей:

  • Атрибути #[Temperature] і #[MaxSteps] декларативні - не потрібно передавати значення через параметри конструктора чи конфігураційний файл.
  • Метод instructions() рендерить Blade-представлення, тож системний промпт - це звичайний шаблон з include та partial.
  • Метод tools() повертає iterable, тому інструменти можна вмикати й вимикати залежно від контексту.

Інструменти (tools)

Інструменти - це класи, які модель може вирішити викликати. Вони мають типізовану JSON-схему, тож аргументи валідуються ще до того, як потраплять у код застосунку. Ось інструмент, що змінює статус тікета:

class ChangeTicketStatusTool implements Tool
{
    use FindsTicketsInWorkspace;

    public function __construct(protected Workspace $workspace) {}

    public function description(): string
    {
        return 'Change the status of a ticket. Use this when the agent asks to close, reopen, or mark a ticket as spam.';
    }

    public function schema(JsonSchema $schema): array
    {
        return [
            'ticket_subject' => $schema->string()->description('The subject, title, or ULID of the ticket.')->required(),
            'contact_email' => $schema->string()->description('The contact email on the ticket.')->required(),
            'new_status' => $schema->string()->description('The new status: open, closed, or spam.')->required(),
        ];
    }

    public function handle(Request $request): string
    {
        $status = TicketStatus::tryFrom($request['new_status'] ?? '');

        if (! $status) {
            return 'Invalid status. Must be one of: open, closed, spam.';
        }

        $ticket = $this->findTicket($request['ticket_subject'], $request['contact_email']);

        if (! $ticket) {
            return 'Could not find a matching ticket.';
        }

        app(ChangeTicketStatusAction::class)->execute($ticket, $status);

        return json_encode([
            'result' => 'success',
            'ticket' => $ticket->displayTitle(),
            'new_status' => $status->label(),
        ]);
    }
}

Кожен метод має чітку роль:

  • description() - те, що модель читає, вирішуючи, чи викликати цей інструмент.
  • schema() - типізована JSON-схема, якій має відповідати модель.
  • handle() - виконує інструмент і повертає рядок, що потрапляє назад у контекст моделі. У разі успіху повертається JSON, щоб у моделі були структуровані дані для фінальної відповіді.

Важливо, що всередині інструмента немає складної логіки. Реальна робота делегована ChangeTicketStatusAction - звичайній domain-дії. Інструмент лише виступає AI-адаптером над кодом, який уже існував.

Виклик агента

Викликати агента з action можна кількома рядками:

$agent = new ThereThereAgent(
    workspace: $workspace,
    user: $user,
    contextTicket: $agentChat->contextTicket,
    conversationHistory: $agentChat->getConversationHistoryExcludingLatest(),
);

return $this->streamingService->stream($agent, $messageForAi, $agentChat);

Агента передають у streaming-сервіс, який перетворює потік відповіді SDK на події, зрозумілі фронтенду. Про це автор обіцяє окремий допис.

Підсумок

За словами автора, Laravel AI SDK ідеально підійшов для їхнього сценарію: абстракції агента й інструментів прості, промпт на основі Blade приємно редагувати, а типізована схема означає, що модель рідко плутає аргументи. Вони лише торкнулися поверхні можливостей SDK.

Детальніше про SDK можна дізнатися в репозиторії Laravel AI SDK, а спробувати There There - подавши заявку на ранній доступ до закритої бети на there-there.app.

9

Читати в документації

Коментарі

Увійдіть, щоб залишити коментар

Будьте першим, хто залишить коментар!

Читайте також

CSRF і завантаження
Новини 09 жовтня 2026

Порада з безпеки: як завантаження файлів може обійти захист від CSRF

Стівен Ріс-Картер пояснює, чому файли користувачів варто віддавати з окремого домену: HTML і JS у межах основного застосунку дають доступ до cookie та CSRF-токенів.

18
Порядок middleware
Новини 07 жовтня 2026

Порядок авторизації та прив’язки моделей у Laravel: чому замість 403 приходить 404

Чому користувач без прав отримує 404 замість 403 на маршрутах із route model binding, як це пов’язано з пріоритетом middleware SubstituteBindings та Authorize і як це виправити за допомогою PermissionMiddleware.

17

Вакансії за темою

Optimizee Group
29 днів тому

Product Lead (Strategy + Full Stack)

Product Lead з відповідальністю за розробку та лідерство. Гібридна роль: 60% управління продуктом (дорожна карта, пріоритизація, аналітика) та 40% full stack розробки на PHP Laravel. Потрібен досвід розробника (5+ років), знання бекенду, баз даних, здатність приймати продуктові рішення та керувати командою. Основний стек: PHP 8.2+, Laravel 12, MySQL, Redis, Alpine.js, Livewire.

N-iX Нова
2 дні тому

Senior/ Lead PHP Engineer (with AI Skills) (#5828)

Розробка та підтримка backend-сервісів і API на PHP та Laravel з повним циклом володіння фічами від дизайну до моніторингу. Ключове завдання - інтеграція агентних AI-workflow (LLM-агенти, tool calling) у продукт і внутрішні інструменти, а також менторство інших інженерів. Вимоги: 6+ років PHP, 4+ роки з Laravel, досвід GenAI, знання MySQL/PostgreSQL, Docker та хмарних платформ, робота за часовим поясом EDT.

N-iX
11 днів тому

Senior / Lead PHP Engineer with AI skills

Senior/Lead PHP Engineer з досвідом у Laravel та GenAI. Займатиметесь розробкою backend-сервісів і API, інтеграцією агентних AI-систем (LLM, tool-calling, autonomous workflows), оптимізацією продуктивності й надійності. Потребує 6+ років досвіду PHP, 4+ років Laravel, hands-on роботи з LLM API та агентами. Основний стек: PHP, Laravel, MySQL/PostgreSQL, Docker, AWS/GCP. Керівництво та ментор інших інженерів.

Пакети за темою

Laravel Blade Javascript

spatie/laravel-blade-javascript

Blade-директива для експорту змінних у JavaScript.

619 2.9.0 13 4

Bagisto

bagisto/bagisto

Bagisto — це платформа для електронної комерції, побудована на Laravel. Вона надає готове рішення для створення та управління інтернет-магазинами з підтримкою каталогу товарів, замовлень, платежів та клієнтів.

28,224 v2.5.0 13 26