Skip to content

AI policies

An AI policy is the set of AI controls one scope sets for itself: which models and modalities may run, whether the Layer agent and each subagent may run, the spend above which the agent asks before a job, and the parameter values a generation on a model starts from. The AI Policies endpoints let a workspace’s admins read and change them from a script, the same as Settings > AI Controls in the app. The same operations are on the management MCP server.

A policy is attached to one scope, and holds only what that scope sets itself. Everything else is inherited from the less specific scopes, in this order:

  1. the workspace (and, for a workspace under another, the workspaces above it)
  2. a project in it, for work done in that project
  3. the groups the member belongs to
  4. the member: a user, service account or API key

The most specific scope that sets a value wins. Where a member’s groups disagree, the most permissive value wins: belonging to a stricter group never takes away what another group grants. Model defaults are the exception: groups that disagree on a default cancel out, and the member inherits it from the less specific scopes.

A workspace or project can lock a value. A locked value holds for every scope below the one that set it, which cannot override it. Group and member policies cannot lock.

Every value is a setting, { "value": …, "locked": false }. Maps hold one setting per key, so each model, modality or subagent is inherited, overridden and locked on its own.

Control Value What it does
agent_enabled boolean The Layer agent as a whole.
agents map of principal id to boolean Each subagent, by the principal it acts as.
agent_confirm_above_cu number The Creative Units above which the agent asks before running a job.
modalities map of modality to boolean IMAGE, VIDEO, THREE_D, AUDIO, TEXT on or off.
new_models_enabled boolean Whether a model models does not name may run: true makes models a deny list, false an allow list.
models map of base model id to boolean Each base model on or off.
model_defaults map of base model id to a map of parameter to value The parameter values a generation on the model starts from.
nsfw_tolerance 1 to 6 How much NSFW content generations may produce: 1 is the strictest. Workspaces and projects only.
reference_set_sharing_enabled boolean Whether the workspace’s reference sets may be shared beyond it. Workspaces only.
workflow_sharing_enabled boolean Whether the workspace’s workflows may be shared beyond it. Workspaces only.

Three more controls appear in reads and are kept when a policy is replaced or cleared:

Control Value What it does
usage_caps map of daily, weekly or monthly to {cu_limit, mode, warn_threshold_pct} The Creative Units each member may spend in the workspace per period. mode is warn or block; a null value lifts a cap set above. Set it with a patch, which takes the billing admin permission as well; a group’s cap can also be set with the group usage-limit endpoints.
guardrails map of rule id to boolean Input guardrail rules, written by their own feature. A patch that names it is refused.
output_scoring map of rule id to boolean Output scoring rules, written by their own feature. A patch that names it is refused.

Each scope has its policy at its own path:

Scope Path
Workspace /v2/workspaces/{workspace_id}/ai-policy
Project /v2/workspaces/{workspace_id}/projects/{project_id}/ai-policy
Group /v2/workspaces/{workspace_id}/groups/{group_id}/ai-policy
Member /v2/workspaces/{workspace_id}/members/{principal_id}/ai-policy
Terminal window
curl https://api.app.layer.ai/api/v2/workspaces/$WORKSPACE_ID/groups/$GROUP_ID/ai-policy \
-H "Authorization: Bearer $LAYER_TOKEN"

The response holds the policy the scope sets itself and what it inherited from the less specific scopes, each inherited value with the source scope that set it and whether that scope locked it. A value with no source is the platform default. A scope that sets nothing returns an empty policy.

  1. Patch to change only what you name. The body is a JSON merge patch of the policy: a control or key you name is set, one you name as null is removed so the scope inherits it again, and anything you leave out stays as it is. A setting is replaced whole, value and lock.

    Terminal window
    curl -X PATCH https://api.app.layer.ai/api/v2/workspaces/$WORKSPACE_ID/ai-policy \
    -H "Authorization: Bearer $LAYER_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
    "models": { "flux-2-pro": { "value": false, "locked": true }, "flux-2-dev": null },
    "model_defaults": { "flux-2-dev": { "inference_steps": { "value": 30 } } }
    }'

    This turns FLUX.2 Pro off for the whole workspace and locks it, returns FLUX.2 Dev to what the workspace inherits, and starts every FLUX.2 Dev generation at 30 steps, leaving every other control alone. Patches to one scope apply one after another, so two admins changing different models never undo each other.

    A member’s monthly cap is raised the same way:

    Terminal window
    curl -X PATCH https://api.app.layer.ai/api/v2/workspaces/$WORKSPACE_ID/members/$PRINCIPAL_ID/ai-policy \
    -H "Authorization: Bearer $LAYER_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{ "usage_caps": { "monthly": { "value": { "cu_limit": 1000, "mode": "block", "warn_threshold_pct": 80 } } } }'
  2. Replace with PUT to set the whole policy at once. Anything the body leaves out is inherited, except guardrails, output scoring and usage caps, which are kept. Read the policy first and send it back with your change, or prefer a patch.

  3. Clear with DELETE to remove every control the scope sets, so it inherits them. Guardrails, output scoring and usage caps are kept. It answers 204.

A patch or replacement that sets nothing removes the policy, as a clear does. A patch that changes nothing writes nothing.

GET /v2/workspaces/{workspace_id}/ai-policies lists every policy stored in the workspace, oldest first, each with its scope, its policy, and when and by whom it was last written. Filter by scope with kind=workspace, project, group or member, and page with cursor as on the other list endpoints.

GET /v2/workspaces/{workspace_id}/effective-ai-policy resolves every scope’s policy into the controls in force for a member’s work, each value with the scope that set it. Name a project_id for work in a project, and a principal_id for another member; without one it resolves for the caller.

Terminal window
curl "https://api.app.layer.ai/api/v2/workspaces/$WORKSPACE_ID/effective-ai-policy?project_id=$PROJECT_ID" \
-H "Authorization: Bearer $LAYER_TOKEN"

The maps hold only what some policy names. A model, modality or subagent they leave out takes the platform default: allowed, unless new_models_enabled is false, in which case a model only runs when models turns it on.

Reading or changing a policy takes the role that edits it in the app: the settings admin permission in the workspace, or for a project’s policy, the permission to edit its content policy. The list endpoint takes settings admin. Any member may read the policy in force for their own work; reading another member’s takes settings admin.

An access token needs the workspace:read scope to read and workspace:write to change a policy.

Status Code When
402 AI_POLICY_REQUIRES_ENTERPRISE A control the scope can only set on the Enterprise plan.
404 AI_POLICY_SCOPE_NOT_FOUND The project, group or member is not live in the workspace.
422 AI_POLICY_LOCK_NOT_ALLOWED A group or member policy that locks a setting.
422 AI_POLICY_CONTROL_NOT_AT_SCOPE A control the scope kind cannot set, such as sharing on a project.
422 AI_POLICY_MIRROR_GROUP A group that mirrors another workspace’s group: set the policy on the source group.
422 AI_POLICY_INVALID_MODEL_DEFAULT A parameter the model cannot default, or a value it does not accept.
422 INVALID_LIMIT A usage cap that is not positive, or above 10,000,000 Creative Units.
422 INVALID_WARN_THRESHOLD A usage cap whose warn_threshold_pct is outside 1 to 100.