Agent policy
Turn the Agent on or off for the server and set per-tenant limits on models, message rate and the lookups it may use.
The Agent is the chat assistant in the dashboard. Operators decide whether it runs at all; tenant administrators set a policy that limits how it is used in their tenant. This page covers both.
Server settings
| Key | Default | Purpose |
|---|---|---|
agent.enabled |
true |
Turns the Agent on. When false, every /api/v1/agent/* endpoint answers 501 and the dashboard shows "The agent chat assistant is not enabled on this server." |
agent.defaultConversationTitle |
New conversation |
Title for conversations started without one. |
agent.maxMessageBytes |
65536 |
Largest message a user can send, in bytes. Longer messages are rejected with 400. |
agent.billing.centsPer1kTokens |
2 |
Price for turns on operator-provided models. Has no effect yet (see Spend cap). |
Override them with environment variables named after the key, for example LAHIJAN_AGENT_ENABLED=false. See Configuration.
Users bring their own model-provider keys. Lahijan encrypts each key with auth.secrets.encryptionKey (a base64-encoded 32-byte key) before storing it. Outside the dev environment, if that key is empty or invalid, saving a provider fails with an internal error. In dev an insecure built-in key is used instead.
The Agent calls the provider's API from the Lahijan server, so the server needs outbound network access to the providers your users choose, or to the local model server they point at.
Who can change the policy
The policy belongs to a tenant. Changing it needs agent.policy.manage, held by tenant.owner, tenant.admin and platform.admin. Anyone who can read Agent conversations (every tenant role) can read the policy, so members see the limits that apply to them.
In the dashboard the page is Administration > Agent Policy. The Administration section of the sidebar is only shown to platform administrators; tenant owners and administrators can open the same page directly at /admin/agent.
The policy fields
| Dashboard field | API field | Default | Effect |
|---|---|---|---|
| Allowed models | allowModels |
empty | Models users may run. Empty allows all. |
| Max messages per window | maxMessagesPerWindow |
0 |
Messages each user may send per window. 0 means unlimited. |
| Window seconds | windowSeconds |
60 |
Length of the sliding window, in seconds. |
| Spend cap (credits) | spendCapCredits |
0 |
See Spend cap. |
| Denied tools | denyTools |
empty | Lookups the Agent may not use. |
| Force admin-provided models (disable user keys) | forceAdminModels |
off | Disables users' own keys. |
Until someone saves a policy, the tenant uses these defaults.
Allowed models
Enter model names separated by commas. Matching ignores case. A name ending in * matches every model that starts with the rest, so gpt-4o* allows gpt-4o and gpt-4o-mini. Any other name must match exactly; other wildcard patterns are not supported.
When a user sends a message, the Agent picks the first of their provider configurations whose model is on the list. If none matches, the Agent replies that no model provider is configured. A configuration saved without a model name never matches a non-empty list, so ask users to fill in Model when you use an allowlist.
Message rate
The limit is per user. Lahijan counts the messages the user sent in the last windowSeconds seconds; once the count reaches maxMessagesPerWindow, new messages are refused with 429 until older ones fall out of the window.
Denied tools
Enter tool names separated by commas; matching is exact and ignores case. A denied tool is not offered to the model, and if the model asks for it anyway the call is refused. The tools available today are all read-only:
| Tool | Reads |
|---|---|
compute.list_instances |
Instances in the tenant |
dns.list_zones |
DNS zones in the tenant |
storage.list_buckets |
Buckets in the tenant |
billing.list_usage |
The user's own usage records |
audit.list_events |
Recent audit events in the tenant |
Each tool is also checked against the user's own permissions when it runs, so denying a tool is only needed when you want to keep that data away from the model provider entirely.
Force admin-provided models
This switch turns off users' own provider keys so that only operator-provided models can be used. Operator-provided models are not available in this release, so turning it on stops the Agent from answering anyone in the tenant: sending a message fails with 403.
Spend cap
The spend cap applies only to turns on operator-provided models, which would be charged to the user's balance. Turns on a user's own key are never charged. Since operator-provided models do not exist yet, the spend cap currently has no effect.
Set the policy with the API
PUT /api/v1/agent/policy replaces the whole policy, so send every field:
curl -X PUT https://cloud.example.com/api/v1/agent/policy \ -H "Authorization: Bearer $LAHIJAN_TOKEN" \ -H "X-Tenant-Id: $LAHIJAN_TENANT_ID" \ -H "Content-Type: application/json" \ -d '{ "allowModels": ["gpt-4o*", "llama3*"], "forceAdminModels": false, "maxMessagesPerWindow": 30, "windowSeconds": 3600, "spendCapCredits": 0, "denyTools": ["audit.list_events"] }'A windowSeconds of 0 or less is stored as 60. GET /api/v1/agent/policy returns the current policy, or the defaults if none was saved.
Each change is written to the audit log as agent.policy.update, with the new force-admin-models and denied-tools values. Like other Agent events, it is stored without a tenant and does not appear on the tenant Audit Log page in this release.