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 / update / delete → create/edit/delete roles; list_permissionscan-show-permissions or create/edit roles.

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

Similarity is still a text scan

SearchSimilarCollectionItems does not read ai.embeddings.enabled. It always runs a semantic-lite pass: load up to 500 recent items, case-insensitive str_contains over the lowercased JSON of assembled field values, and return "mode": "semantic-lite". The embeddings flag is config-ready for a future vector provider; it does not change similarity behavior today.

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 (token-gated, CSRF-excepted)
Previous
File tree model