Passer au contenu principal
Afficher en Markdown

Kiro Governance Language (KGL) reference

KGL (Kiro Governance Language) is the YAML format of a Kiro Enterprise Management policy. This page is for administrators who edit a policy in the YAML view of the console's Controls page, with the AWS CLI, or with the API. Kiro Enterprise Management is in preview for new Kiro profiles created in US East (N. Virginia) (us-east-1). It is on for all newly created profiles there; existing profiles are not affected by this change. The console's Capability catalog and Settings catalog, in the info pane of the Controls page, list the same capabilities and settings with their descriptions and shipped defaults. Which capabilities each client enforces is listed in Enforcement status. To publish a policy, follow Get started with Enterprise Management.

Grammar at a glance

The whole language in one block. Every field, every capability, and every setting key appears once, with its value form or a comment that says what it takes. It is a map of the language, not a policy to publish; the setting values are placeholders. The sections that follow explain each part.

yaml
version: "0.1" # optional; read but not checked metadata: # optional; notes for you, ignored by the service name: "Engineering policy" rules: # optional; a list. See How rules combine - id: rule-name # optional; lower-case, digits, hyphens; unique capability: model_use # required; a capability or group below effect: allow # required; allow, deny, or ask. deny always wins match: ["claude-*"] # optional; pattern list. Omit to cover everything exclude: ["claude-opus-5"] # optional; pattern list carved out of match when: 'groups in ["<group id>"]' # optional; single-quoted. Omit for all # capability match takes can ask no rule # fs_read, fs_write file path, **/.env yes ungoverned # shell command, "git push *" yes ungoverned # web_search nothing yes ungoverned # web_fetch domain, *.example.com yes ungoverned # mcp server/tool, corp-tools/* yes ungoverned # model_use model identifier, claude-opus-* no denied # apikey_create nothing no denied # messaging_channel channel id, slack no denied # messaging nothing no denied # permission_mode Kiro Crew mode, yolo no yolo denied # cron nothing no Kiro Crew default # network_egress domain, *.example.com no denied # browser_use nothing no Kiro Crew default # tailnet_origin nothing no Kiro Crew default # theme_install nothing no Kiro Crew default # groups: all > builtin > filesystem. A rule on a group covers every # capability under it # when: groups in ["<group id>"] user == "<user id>" user != "<user id>" # combine with && || ! and parentheses. IDs, not names settings: # optional; a map of setting keys to values # !locked: the developer cannot change it. Every setting takes it # !replace: a default the developer can change. default_model only default_model: !replace "claude-sonnet-4.5" # a model_use rule must allow it model_governance.enabled: true # false: model rules do not limit cloud_sessions.enabled: false device_code_sign_in.enabled: true web_tools.enabled: true # rules still decide each call mcp_tools.enabled: true # rules still decide each call mcp_registry_url: "https://example.com/registry" usage_dashboard: true prompt_logging.enabled: true # needs prompt_logging.destination prompt_logging.destination: "s3://bucket/prefix/" user_activity_report.enabled: true user_activity_report.csv_export: true user_activity_report.csv_destination: "s3://bucket/prefix/" user_activity_report.otel_export: true user_activity_report.otel_secret_arn: "<secret arn>" user_activity_report.otel_protocol: grpc # grpc or http/protobuf user_activity_report.otel_temporality: Delta # Delta or Cumulative user_activity_report.otel_private_mode: privatelink # privatelink or lattice user_activity_report.otel_endpoint_service_name: "<name>" user_activity_report.otel_endpoint_service_region: us-east-1 user_activity_report.otel_resource_configuration_arn: "<arn>" user_activity_report.otel_collector_hostname: "<hostname>" realtime_event_export.enabled: true realtime_event_export.secret_arn: "<secret arn>" # a different secret realtime_event_export.private_mode: lattice # privatelink or lattice realtime_event_export.endpoint_service_name: "<name>" realtime_event_export.endpoint_service_region: us-east-1 realtime_event_export.resource_configuration_arn: "<arn>" realtime_event_export.collector_hostname: "<hostname>" crew_sandbox_min_level: standard # off, standard, cc, strict

Patterns: * matches any characters, ** matches any folders, matching is case-sensitive, and "git push *" also matches bare git push. Model identifiers have no anthropic. prefix. A misspelled optional field such as matches: gives no error and the rule then covers everything.

File layout

yaml
version: "0.1" # optional; read but not checked metadata: # optional; notes for you, ignored by the service name: "My policy" rules: # optional; a list of rules - id: model-use-allow capability: model_use effect: allow settings: # optional; a map of setting keys to values default_model: !replace "claude-sonnet-4.5"
KeyRequiredWhat it holds
versionNoA string such as "0.1". Read but not checked.
metadataNoA map of notes for you, such as name. The service ignores it.
rulesNoA list of rules. See Rules.
settingsNoA map of setting keys to values. See Settings.

The file must be a YAML map. Unknown top-level keys are ignored without an error. A policy can hold several KGL files; the service reads them as one set.

Rules

yaml
rules: - id: my-rule # optional name capability: model_use # required effect: deny # required: allow, deny or ask match: ["claude-opus-*"] # optional: what the rule covers exclude: ["claude-opus-5"] # optional: carve-outs when: 'groups in ["<group id>"]' # optional: who it applies to
FieldRequiredWhat it does
idNoA name for the rule: lower-case letters, digits, and hyphens. Must be unique per rule.
capabilityYesThe permission the rule decides, such as model_use or shell, or a group such as builtin.
effectYesallow, deny, or ask. Some capabilities cannot ask.
matchNoA list of patterns the rule covers. Leave it out to cover everything.
excludeNoA list of patterns carved out of match.
whenNoA condition on groups or users. Leave it out to apply to everyone.

match and exclude are always lists.

How rules combine

A capability with no rule is denied. Some capabilities are ungoverned instead: Kiro applies its own default until a rule names them. For those, the developer's own configuration decides, and Kiro asks when it neither allows nor denies. Any rule on an ungoverned capability, a deny included, brings back the default deny for everything the rule does not cover. Five Kiro Crew capabilities keep Kiro Crew's own default instead, as the table shows. A deny always wins. Rule order has no effect.

With no ruleCapabilities
Deniedmodel_use, apikey_create, and the Kiro Crew capabilities messaging_channel, messaging, network_egress
Ungovernedfs_read, fs_write, shell, web_search, web_fetch, mcp
Kiro Crew defaultcron: scheduled jobs run until a rule denies them. permission_mode: yolo is off; normal, trust, and trust_reads stay available unless a rule denies them. browser_use, tailnet_origin, theme_install: on until a rule denies them

So a policy with one shell deny rule turns every other shell command from ask to denied. Add an ask or allow rule beside the deny to keep the rest open.

Capabilities

CapabilityWhat it coversmatch takesCan ask
fs_readReading and searching files, directories, and codeFile path, such as .env or */secrets/*Yes
fs_writeCreating, editing, moving, and deleting filesFile pathYes
shellRunning shell commandsCommand, such as rm -rf *Yes
web_searchSearching the webNothingYes
web_fetchFetching content from a web URLDomain, such as *.example.comYes
mcpCalling tools exposed by MCP serversserver/tool, such as corp-tools/*Yes
model_useWhich models the agent may invokeModel identifier, such as claude-opus-*No
apikey_createGenerating API keys to run Kiro CLI in automationNothingNo
messaging_channelWhich messaging channels (Slack, Discord, Telegram, and others) a Kiro Crew agent may connect to and send onChannel id, such as slackNo
messagingSending messages to people from a Kiro Crew agentNothingNo
permission_modeWhich tool approval modes a Kiro Crew user may select. Denying yolo turns auto-approve off, including a grant that is already on; normal, trust, and trust_reads stay availableMode, such as yoloNo
cronWhether Kiro Crew may run scheduled jobs. They run until a rule denies them. A deny stops every scheduled job, including ones created earlier (they are kept), and stops new ones from being created. To turn them back on, allow the capability; removing the deny is not enoughNothingNo
network_egressHosts a Kiro Crew agent may connect to. Kiro Crew applies it to its fetch toolDomain, such as *.example.comNo
browser_useWhether a Kiro Crew agent may drive its web browser (open pages, click, type). A deny turns the browser tool off. web_fetch, web_tools.enabled, and network_egress do not cover itNothingNo
tailnet_originWhether a Kiro Crew dashboard may be opened from other devices on the user's Tailscale tailnet. A deny turns Tailscale access off and refuses turning it back onNothingNo
theme_installWhether a Kiro Crew user may download and install third-party dashboard themes. A deny refuses new installs; built-in and already installed themes keep workingNothingNo

Three groups also take a rule, and a rule on a group covers every capability under it: all holds everything; builtin sits under all and holds the built-in tools; filesystem sits under builtin and holds fs_read and fs_write.

A capability that takes nothing cannot have match or exclude; Publish returns BINARY_CAPABILITY_SCOPED. For which capabilities are enforced, and by which client, see Enforcement status, and for rule behaviors that are under investigation, see Known issues.

Patterns

  • * matches any characters. claude-* matches every Claude model, including models that Kiro adds later.
  • "git push *" also matches the bare command git push.
  • File paths use globs. ** matches any folders, so **/secrets/** matches every file under any secrets folder.
  • Patterns are case-sensitive. A literal * cannot be matched.
  • Model identifiers have no anthropic. prefix. anthropic.claude-opus-* matches nothing; write claude-opus-*.

Conditions (when)

yaml
rules: - capability: web_search effect: allow when: 'groups in ["12345678-90ab-cdef-1234-567890abcdef"]' - capability: web_search effect: deny when: 'user == "abcdef12-3456-7890-abcd-ef1234567890"' - capability: shell effect: ask match: ["git push *"] when: '!(groups in ["<group id>"]) && user != "<user id>"'
  • Use user IDs and group IDs, not names. In YAML you type the ID; in the Form view you pick the user or group and the console writes the ID. With Okta, the Form view is the only place to get the ID. Publish checks each ID against your directory. To find the IDs, see Find user and group IDs.
  • Always put the whole value in single quotes.
  • Combine conditions with &&, ||, !, and parentheses.

Settings

yaml
settings: default_model: !locked "claude-sonnet-4.5" prompt_logging.enabled: true prompt_logging.destination: "s3://my-bucket/prompts/"
TagMeaningAllowed on
!lockedThe developer cannot change the value. The Form view shows this as Developer override: Not allowed.Every setting
!replaceA default the developer can change. The Form view shows this as Developer override: Can update.default_model only
  • default_model must be a model that a model_use rule allows; otherwise Publish returns POLICY_BOUNDARY_VIOLATION. Its shipped default is auto.
  • model_governance.enabled decides whether model_use rules limit the models developers see. A new profile ships with it false; set it to true for the rules to take effect.
  • A setting that is turned on may need another one. prompt_logging.enabled: true needs prompt_logging.destination; otherwise Publish returns SETTING_REQUIREMENT_MISSING. The console shows no error for a missing pair until you publish, so set both values.

For every setting key, its shipped default, and its values, see Setting keys.

Example

yaml
version: "0.1" rules: - id: model-use-allow capability: model_use effect: allow match: ["claude-*"] - id: models-deny-opus-for-contractors capability: model_use effect: deny match: ["claude-opus-*"] when: 'groups in ["<group id>"]' - id: web-search-ask capability: web_search effect: ask - id: shell-ask capability: shell effect: ask - id: shell-deny-destructive capability: shell effect: deny match: ["rm -rf *", "sudo *"] settings: default_model: !locked "claude-sonnet-4.5"

This policy allows Claude models, but not Opus for the group named in when. Kiro asks before web searches and shell commands, and refuses destructive commands. Capabilities it does not name keep Kiro's own default. For more policies, from an eight-rule floor to a complete one, see KGL examples.

Common errors

Publish returns these codes. The API returns them in the code field of a diagnostic; see EnterpriseManagementDiagnostic.

CodeCause
YAML_PARSE_ERRORThe file is not valid YAML.
UNKNOWN_CAPABILITY / UNKNOWN_SETTINGA typo in a capability or setting name.
DECISION_NOT_ALLOWEDask on a capability that cannot ask.
BINARY_CAPABILITY_SCOPEDmatch on a capability that takes nothing.
FIELD_NOT_A_STRING_LISTmatch: "x" in place of match: ["x"].
WHEN_PARSE_ERRORBad when syntax, or the value is not quoted.
UNKNOWN_GROUP / UNKNOWN_USERA name or a wrong ID in when.
POLICY_BOUNDARY_VIOLATIONdefault_model is not allowed by a model_use rule.
SETTING_REQUIREMENT_MISSINGA setting that is on needs another value.

A misspelled optional field, such as matches:, gives no error. The service ignores it, and the rule then covers everything. Check the spelling of every optional field before you publish.

Page mise à jour : 11 novembre 2026