Performance - v1.1.0
AI Reference
Programmatic surface of the two AI features introduced in 1.1.0. For a walkthrough that shows how to wire them into an application, see the guides/ai-features guide.
Agents
Both agents extend ArtisanPackUI\Ai\Agents\ArtisanPackAgent and are self-registered against artisanpack-ui/ai through PerformanceServiceProvider::aiFeatures().
PerformanceInsightAgent
Namespace: ArtisanPackUI\Performance\Ai\Agents\PerformanceInsightAgent
| Field | Value |
|---|---|
featureKey |
performance.query_insight |
package |
artisanpack-ui/performance |
defaultModel |
claude-sonnet-4-6 |
cacheable |
false — outputs are point-in-time diagnostic snapshots. |
Input:
[
'query' => string (required),
'explain' => array | string | null,
'schema' => array | string | null,
'time_ms' => int | float | null,
'connection' => string | null,
]
Output:
{
summary: string,
bottlenecks: string[],
suggested_indexes: [ { table: string, columns: string[], rationale: string } ],
rewrites: [ { original: string, suggested: string, rationale: string } ],
caveats: string[]
}
Rows returned by the model that are missing a table / columns / original / suggested field are dropped silently by validateOutput() — the final payload always matches the shape above.
OptimizationSuggestionAgent
Namespace: ArtisanPackUI\Performance\Ai\Agents\OptimizationSuggestionAgent
| Field | Value |
|---|---|
featureKey |
performance.optimization_suggestion |
package |
artisanpack-ui/performance |
defaultModel |
claude-sonnet-4-6 |
cacheable |
false — outputs reflect the current metrics window. |
Input:
[
'range' => [ 'from' => 'YYYY-MM-DD', 'to' => 'YYYY-MM-DD' ],
'metrics' => array<int, array<string, mixed>>,
'context' => [
'business_priority' => string | null,
'recent_changes' => string | null,
'traffic_mix' => string | null,
],
]
Output:
{
summary: string,
focus_areas: [
{
title: string,
routes: string[],
impact: 'high' | 'medium' | 'low',
effort: 'high' | 'medium' | 'low',
rationale: string,
actions: string[]
}
],
quick_wins: string[],
caveats: string[]
}
Impact / effort values outside the enumerated set are clamped to medium. An empty metrics list short-circuits without calling the provider.
HTTP endpoints
Wired by PerformanceServiceProvider::registerRoutes() from routes/api-ai.php under the ai_middleware config (default ['api', 'auth:sanctum']).
| Method | Path | Controller method |
|---|---|---|
| POST | /api/performance/ai/query-insight |
AiAgentApiController::queryInsight |
| POST | /api/performance/ai/optimization-suggestion |
AiAgentApiController::optimizationSuggestion |
Success envelope: { data: <agent output>, feature_key: string }.
Error status codes:
| Status | Meaning |
|---|---|
| 403 | The performance.ai.use Gate denied the caller. |
| 404 | Unknown feature key (should never happen against the shipped endpoints). |
| 409 | Feature toggle is off in the registry. |
| 412 | artisanpack-ui/ai cannot resolve credentials. |
| 422 | Form-request validation failed, or the agent raised FeatureError. |
| 500 | Unexpected error; the exception is report()ed before the response is sent. |
The controller uses a static AGENTS map keyed by feature key rather than reflecting through the registry so a caller cannot execute an arbitrary agent class by naming it in the request body.
Configuration
config/performance.php:
'routes' => [
// …
// Middleware for the AI JSON API endpoints. These dispatch to paid LLM
// providers, so the shipped default gates them behind Sanctum plus the
// performance.ai.use Gate.
'ai_middleware' => [ 'api', 'auth:sanctum' ],
],
config/artisanpack/ai.php (from artisanpack-ui/ai):
'features' => [
'performance.query_insight' => [ 'enabled' => true ],
'performance.optimization_suggestion' => [ 'enabled' => true ],
],
Authorization Gate
PerformanceServiceProvider::registerAiGate() defines a default performance.ai.use Gate that allows any authenticated user:
Gate::define( 'performance.ai.use', static function ( $user = null ): bool {
return null !== $user;
} );
Registration is guarded so a host-registered override (defined before boot) wins. The controller's dispatchAgent() method also checks the Gate belt-and-braces, so even if the AI route middleware is loosened, unauthorized callers still receive a 403.
Livewire panels
Two Livewire components ship as trigger UIs for the agents. See api/livewire for the full component reference.
perf-ai-query-insight-panel(ArtisanPackUI\Performance\Livewire\Ai\QueryInsightPanel)perf-ai-optimization-suggestion-panel(ArtisanPackUI\Performance\Livewire\Ai\OptimizationSuggestionPanel)
JavaScript client
Two methods on PerformanceClient cover the endpoints; see api/javascript for the full client reference.
suggestQueryInsight(input)suggestOptimization(input)
Both throw PerformanceAiError on non-2xx responses and on malformed 2xx bodies (empty response, non-JSON payload, missing data key).