Hands-on · Chapter 5 of 16
Advanced Tutorial
A production-shaped workflow that combines specs, steering, hooks, MCP, custom agents, and skills, written for engineers who already know the basics.
Advanced last reviewed 2026-06-11
◎ Learning objective
Assemble Kiro's primitives into a repeatable team workflow: foundation steering, requirements-first specs, scoped hooks, deliberate MCP config, and role-based custom agents.
This chapter assumes you’ve read Core Concepts (or already use Kiro). It builds one coherent workflow you can adapt to a real codebase.
A note on labeling, kept honest: the mechanics below (file locations, commands, config fields, behavior of modes) are verified against official documentation as of the review date. The workflow itself (the order, the discipline, what goes where) is this site’s recommended practice, not an official prescription. Where something is purely opinion, it says so.
The scenario
A small inventory service: a REST API with a database, owned by a three-person team. We’ll wire it up so that:
- The agent permanently knows the project’s shape (steering).
- New features run through reviewed specs.
- Tests and docs maintain themselves (hooks).
- The agent can reach the team’s external tools (MCP).
- Risky work happens through restricted personas (custom agents).
Adapt the nouns to your stack; the pattern carries over.
Step 0: Foundation steering
Before any clever automation, write the three foundational files in .kiro/steering/ (workspace level, committed to the repo so the whole team shares them):
# product.md - one screen, no more
Inventory service for internal warehouse teams. Tracks stock levels,
reservations, and reorder thresholds. Correctness beats speed:
a wrong stock count costs real money.
# tech.md
Python 3.12, FastAPI, PostgreSQL 16, SQLAlchemy 2.x, pytest.
No new dependencies without a design-doc note explaining why.
# structure.md
src/api/ → routers (one file per resource)
src/models/ → SQLAlchemy models
src/services/ → business logic (routers stay thin)
tests/ mirrors src/ one-to-one.
These three load into every interaction by default. Then add narrow rules with conditional inclusion. For example, an API-conventions file can load only when API files are involved, via front matter at the very top of the file: inclusion: fileMatch plus fileMatchPattern: "src/api/**". Keep each file to one domain, and explain why a rule exists so the agent can generalize it sensibly.
Opinion, clearly labeled: steering is the most valuable hour you will spend setting up Kiro. Teams that skip it re-litigate their conventions in every chat, forever.
Step 1: Features as requirements-first specs
For a real feature, say stock reservations with expiry, start a feature spec using the requirements-first workflow (Kiro also offers design-first and quick-plan variants for smaller work).
Work the EARS notation properly, including the patterns beginners skip:
WHEN a client reserves stock for an order
THE SYSTEM SHALL decrement available count and create a reservation
with a 30-minute expiry
IF a reservation request exceeds available stock
THEN THE SYSTEM SHALL reject it with a 409 and the current available count
WHILE a reservation is active
THE SYSTEM SHALL exclude its quantity from availability calculations
The discipline: WHEN for nominal behavior, IF/THEN for error paths, WHILE for ongoing states. Error paths are where production incidents live. If your requirements have no IF/THEN lines, they’re not done.
Before approving, run Kiro’s optional requirements analysis: it flags acceptance criteria that admit multiple interpretations, contradictions, and gaps. It’s cheap insurance at the cheapest possible moment.
In design.md, review like a senior engineer, not a spell-checker: data model changes, transaction boundaries, failure modes, sequence diagrams. Then execute tasks.md. Kiro runs independent tasks concurrently in waves, so a well-decomposed task list finishes faster than a monolithic one.
Finally, since GA Kiro supports property-based testing to check the implementation against the spec. Use it on anything with invariants (stock can never go negative; reserved + available = total).
Step 2: Regressions as bugfix specs
When a real bug lands (“reservations sometimes never expire”), resist the hotfix reflex. A bugfix spec puts the analysis in bugfix.md (symptoms, root cause, blast radius) and then designs the fix.
Recommended practice: make the first task a failing regression test that reproduces the bug, and only then the fix. The spec records why the bug existed; the test guarantees it can’t quietly return. Keep checkpoints in mind throughout: if an agent session takes a wrong turn mid-fix, roll back to the checkpoint instead of un-picking edits by hand.
Step 3: Hooks for the boring loop
Automate exactly two kinds of things at first (opinion: more than that, this early, becomes noise):
- Scoped test runs: on save of files under
src/services/, run that module’s tests and summarize failures. - Doc sync: on save of files under
src/api/, check whetherdocs/api.mdstill matches the endpoints’ signatures and propose an update if not.
Create both in natural language from the hooks panel: describe the trigger and action, and Kiro generates the configuration. Hook triggers can also fire on prompt submission, agent-turn completion, before/after tool calls, and before/after spec tasks. The advanced uses, like a before-spec-task validation gate, are worth exploring once the basics earn their keep.
Step 4: MCP, deliberately
Wire external reach at the workspace level so the whole team shares it: .kiro/settings/mcp.json (workspace beats user-level ~/.kiro/settings/mcp.json on conflict):
{
"mcpServers": {
"docs-search": {
"command": "npx",
"args": ["-y", "example-docs-mcp-server"],
"env": { "DOCS_TOKEN": "${DOCS_TOKEN}" },
"autoApprove": [],
"disabled": false
},
"issue-tracker": {
"url": "https://mcp.example-tracker.com/mcp",
"oauth": { "clientId": "kiro-team-inventory" }
}
}
}
Field notes, all verified: env vars expand with ${VAR} syntax (no secrets in the file itself); remote servers use url plus headers/oauth; disabledTools can mask individual tools; "autoApprove": "*" exists and you should treat it like sudo without a password prompt. Start every server with autoApprove: [], watch what it asks for during a normal week, then approve the read-only tools you actually use. Connection problems? The “Kiro - MCP Logs” output channel is the first stop.
Step 5: Custom agents as roles
Generalist agents accumulate generalist permissions. Define roles instead, as JSON in .kiro/agents/ (workspace) or ~/.kiro/agents/ (global):
{
"name": "reviewer",
"description": "Strict review persona - reads everything, changes nothing",
"tools": ["read"],
"allowedTools": ["read"],
"resources": ["file://docs/standards.md", "skill://.kiro/skills/*/SKILL.md"],
"prompt": "You are the team's strictest reviewer. Hunt for correctness bugs, missing error paths, and violations of docs/standards.md. Report; never fix."
}
Create with /agent create reviewer -D "strict reviewer" (add --manual to edit the JSON directly), switch mid-session with /agent swap, or start sessions as a role: kiro-cli --agent reviewer. The payoff is twofold: pre-approved safe tools mean fewer interruption prompts, and a hard permission ceiling means you can run the reviewer in Autopilot with a clear conscience, because it cannot write.
Recommended pattern: one read-only reviewer, one implementer with normal tools, and (if you do data work) a migrations agent whose prompt forbids destructive statements and whose tools exclude anything that can execute against production.
Step 6: Skills and powers to scale knowledge
When you’ve explained the same procedure twice (“how we write release notes”, “how we add a new pipeline source”), it’s a skill: a folder in .kiro/skills/ with a SKILL.md (name + precise description in front matter, then the steps). Commit workspace skills so the team shares them; Kiro activates them when a request matches the description, or explicitly as /skill-name. Keep the SKILL.md actionable and push long reference material into the skill’s auxiliary files.
For third-party technology knowledge, check powers first. A power bundles POWER.md + MCP config (+ optional steering/hooks) and loads on demand, which keeps your default context lean compared to a pile of always-on MCP servers. Read what’s inside before installing, exactly as you’d skim a setup script.
Step 7: The terminal and CI edge
Everything above works in kiro-cli too: same steering, hooks, MCP, agents, skills. Two advanced uses earn special mention:
- Remote work: over SSH or in containers, the CLI is the whole experience:
/context add "src/**",!pytest -x,/chat savefor handoffs. - Headless automation: the CLI supports headless operation with API-key authentication for CI/CD. Treat it as production automation: pin the custom agent it runs as, restrict its tools, and budget credits. (The capability is verified; the guardrail design is on you.)
The full command reference lives in the CLI Guide.
The operating model, on one screen
- Steering = the constitution (rare, reviewed changes).
- Specs = every feature and risky fix (requirements → design → tasks).
- Hooks = the chores (narrow triggers, light actions).
- MCP/powers = reach (workspace-level, least privilege).
- Custom agents = roles (permissions match the job).
- Skills = procedures (written once, activated on demand).
- Supervised vs Autopilot = a dial you set per task risk, not a personality trait.
☰ Chapter summary
- Lay foundations first: product.md, tech.md, structure.md in .kiro/steering/, then narrow fileMatch rules.
- Run features as requirements-first specs; use requirements analysis to catch ambiguity before design.
- Run regressions as bugfix specs: analysis in bugfix.md, regression test before the fix.
- Hooks automate the boring loop (tests, doc sync); scope triggers narrowly to avoid noise and loops.
- Configure MCP per workspace with empty autoApprove by default; approve tools deliberately.
- Use restricted custom agents for roles (read-only reviewer); share team know-how as skills in .kiro/skills/.
All chapter summaries are collected on the revision page.