Skip to main content

Environment Settings

Environment settings are configuration that applies to a whole environment (one account and environment pair), rather than to a single agent. They are grouped into sections, each identified by a namespace key. Each section is read and replaced as a unit.

Today there is one section, passport, which sets the Agent Passport policy for the environment. More sections may be added later. They will use the same endpoints, permissions and audit event.

Who can use these endpoints

Environment settings are an administrator responsibility. The permissions are granted to the Agent Builder Administrator role.

PermissionAllows
cin-agent-builder.environment-settings.readEvery endpoint that changes nothing: listing sections, reading a section, and the impact preview.
cin-agent-builder.environment-settings.editReplacing a section (PUT).

edit does not include read. A client that reads a section before replacing it needs both.

Endpoints​

MethodPathPermissionDescription
GET/v1/environment-settingsreadList every section, with its current or default value.
GET/v1/environment-settings/{namespace}readGet one section and its ETag.
GET/v1/environment-settings/{namespace}/impactreadPreview what each value would do, before changing it (sections that support it).
PUT/v1/environment-settings/{namespace}editReplace one section. Requires If-Match.

A section that has never been set is returned with its default value, revision: 0 and source: "DEFAULT". A section that has been set has source: "OVERRIDE". Responses are never cached (Cache-Control: no-store).

Reading a section​

GET /v1/environment-settings/passport

Example response:

{
"namespace": "passport",
"properties": {
"passportMode": "REQUIRED_FOR_NEW"
},
"revision": 4,
"source": "OVERRIDE",
"updatedAt": "2026-10-02T14:05:11Z",
"updatedBy": "8c1f0a8e-..."
}

The response carries an ETag header, for example "passport-v2-4". Treat it as opaque and send it back exactly as received when you replace the section. Comparison is strict: a tag the server didn't issue never matches, even if it looks equivalent (for example "passport-v2-04").

Replacing a section​

PUT /v1/environment-settings/passport
If-Match: "passport-v2-4"
Content-Type: application/json

{ "passportMode": "REQUIRED_FOR_ALL" }

If-Match protects against lost updates. If someone else changed the section since you read it, the write is refused with 412 Precondition Failed, and the response's ETag is the current one. Read the section again, check it, and retry with the new ETag.

If-Match: * replaces the section unconditionally, whatever its current revision. It gives up lost-update protection, so use it only for break-glass automation.

The body is the whole section. Fields you leave out are not kept from the old value, and an empty body {} is rejected.

StatusMeaning
200Section replaced. The body's revision is the new revision.
400Invalid body, or a malformed If-Match.
403Caller lacks environment-settings.edit. The body is {"detail": "..."}.
404Unknown namespace.
412If-Match didn't match the current revision.
428If-Match is missing.
503Writes are not yet activated in this deployment, the section is busy, or the database is unavailable. Retry later.

Every successful change is recorded in the audit trail as a cin-agent-builder.environment-settings.updated event. The event records the section's settings before and after the change, the new revision, and who made it. Because every value goes into the audit trail, settings never hold secrets.

Passport policy (passport section)​

The passport section has one setting, passportMode. It decides which agents need an issued Agent Passport before they can be invoked.

passportModeNew agents and versionsExisting agents without a passportAgents with a passport
DISABLED (default)No passport is requested.Invocable.Invocable. Passports are not checked.
REQUIRED_FOR_NEWEach new agent or version requests a passport, and can't be invoked until it is approved.Still invocable (grandfathered).Invocable only while the passport is issued and not expired.
REQUIRED_FOR_ALLAs for REQUIRED_FOR_NEW.Refused until a new version gets an approved passport.Invocable only while the passport is issued and not expired.
"All" means all agents written in your tenant

Global agents (platform-provided agents shared across tenants) are exempt in every mode, including REQUIRED_FOR_ALL. They are never refused for passport reasons. A copy of a global agent made in your tenant is a tenant agent and follows your policy.

Agents that use other agents​

A topology manager's experts and a tool agent's task-agent tools are checked against the same policy when the agent is invoked. If any one of them is refused, the whole invocation is refused, and the error names the agent that caused it.

This applies at every depth: a task agent used as a tool that itself has task-agent tools has those checked too, before anything runs. A chain of task-agent tools that calls back into itself, or that is nested more than 5 deep (by default), is refused with 400.

One invocation may also embed at most 160 task agents in total (by default), counted across the agent and all of its experts, every use of a shared task agent counted separately. For example, an agent whose 5 task agents each use 5 more, which each use 5 more, embeds 5 + 25 + 125 = 155. Their configurations may total at most 8 MiB (a provisional default). Exceeding any of these limits is refused with 400 before anything runs. All three are deployment settings, so your platform operator may have set different values. These limits apply whatever the passport mode.

References to other agents are pinned to a specific version when the agent is saved. To choose the version a task-agent tool runs, send its agentVersionId. If you omit it, the version in the deprecated agentVersion is used, or the current version when that is latest or absent; either way the saved agent returns the resolved agentVersionId. Sending agentVersionId and an agentVersion UUID that name different versions is rejected with 400.

An agent saved before pinning existed may still reference another agent by latest. Under REQUIRED_FOR_NEW or REQUIRED_FOR_ALL, such an agent is refused with PASSPORT_REFERENCE_UNPINNED. Save a new version of it to pin its references.

Refusals​

A refused invocation returns 403 with a machine-readable errorCode:

{
"status": 403,
"error": "Forbidden",
"message": "This environment requires an Agent Passport for every agent, and this agent has none. Create a new version to request one.",
"errorCode": "PASSPORT_REQUIRED"
}
errorCodeMeaningWhat to do
PASSPORT_REQUIREDREQUIRED_FOR_ALL, and the agent has never had a passport.Create a new version, then have it approved.
PASSPORT_NOT_PROVISIONEDThis version has no passport, but the agent has one on another version.Create a new version, then have it approved.
PASSPORT_PENDING_APPROVALThe passport is waiting for approval.Ask a Governance Officer to approve it.
PASSPORT_ISSUANCE_FAILEDThe version was approved, but its passport could not be issued.Retry the approval.
PASSPORT_REJECTEDThe passport was rejected.Address the reason for the rejection, then create a new version.
PASSPORT_REVOKEDThe passport was revoked.Create a new version, then have it approved.
PASSPORT_SUSPENDEDThe passport is suspended.Ask a Governance Officer to unsuspend it.
PASSPORT_EXPIREDThe passport's expiry date has passed.Have it approved again.
PASSPORT_REFERENCE_UNPINNEDThe agent references another agent by latest.Save a new version of the agent.

Treat any 403 from an invocation endpoint as a refusal, even if it has an errorCode you don't recognize. New codes may be added. A 403 because the caller lacks a permission has a different body, {"detail": "..."}, with no errorCode.

Previewing a change​

Before changing the mode, check what it would do:

GET /v1/environment-settings/passport/impact

Example response:

{
"observedAt": "2026-10-02T14:10:00Z",
"settingsRevision": 4,
"settingsEtag": "\"passport-v2-4\"",
"configuredMode": "REQUIRED_FOR_NEW",
"effective": true,
"effectiveMode": "REQUIRED_FOR_NEW",
"tenantAgentCount": 42,
"breakdown": {
"PASSPORT_REQUIRED": 30,
"PASSPORT_PENDING_APPROVAL": 2
},
"refusedUnder": {
"DISABLED": 0,
"REQUIRED_FOR_NEW": 2,
"REQUIRED_FOR_ALL": 32
},
"currentlyRefusedCount": 2,
"transitions": {
"DISABLED": { "newlyRefused": 0, "readmitted": 2 },
"REQUIRED_FOR_NEW": { "newlyRefused": 0, "readmitted": 0 },
"REQUIRED_FOR_ALL": { "newlyRefused": 30, "readmitted": 0 }
}
}

(breakdown lists every refusal code; the zero counts are left out above.)

FieldMeaning
tenantAgentCountYour tenant's agents. Global agents are not counted, because they are exempt.
breakdownHow many agents would be refused, by refusal code.
refusedUnderHow many agents each mode would refuse.
transitionsFor each mode: how many agents switching to it would newly refuse or newly allow, compared with today.
effectivefalse when Agent Passport isn't enabled in this deployment. The mode is stored but not enforced, and effectiveMode is DISABLED.
settingsEtagSend this as If-Match on the PUT. The write then fails with 412 if the section changed after the preview.

The preview is a snapshot. Agents can change between the preview and your PUT. It counts each agent on its own: a manager whose expert is refused shows as allowed, but its invocations are refused.

  1. GET /v1/environment-settings/passport/impact and review transitions for the target mode.
  2. PUT /v1/environment-settings/passport with the new mode and If-Match set to settingsEtag from step 1.
  3. On 412, someone else changed the section: start again from step 1.

Moving from REQUIRED_FOR_NEW to REQUIRED_FOR_ALL immediately refuses every tenant agent that has never had a passport (PASSPORT_REQUIRED). Plan that change with the agents' owners.