Skip to main content
Agents can inherit configuration from other agents using the inherits field.

A relatable example: dependabot

This is a good way to think about inheritance in practice. Start with a reusable git policy that is intentionally conservative: ~/.kiro/generators/manifests/kg.toml
[agents]
git-readonly = { template = true }
dependabot = { inherits = ["git-readonly"] }
~/.kiro/generators/agents/git-readonly.toml
[nativeTools.shell]
allow = [
  "git status .*",
  "git fetch .*",
  "git diff .*",
  "git log .*"
]
deny = ["git commit .*", "git push .*"]
Then create a child agent that mostly follows that policy, but needs two extra capabilities: ~/.kiro/generators/agents/dependabot.toml
[nativeTools.shell]
forceAllow = ["git commit .*", "git push .*"]
That is a useful inheritance example because it shows the point clearly:
  • the parent defines the default behavior
  • the child reuses that behavior instead of copying it
  • the child changes only the specific capability it actually needs

Basic inheritance

[agents]
default = { inherits = [] }
rust = { inherits = ["default"] }
The rust agent inherits all configuration from default and can override or extend it.

Multiple Parents

Agents can inherit from multiple parents:
[agents]
git-base = { template = true }
rust-base = { template = true }
rust-dev = { inherits = ["git-base", "rust-base"] }
Configuration is merged left-to-right. Later parents override earlier ones.

Merge Behavior

Arrays (allowedTools, resources, etc.)

Arrays are merged (combined): Parent:
[agents.default]
allowedTools = ["read", "knowledge"]
Child:
[agents.rust]
inherits = ["default"]
allowedTools = ["@rustdocs", "@cargo"]
Result:
allowedTools = ["read", "knowledge", "@rustdocs", "@cargo"]

Objects (nativeTools, mcpServers, etc.)

Objects are deep merged: Parent:
[agents.default.nativeTools.shell]
allow = ["git status", "git fetch"]
autoAllowReadonly = true
Child:
[agents.rust.nativeTools.shell]
allow = ["cargo .*"]
Result:
[nativeTools.shell]
allow = ["git status", "git fetch", "cargo .*"]
autoAllowReadonly = true

Scalars (description, timeout, etc.)

Scalars are replaced: Parent:
description = "Default agent"
Child:
description = "Rust development agent"
Result:
description = "Rust development agent"

Inheritance Chain

You can create deep inheritance hierarchies:
[agents]
base = { inherits = [] }
dev = { inherits = ["base"] }
rust-dev = { inherits = ["dev"] }
Configuration is merged from root to leaf: basedevrust-dev

Force properties

Force properties override permission restrictions in child agents. They ensure specific commands or paths are always allowed, even if a child tries to deny them.

forceAllow for shell commands

Force specific shell commands to be allowed: ~/.kiro/generators/agents/dependabot.toml
[nativeTools.shell]
forceAllow = ["git commit .*", "git push .*"]
Child agents cannot deny these commands: ~/.kiro/generators/agents/dependabot.toml
[nativeTools.shell]
deny = ["git push .*"]  # Ignored - git push is force-allowed
The forced commands are added to allow and removed from deny.

forceAllow for paths

Force specific paths to be readable or writable:
[agents.cargo-editor]
template = true

[agents.cargo-editor.nativeTools.read]
forceAllow = [".*Cargo.toml.*"]

[agents.cargo-editor.nativeTools.write]
forceAllow = [".*Cargo.toml.*"]
Child agents must allow access to these paths:
[agents.dependabot]
inherits = ["cargo-editor"]

[agents.dependabot.nativeTools.write]
deny = [".*Cargo.toml.*"]  # Ignored - Cargo.toml is force-allowed

Use Cases

Force properties are useful for:
  • Ensuring critical permissions in specialized agents (like dependabot needing git push)
  • Creating permission templates that can’t be accidentally restricted
  • Building agent hierarchies with guaranteed capabilities

Validation

Use kg validate to see the final merged configuration:
kg validate
This shows exactly what each agent will generate, including inherited settings and forced permissions.