Concepts

AI assistant model

The in-app assistant is App\Ai\Agents\AppAssistant: a conversational, tool-using agent (laravel/ai) whose tool list is filtered by the user’s effective permissions. Chat history, attachments, imports, and sync sources sit around that agent.

Related

AppAssistant

ItemDetail
ClassApp\Ai\Agents\AppAssistant
Pathapp/Ai/Agents/AppAssistant.php
ContractsAgent, Conversational, HasTools
Provider attribute#[Provider('local')]
TraitsPromptable, RemembersConversations
StepsmaxSteps() = count(FieldTypeEnum::cases()) + 16
Timeout300 seconds
EntryAiChatControllernew AppAssistant($user)
Route gatepermission:can-use-ai on routes/ai.php

Tools are registered in AppAssistant::tools() only when the user holds the required permission(s) via EffectivePermissionResolver. Each tool then re-checks action-level permissions through ChecksAiPermissions::requirePermission().

Language policy

  • The assistant replies in the same language as the user’s latest message. If it cannot confidently use that language, it uses English. It must never assume Italian.
  • Tool errors, fallback turn summaries, and AI HTTP messages are English machine strings; the model translates them for the user.
  • Prompt chips / AI UI chrome in resources/js ship English literals (admin UI i18n elsewhere is unchanged).

Field-type knowledge (no MCP yet)

PieceDetail
CookbookApp\Ai\Support\FieldTypeCookbook — curated purpose / required keys / settings_json examples / nested rules (aligned with Field types + BlocksFieldSchema)
ToolDescribeFieldTypes — input types = list, all, or complex
GateRegistered with collection tools; needs show/create/edit collections
Prompt ruleBefore create_field / update_field on complex types, MUST call DescribeFieldTypes; treat ManageCollections get as source of truth for existing schema
Validationcreate_field / update_field run CollectionFieldSettingsPipeline (same normalize + rules as HTTP Store/Update field)
MCPai.mcp.enabled stays off — custom tools are the knowledge plane for now

Permission-gated tools

Registration (tool available in the agent)

Tool classRegistered when the user has
ManageCollectionsAny of: show / create / edit / delete / restore / force-delete collections
ManageCollectionItemsSame collection permission set
DescribeFieldTypesSame collection permission set (action also accepts show or create or edit)
QueryCollectionItemscan-show-collections
ExportCollectioncan-show-collections
SearchSimilarCollectionItemscan-show-collections
ImportCollectionCsvcan-create-collections
ImportRemoteJsoncan-create-collections
ExtractPdfTextcan-create-collections
GetImportJobStatuscan-create-collections
ManageAiSyncSourcescan-create-collections
RollbackLastAiTurncan-delete-collections
ManageFilesAny of: show / create / edit / delete / restore / force-delete files
ManageUsersAny of: show / create / edit / delete / restore / force-delete users
ManageRolesAny of: show / create / edit / delete roles
ManageGroupsAny of: show / create / edit / delete / restore / force-delete groups
QueryActivityLogscan-show-activity-logs

Paths: app/Ai/Tools/{ToolName}.php.

Action-level gates (high level)

ManageCollections

ActionsPermission
list, get, list_field_packscan-show-collections
create, duplicatecan-create-collections
update, create_field, update_field, delete_field, apply_field_packcan-edit-collections
deletecan-delete-collections
restorecan-restore-collections
force_deletecan-force-delete-collections

Collection packs: for SEO entity / Articles / Pages / Products / Categories, the assistant MUST call apply_collection_pack (pack, e.g. seo or articles). Dependencies auto-create. UI: Collections Create from pack…. Presets: “Apply SEO collection”, “Scaffold Articles”, “Scaffold Products”.

Field packs: for denormalized SEO (seo_inline) or publishing/contact/social on an existing collection, MUST call apply_field_pack (collection_id + pack). Use seo_inline only when the user wants inline seo_* fields. UI: Fields page Add field pack…. Registry: Field types — Field packs.

ManageCollectionItems

ActionsPermission
list, get, list_relation_optionscan-show-collections
createcan-create-collections
update, bulk_updatecan-edit-collections
delete, bulk_deletecan-delete-collections
restorecan-restore-collections
force_deletecan-force-delete-collections

Single-permission tools

ToolPermission
QueryCollectionItemscan-show-collections
ExportCollectioncan-show-collections
SearchSimilarCollectionItemscan-show-collections
ImportCollectionCsvcan-create-collections
ImportRemoteJsoncan-create-collections
ExtractPdfTextcan-create-collections
GetImportJobStatuscan-create-collections
RollbackLastAiTurncan-delete-collections
QueryActivityLogscan-show-activity-logs

ManageAiSyncSources

ActionsPermission
list, createcan-create-collections
update, enable, disable, deletecan-edit-collections

ManageFiles

ActionsPermission
list, searchcan-show-files
create / create_folder, save_attachmentcan-create-files
rename, move, move_manycan-edit-files
deletecan-delete-files
restorecan-restore-files
force_deletecan-force-delete-files

ManageUsers / ManageGroups — show / create / edit / delete / restore / force-delete mapped to the matching can-*-users or can-*-groups permissions.

ManageRoleslist/getcan-show-roles; create / duplicatecan-create-roles (+ show for duplicate); update / delete → edit/delete roles; list_permissionscan-show-permissions or create/edit roles. Duplicate clones Spatie permissions and collection/file matrices into a new named role (no user/group memberships). Cannot duplicate super-admin or locked system roles (same as the UI).

Same gates as HTTP

Collections HTTP routes use Spatie permission:can-*-collections (and FormRequest checks on bulk). The assistant re-checks the same permission names per tool action, plus CollectionPermissionEnforcer for item ACL / item_filter. See Effective permissions · Collections API.

Conversations

Configured under config/ai.phpai.conversations:

KeyValue
Tablesagent_conversations, agent_conversation_messages
generate_titlefalse (title derived from the first prompt without an extra LM call)

Controllers: AiConversationController, AiPageController. Routes cover list/create/update/destroy, pin, truncate, bulk-destroy, and deep-link GET /ai/{conversation}.

Attachments

PieceDetail
ModelApp\Models\AiChatAttachment
Disklocal (AiChatAttachment::DISK)
Max size5 MiB
TTL24 hours
Extensionscsv, txt, xlsx, pdf
Upload routePOST /ai/attachments (throttle 30/min)
Chat usageUp to 5 attachment_ids on POST /ai/chat
Cleanupai:cleanup-attachments (daily schedule)

Daily prompt limit

ConfigEnvDefault
ai.daily_prompt_limitAI_DAILY_PROMPT_LIMIT0 (disabled)

When the limit is greater than 0, AiChatController counts today’s Spatie activity rows (log_name = ai, event = ai_prompt, causer = user). At or above the limit the chat endpoint returns 429 with message Daily AI prompt limit reached.

ConfigEnvDefault
ai.embeddings.enabledAI_EMBEDDINGS_ENABLEDfalse

SearchSimilarCollectionItems (can-show-collections) respects the flag:

ModeWhenResponse mode
EmbeddingsFlag true, query embedding succeeds, and stored CollectionItemEmbedding rows exist for the collection"embeddings"
Semantic-liteFlag false, provider failure, or no stored vectors yet"semantic-lite"

Embeddings path: generate a query vector via Laravel AI Embeddings, score stored vectors (cosine over JSON float arrays; pgvector later), return scored items. Item saves queue GenerateCollectionItemEmbeddingJob. If the collection has zero stored embeddings, the tool dispatches generation for up to 50 recent items and falls back this request.

Semantic-lite path: load up to 500 recent items (permission-filtered), case-insensitive str_contains over lowercased JSON of assembled field values.

Tool description text also switches when the flag is on. Config details: AI configuration — Embeddings.

MCP flag

ConfigEnvDefault
ai.mcp.enabledAI_MCP_ENABLEDfalse

Referenced as an opt-in placeholder in AppAssistant::tools() comments. There is no active MCP wiring until laravel/ai exposes stable agent MCP integration. Leaving the flag false is correct for production today.

Surrounding jobs and schedule

PieceRole
ImportCollectionJobCSV / Excel / remote JSON imports; status in cache
ai:run-sync-sourcesEvery minute — due AiSyncSource rows enqueue imports
ai:cleanup-attachmentsDaily — purge expired chat attachments
WebhookPOST /ai/webhooks/collection-import (HMAC-signed, CSRF-excepted)
Previous
File tree model