selli / ticketing
The headless, multi-tenant help-desk engine for Laravel: tickets on any model, workflow, SLA, routing, email & widget channels, AI with human hand-over, knowledge base, KPIs, MCP and RAG.
Fund package maintenance!
Requires
- php: ^8.3
- illuminate/contracts: ^11.0||^12.0||^13.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- directorytree/imapengine: ^1.25
- larastan/larastan: ^3.0
- laravel/mcp: ^1.0
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.8
- orchestra/testbench: ^11.0.0||^10.0.0||^9.0.0
- pestphp/pest: ^4.0
- pestphp/pest-plugin-arch: ^4.0
- pestphp/pest-plugin-laravel: ^4.0
- phpstan/extension-installer: ^1.4
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-phpunit: ^2.0
- sellinnate/rag-engine: ^1.4
Suggests
- directorytree/imapengine: Poll inbound email over IMAP with php artisan ticketing:mail:poll (^1.25).
- laravel/mcp: Expose the help desk to AI agents as MCP tools (Selli\Ticketing\Mcp\TicketingServer; Laravel 12.41+).
- laravel/reverb: Realtime ticket updates over WebSockets (ticketing.broadcasting).
- sellinnate/rag-engine: Semantic knowledge-base search, RAG answers with citations, similar tickets (Selli\Ticketing\Integrations\RagEngine; ^1.4).
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-11 07:46:26 UTC
README
Selli Ticketing
📖 Full documentation: laravel-ticketing.selli.io
The headless, multi-tenant help-desk engine for Laravel. Tickets about anything in your app — an order, a device, a contract, or nothing at all — with the workflow, SLA, routing, channels, AI and reporting a support team needs, and no UI or product decisions imposed on you.
An engine, not an app.
selli/ticketingis the domain layer you build customer support, technical interventions, internal requests or incident management on. The same engine serves a Filament back-office, an Inertia/Vue front-end, a mobile API, a chat widget on a customer's website or an AI agent.
What you can build
- 🎫 A help desk inside your product — tickets attached to your own models, your users as requesters and agents, every tenant isolated.
- 💬 A chat widget on any website that answers with AI from your knowledge base and hands over to a person — the conversation becomes a ticket with its transcript.
- 📧 Email support — by webhook or IMAP, threaded, without quotes, autoresponders or loops.
- 🤖 An AI first line that answers with sources, drafts for agents, classifies, and escalates by rule; agents take over at any moment.
- 📊 Support KPIs — volume, backlog, response and resolution times, SLA, AI share and cost, CSAT, unanswered questions — with streamed CSV exports.
- 🧠 AI agents on your help desk through MCP tools that obey your policies.
Features
| Area | Highlights |
|---|---|
| Core | Tickets on any model (Ticketable), config-driven workflow per type with guards, custom fields, references, listing & filtering (TicketQuery) |
| Operations | SLA on business hours, routing & assignment (round-robin, least-busy, skill-based), collaboration (attachments, mentions, macros, merge/split, tags), automation and webhooks, notifications, CSAT |
| People | Your models as requesters/agents, contacts for people without an account, reopen on requester reply |
| Channels | REST API, email (webhook or IMAP), chat widget with a reference JS client, broadcasting |
| AI | Provider-agnostic AI layer: auto / draft / off per tenant and type, escalation rules, human takeover, usage and cost per turn |
| Knowledge | Knowledge base: articles and FAQs, versions, locales, audiences (public, customer, internal, per client) |
| Insight | KPIs and CSV exports, in the database, at any volume |
| Integrations | MCP tools (laravel/mcp), RAG Engine bridge (sellinnate/rag-engine): semantic search, answers with citations, similar tickets |
| Security | Fail-closed multi-tenancy, policies, immutable audit trail, GDPR erasure / export / retention |
Installation
composer require selli/ticketing php artisan ticketing:install # publishes config + migrations, offers to migrate php artisan ticketing:demo # seeds a working example ticket
Requires PHP 8.3+ and Laravel 11, 12 or 13. Tested on MySQL 8.4, PostgreSQL 16 and SQLite (its SQL avoids vendor-specific constructs, SQL Server included).
Quick start
use Selli\Ticketing\Concerns\HasTickets; use Selli\Ticketing\Contracts\Ticketable; class Order extends Model implements Ticketable { use HasTickets; // tickets() relation + openTicket() helper }
use Selli\Ticketing\Facades\Ticketing; use Selli\Ticketing\Enums\{MessageVisibility, Priority}; $ticket = $order->openTicket(type: 'support', title: 'Missing shipment', requester: $customer, priority: Priority::High); Ticketing::for($ticket)->postMessage($agent, 'Checking with the courier', MessageVisibility::Internal); Ticketing::for($ticket)->postMessage($agent, 'A new parcel leaves today.'); Ticketing::transition($ticket, 'resolve', $agent); $open = Ticketing::tickets()->state('open')->assignedTo($agent)->sort('priority')->paginate(); $kpis = Ticketing::metrics()->between(now()->subMonth(), now())->summary();
Actors are agnostic: implement CanRequestTickets and/or CanActOnTickets on whichever models represent
your requesters and agents (even two different populations such as Customer and Operator).
Multi-tenancy
Every table carries a tenant column, every read goes through a global scope, every write is assigned to the
current tenant, and with no tenant resolved the scope fails closed. Bind your own TenantResolver to
reuse stancl/tenancy, spatie/laravel-multitenancy or your own; act as a tenant in CLI and queues with
TenantContext::forTenant().
AI, with humans in charge
// config/ticketing.php 'ai' => ['enabled' => true, 'driver' => 'rag-engine', 'mode' => 'auto'],
The AI answers customers from what they may read, with sources; it hands over — to the routing rules, then
the escalation team, notifying its leads — when it is unsure, finds nothing, meets a sensitive topic, or the
customer asks for a person. The moment an agent replies, it steps aside for good. Drivers are pluggable:
null, fake for tests, rag-engine, or your own.
Stability
1.x follows semantic versioning: the
public API — facade, actions, contracts, events,
models and tables, config keys, REST routes, commands — never breaks within 1.x; migrations are only ever
added. See UPGRADE.md.
Testing
composer test # Pest (TICKETING_TEST_DB=mysql|pgsql for a real database) composer test-coverage # with the 90 % minimum composer analyse # PHPStan (Larastan) level 8 composer format # Laravel Pint
CI runs PHP 8.3–8.5 × Laravel 11–13 (lowest and stable dependencies) on Linux and Windows, the whole suite on MySQL 8.4 and PostgreSQL 16, coverage, static analysis and the widget client tests.
Changelog, upgrading, contributing
- CHANGELOG — what changed in each release.
- UPGRADE.md — how to move between versions.
- CONTRIBUTING.md — setup and quality gates.
Security
Please report vulnerabilities privately — see SECURITY.md.
Credits
License
The MIT License (MIT). Please see License File for more information.
