Configuration
Publish the config first:
php artisan vendor:publish --tag=laravel-iam-ai-config
This writes config/iam-ai.php. The defaults are sovereign and off.
Keys
| Key | Env | Default | Meaning |
|---|---|---|---|
enabled |
IAM_AI_ENABLED |
false |
Master switch. While false, the DisabledProvider is used and you get deterministic answers only. |
provider |
IAM_AI_PROVIDER |
disabled |
disabled | regolo (EU, OpenAI-compatible) | ollama (on-prem). Both transports ship with the package. |
model |
IAM_AI_MODEL |
null |
Model name passed to the chosen provider. |
base_url |
IAM_AI_BASE_URL |
null |
Provider endpoint (e.g. https://api.regolo.ai/v1 or http://localhost:11434). Required to enable a real provider. |
api_key |
IAM_AI_API_KEY |
null |
Bearer key — required for regolo, optional for ollama (gateway). |
timeout |
IAM_AI_TIMEOUT |
20 |
HTTP timeout (seconds) for the provider call. |
redaction |
— | true |
The PRE-prompt redaction pipeline. Mandatory; leave it on. |
store_prompts |
— | false |
Never persist prompts (possible PII/secrets). Hard default — no env override. |
store_outputs |
IAM_AI_STORE_OUTPUTS |
false |
Opt-in: store the sanitized output in the audit trail. |
max_context_events |
— | 50 |
Cap on past events passed as model context. |
The shipped file:
return [
'enabled' => env('IAM_AI_ENABLED', false),
// 'disabled' (default) | 'regolo' | 'ollama' — real providers are optional adapters.
'provider' => env('IAM_AI_PROVIDER', 'disabled'),
'model' => env('IAM_AI_MODEL'),
'redaction' => true, // mandatory pre-prompt redaction
'store_prompts' => false, // never persist prompts (possible PII/secrets)
'store_outputs' => env('IAM_AI_STORE_OUTPUTS', false), // opt-in: sanitized output in audit
'max_context_events' => 50, // cap on past events passed as context
];
Enabling a sovereign provider
The recommended providers are sovereign: Regolo (Italian/EU) or Ollama (on-prem). The core never wires
a non-sovereign provider as a default, and pulls in no AI SDK via require.
Both regolo and ollama transports ship with the package — just configure one via env. No extra
Composer package, no rebinding.
IAM_AI_ENABLED=true
IAM_AI_PROVIDER=regolo
IAM_AI_BASE_URL=https://api.regolo.ai/v1
IAM_AI_API_KEY=your-regolo-api-key
IAM_AI_MODEL=your-model
IAM_AI_TIMEOUT=20
OpenAI-compatible /chat/completions, Bearer auth, temperature pinned to 0.
IAM_AI_ENABLED=true
IAM_AI_PROVIDER=ollama
IAM_AI_BASE_URL=http://localhost:11434
IAM_AI_MODEL=llama3.1
# IAM_AI_API_KEY=... # only if Ollama is behind an authenticating gateway
Non-streaming /api/chat against your own infrastructure — data never leaves the perimeter.
IAM_AI_ENABLED=true
IAM_AI_PROVIDER=my-sovereign
IAM_AI_MODEL=your-model
Implement AiProvider and rebind it — see Write a sovereign provider.
If a real provider is selected but its transport isn’t fully configured (e.g. regolo with no api_key),
the binding falls back to DisabledProvider — never a misconfigured network call. Redaction and the
hallucination-guard remain active regardless of provider, and any transport error falls back to the
deterministic text.
How the provider is resolved
The module’s own provider currently matches every value to DisabledProvider; a real transport comes from an
adapter package that rebinds AiProvider from its own service provider. Setting provider without
installing such an adapter leaves you on the inert default.
Audit & privacy keys in practice
store_prompts=falseis a hard default — prompts are never written, full stop.store_outputs=truepersists only the redacted output, and only if you opt in.- Every AI action is audited under
stream=ai/iam.ai.advisorywith the governance flags regardless of
these toggles. → Audit & privacy
Gotchas
enabled=truewithout an adapter ⇒ deterministic answers. The binding stays onDisabledProvider(its
complete()throws → fallback). CheckAdvisory::$aiUsed/$provider.max_context_eventstruncates. Modules that pass history (e.g. review summaries) only see the first N —
order signals by relevance.- Don’t try to disable
redaction. The flag defaults totrueand the client redacts unconditionally; it
is not a performance toggle.