blog

Agent Steering Best Practices for Kiro CLI Custom Agents

A comprehensive guide to writing effective agent steering files, synthesized from CLAUDE.md, AGENTS.md, Cursor Rules, Kiro steering, and community best practices.

Agent Steering Best Practices for Kiro CLI Custom Agents

A comprehensive guide to writing effective agent steering files, synthesized from CLAUDE.md, AGENTS.md, Cursor Rules, Kiro steering, and community best practices. Last updated: February 2026.


Table of Contents

  1. The Steering Landscape
  2. Universal Principles
  3. Kiro CLI Agent Architecture
  4. Writing Effective Prompts
  5. Steering File Strategy
  6. Resource & Context Management
  7. Security & Permissions
  8. Hooks for Dynamic Context
  9. Cross-Tool Compatibility
  10. Templates & Examples

1. The Steering Landscape

The AI coding agent ecosystem has converged on markdown-based instruction files that provide persistent context to agents. The major approaches:

Format Origin Scope Adoption
AGENTS.md OpenAI/Codex Universal standard 60k+ repos; Codex, Cursor, Amp, Cline, Copilot, Jules, Augment, Roo Code
CLAUDE.md Anthropic Claude Code specific Native in Claude Code; fallback in Codex, Cursor, Amp, Copilot, Augment
GEMINI.md Google Gemini CLI specific Native in Gemini CLI; supported by Copilot, Zed
Cursor Rules Cursor Cursor IDE specific .cursor/rules/*.mdc with YAML frontmatter
Kiro Steering AWS/Kiro Kiro IDE & CLI .kiro/steering/*.md — persistent AI context
Kiro Custom Agents AWS/Kiro Kiro CLI .kiro/agents/*.json — full agent configuration

Key trend: AGENTS.md is becoming the de facto cross-tool standard. Kiro CLI supports AGENTS.md natively — place it in your repo root or ~/.kiro/steering/ and it's automatically included in every session.


2. Universal Principles

These principles apply regardless of which tool or format you use. They are distilled from Anthropic's official guidance, community research, and empirical testing.

2.1 Less Is More

Frontier LLMs can reliably follow ~150–200 instructions. Agent harnesses (Claude Code, Kiro, etc.) already consume ~50 of those with their system prompts. That leaves you roughly 100–150 instructions before quality degrades — and degradation is uniform across all instructions, not just the later ones.

Targets: - Root steering/prompt: < 300 lines (ideally < 60 lines for the core) - Per-file steering: < 100 lines each - Total across all loaded files: < 500 lines

2.2 Universally Applicable Content Only

Every instruction in your always-loaded context should apply to every task the agent performs. If an instruction only matters for database schema work, it shouldn't be in the root prompt — put it in a separate file loaded on demand.

Bad: "When creating database migrations, always use reversible migrations" (in root prompt — irrelevant for UI work)

Good: "Use TypeScript strict mode for all files" (in root prompt — always relevant)

2.3 Progressive Disclosure

Don't front-load everything. Structure information in layers:

  1. Always loaded — Project identity, tech stack, key commands, universal rules
  2. Auto-loaded by context — Directory-specific AGENTS.md, glob-matched rules
  3. On-demand — Skills, knowledge bases, referenced docs the agent fetches when needed

2.4 Cover WHAT, WHY, and HOW

  • WHAT: Tech stack, project structure, key directories, dependencies
  • WHY: Purpose of the project, architectural decisions, domain context
  • HOW: Build commands, test commands, deployment steps, verification workflows

2.5 Show, Don't Just Tell

Include concrete code examples of preferred patterns. Before/after comparisons are especially effective. Agents follow demonstrated patterns more reliably than abstract rules.

2.6 Iterate Based on Friction

Start minimal. Add instructions only when you observe the agent making repeated mistakes. Review and prune regularly — outdated instructions are worse than no instructions.


3. Kiro CLI Agent Architecture

Kiro CLI custom agents are JSON configuration files that control every aspect of agent behavior. They live in:

  • Local (project-specific): .kiro/agents/<name>.json
  • Global (user-wide): ~/.kiro/agents/<name>.json

Local agents take precedence over global agents with the same name.

3.1 Configuration Fields Overview

┌─────────────────────────────────────────────────────────┐
│                    Agent Config (.json)                  │
├─────────────────┬───────────────────────────────────────┤
│ Identity        │ name, description, welcomeMessage     │
│ Steering        │ prompt (inline or file://), resources  │
│ Tools           │ tools, allowedTools, toolAliases,      │
│                 │ toolsSettings                          │
│ Integrations    │ mcpServers, includeMcpJson             │
│ Lifecycle       │ hooks (agentSpawn, preToolUse, etc.)   │
│ Preferences     │ model, keyboardShortcut                │
└─────────────────┴───────────────────────────────────────┘

3.2 Creating Agents

# Interactive (recommended for first-time setup)
kiro-cli agent create --name my-agent

# From within a chat session
/agent generate

# Start a session with a specific agent
kiro-cli --agent my-agent

# Swap agents mid-session
/agent swap

4. Writing Effective Prompts

The prompt field is the primary steering mechanism for Kiro CLI agents. It functions like a system prompt — loaded at the start of every conversation.

4.1 Inline vs. File-Based Prompts

Inline — for short, focused agents:

{
  "prompt": "You are a code reviewer focused on security and performance."
}

File-based — for complex agents (recommended):

{
  "prompt": "file://./prompts/backend-specialist.md"
}

File paths resolve relative to the agent config file's directory. Use file:// for relative paths, file:/// for absolute paths.

4.2 Prompt Structure Template

# [Agent Role]

[One sentence: what this agent does and its primary expertise]

## Project Context

- **Stack**: [frameworks, languages, key libraries]
- **Structure**: [key directories and their purposes]
- **Build**: `[build command]`
- **Test**: `[test command]`
- **Lint**: `[lint command]`

## Standards

- [3-7 universally applicable rules]
- [Prefer concrete examples over abstract guidelines]

## Workflow

1. [How the agent should approach tasks]
2. [Verification steps before completing work]

## Anti-Patterns

- DON'T: [specific things to avoid]
- DO: [preferred alternatives]

4.3 Prompt Writing Rules

  1. Front-load the most important information — the first ~100 lines get the most attention from the model
  2. Use imperative, specific language — "Use arrow functions" not "Consider using arrow functions when appropriate"
  3. Avoid contradictions — conflicting instructions cause unpredictable behavior
  4. Don't duplicate what tools already enforce — if ESLint catches it, don't add a prompt instruction for it
  5. Include verification steps — tell the agent how to check its own work

5. Steering File Strategy

Kiro CLI has two complementary steering mechanisms: the agent prompt field and .kiro/steering/ files. Use them together strategically.

5.1 Steering Files (.kiro/steering/*.md)

These provide persistent project knowledge. They are automatically loaded for the default agent but must be explicitly included in custom agent resources:

{
  "resources": ["file://.kiro/steering/**/*.md"]
}

5.2 Recommended Steering File Layout

.kiro/
├── agents/
│   ├── backend.json
│   ├── reviewer.json
│   └── prompts/
│       ├── backend.md
│       └── reviewer.md
└── steering/
    ├── product.md          # What the product does, who it's for
    ├── tech.md             # Stack, dependencies, constraints
    ├── structure.md        # Directory layout, naming conventions
    ├── api-standards.md    # REST conventions, error formats
    └── testing.md          # Test patterns, coverage requirements

5.3 AGENTS.md Integration

Kiro CLI natively supports AGENTS.md. Place it in your repo root for cross-tool compatibility:

project/
├── AGENTS.md               # Universal — works with Kiro, Codex, Cursor, etc.
├── .kiro/
│   └── steering/
│       └── kiro-specific.md  # Kiro-only context
└── src/

For maximum compatibility across tools, maintain an AGENTS.md at the repo root with universal instructions, and use .kiro/steering/ for Kiro-specific guidance.

5.4 Hierarchical Steering for Monorepos

Place AGENTS.md files in subdirectories for area-specific rules:

monorepo/
├── AGENTS.md                 # Global rules
├── packages/
│   ├── api/
│   │   └── AGENTS.md         # API-specific rules
│   ├── web/
│   │   └── AGENTS.md         # Frontend-specific rules
│   └── shared/
│       └── AGENTS.md         # Shared library rules

6. Resource & Context Management

Kiro CLI agents support three resource types, each suited to different context needs.

6.1 File Resources — Always Loaded

Loaded into context at agent startup. Use for content the agent always needs.

{
  "resources": [
    "file://README.md",
    "file://.kiro/steering/**/*.md",
    "file://docs/architecture.md"
  ]
}

Best practice: Keep total always-loaded content under ~500 lines. Every token counts against the context budget.

6.2 Skill Resources — Progressive Disclosure

Only metadata (name + description) loaded at startup. Full content loaded on demand when the agent determines it's relevant. This is the key mechanism for progressive disclosure in Kiro CLI.

Skill files require YAML frontmatter:

---
name: database-migrations
description: Guide for creating and managing database migrations. Use when working
  with schema changes, Alembic, or migration files.
---

# Database Migration Guide

[Full content here — only loaded when the agent needs it]
{
  "resources": [
    "skill://.kiro/skills/**/SKILL.md"
  ]
}

Best practice: Write specific, descriptive description fields so the agent reliably knows when to load the full content.

6.3 Knowledge Base Resources — Large Documentation

For indexing large documentation sets (millions of tokens). The agent searches incrementally rather than loading everything.

{
  "resources": [
    {
      "type": "knowledgeBase",
      "source": "file://./docs",
      "name": "ProjectDocs",
      "description": "API documentation and architecture guides",
      "indexType": "best",
      "autoUpdate": true
    }
  ]
}

6.4 Context Budget Strategy

┌──────────────────────────────────────────────────────┐
│              Context Loading Priority                 │
├──────────────────────────────────────────────────────┤
│ 1. Agent prompt          (always, keep < 60 lines)   │
│ 2. Steering files        (always, keep < 500 total)  │
│ 3. File resources        (always, be selective)       │
│ 4. Skill metadata        (always, lightweight)        │
│ 5. Skill full content    (on demand)                  │
│ 6. Knowledge base search (on demand, incremental)     │
│ 7. Hook outputs          (dynamic, per-trigger)       │
└──────────────────────────────────────────────────────┘

7. Security & Permissions

7.1 Tool Access — Start Restrictive

Begin with minimal tool access and expand as needed:

{
  "tools": ["read", "write", "shell"],
  "allowedTools": ["read"]
}
  • tools — what the agent can use (with confirmation)
  • allowedTools — what runs without confirmation

7.2 AllowedTools Patterns

Use specific patterns over broad wildcards:

{
  "allowedTools": [
    "read",                    // Exact built-in tool
    "@git/git_status",         // Exact MCP tool
    "@git/git_log",            // Exact MCP tool
    "@server/read_*",          // Wildcard: all read tools from server
    "@fetch"                   // All tools from fetch server
  ]
}

Never use "*" in allowedTools — it doesn't work and shouldn't.

7.3 Tool Settings for Guardrails

Restrict tool behavior to safe boundaries:

{
  "toolsSettings": {
    "write": {
      "allowedPaths": ["src/**", "tests/**", "*.md"]
    },
    "shell": {
      "allowedCommands": ["npm test", "npm run build", "git status"],
      "deniedCommands": ["rm -rf.*", "git push.*"],
      "autoAllowReadonly": true
    }
  }
}

7.4 Security Checklist

  • [ ] Never put secrets, API keys, or credentials in steering files or prompts
  • [ ] Review allowedTools carefully before sharing agent configs
  • [ ] Use toolsSettings to restrict write paths and shell commands
  • [ ] Test agents in safe environments before production use
  • [ ] Treat agent configs like code — version control and review changes

8. Hooks for Dynamic Context

Hooks inject dynamic, real-time context at specific lifecycle points.

8.1 Hook Triggers

Trigger When Use Case
agentSpawn Agent initializes Git status, environment checks, AWS identity
userPromptSubmit User sends message Current directory listing, branch info
preToolUse Before tool runs Audit logging, validation, blocking
postToolUse After tool runs Auto-formatting, linting, notifications
stop Agent finishes Run tests, generate summaries

8.2 Practical Hook Examples

{
  "hooks": {
    "agentSpawn": [
      { "command": "git status --porcelain" },
      { "command": "git branch --show-current" }
    ],
    "postToolUse": [
      {
        "matcher": "fs_write",
        "command": "black --quiet --check ."
      }
    ],
    "stop": [
      { "command": "npm test -- --silent" }
    ]
  }
}

Note: Hook matchers use internal tool names (fs_read, fs_write, execute_bash, use_aws), not simplified display names.


9. Cross-Tool Compatibility

If your team uses multiple AI tools, maximize compatibility:

9.1 The Symlink Strategy

# Primary file — universal standard
echo "# Project Instructions" > AGENTS.md

# Symlinks for tool-specific compatibility
ln -s AGENTS.md CLAUDE.md
ln -s AGENTS.md GEMINI.md

9.2 Compatibility Matrix (Key Tools)

Tool AGENTS.md CLAUDE.md Kiro Steering Kiro Agents
Kiro CLI ✅ Native ✅ Native ✅ Native
Claude Code ✅ Native
Codex CLI ✅ Native Fallback
Cursor ✅ Native ✅ Native
GitHub Copilot ✅ Native ✅ Native
Amp ✅ Native Fallback

9.3 Layered Approach

AGENTS.md                    → Universal rules (all tools read this)
.kiro/steering/*.md          → Kiro-specific context
.kiro/agents/*.json          → Kiro CLI agent configs
.cursor/rules/*.mdc          → Cursor-specific rules (if using Cursor)

Keep AGENTS.md tool-agnostic. Put tool-specific instructions in each tool's native format.


10. Templates & Examples

10.1 Minimal Agent Config

{
  "name": "dev",
  "description": "General development assistant for this project",
  "prompt": "file://./prompts/dev.md",
  "tools": ["*"],
  "allowedTools": ["read", "@builtin"],
  "resources": [
    "file://README.md",
    "file://.kiro/steering/**/*.md"
  ]
}

10.2 Specialized Code Review Agent

{
  "name": "reviewer",
  "description": "Code review specialist — read-only, security and quality focused",
  "prompt": "You are a code review specialist. Focus on security vulnerabilities, performance issues, and adherence to project standards. Never modify files directly.",
  "tools": ["read", "shell"],
  "allowedTools": ["read"],
  "toolsSettings": {
    "shell": {
      "allowedCommands": ["grep", "find", "wc", "git diff", "git log"],
      "autoAllowReadonly": true
    }
  },
  "resources": [
    "file://AGENTS.md",
    "file://.kiro/steering/**/*.md"
  ],
  "hooks": {
    "agentSpawn": [
      { "command": "git diff --name-only HEAD~1" }
    ]
  },
  "keyboardShortcut": "ctrl+r"
}

10.3 AWS Infrastructure Agent

{
  "name": "infra",
  "description": "AWS infrastructure specialist for IaC and cloud operations",
  "prompt": "file://./prompts/infra.md",
  "tools": ["read", "write", "shell", "aws"],
  "allowedTools": ["read", "aws"],
  "toolsSettings": {
    "aws": {
      "allowedServices": ["s3", "lambda", "cloudformation", "ec2", "iam", "logs"]
    },
    "write": {
      "allowedPaths": ["infrastructure/**", "scripts/**", "*.yaml", "*.yml"]
    }
  },
  "resources": [
    "file://README.md",
    "file://infrastructure/**/*.yaml",
    "skill://.kiro/skills/**/SKILL.md"
  ],
  "hooks": {
    "agentSpawn": [
      { "command": "aws sts get-caller-identity" }
    ]
  },
  "model": "claude-sonnet-4",
  "keyboardShortcut": "ctrl+i"
}

10.4 Agent with Knowledge Base

{
  "name": "docs-expert",
  "description": "Agent with deep knowledge of project documentation",
  "prompt": "You help developers find and understand project documentation. Search the knowledge base before answering questions.",
  "tools": ["read", "knowledge"],
  "allowedTools": ["read", "knowledge"],
  "resources": [
    "file://README.md",
    {
      "type": "knowledgeBase",
      "source": "file://./docs",
      "name": "ProjectDocs",
      "description": "All project documentation, guides, and ADRs",
      "indexType": "best",
      "autoUpdate": true
    }
  ]
}

10.5 Minimal AGENTS.md Template

# [Project Name]

[One-sentence description]

## Stack

- **Language**: [e.g., Python 3.12, TypeScript 5.x]
- **Framework**: [e.g., FastAPI, Next.js 15]
- **Database**: [e.g., PostgreSQL with SQLAlchemy]
- **Testing**: [e.g., pytest, Jest]

## Commands

\```bash
[package-manager] install    # install dependencies
[package-manager] run dev    # development server
[package-manager] test       # run tests
[package-manager] run build  # production build
\```

## Structure

- `src/` — application source code
- `tests/` — test files (colocated with source)
- `docs/` — documentation

## Standards

- [3-5 key rules that apply to ALL work in this repo]

## Notes

- [Gotchas, non-obvious patterns, important constraints]

Summary: Decision Flowchart

Is the instruction universally applicable?
├── YES → Put in agent prompt or AGENTS.md
└── NO
    ├── Is it domain-specific but frequently needed?
    │   └── YES → Put in a steering file (.kiro/steering/)
    └── Is it large reference documentation?
        ├── YES (< 200 lines) → Use a skill resource
        └── YES (large) → Use a knowledge base resource
Do you need cross-tool compatibility?
├── YES → Use AGENTS.md at repo root + symlinks
└── NO (Kiro only) → Use .kiro/steering/ + .kiro/agents/

References

← back to index