Runs entirely locally: steering is just a Markdown file in the project. No dependencies.
Goal
Create a small steering file and observe how Kiro's behavior immediately follows it — on every subsequent prompt, without naming the rules again.
Preparation
- Any project opened (e.g. the Kanban board from Lab 2).
- Kiro in chat mode.
Step 1 – Capture the baseline behavior
Ask a short question, e.g.:
Write a small function that checks whether a number is even.
Note: in which language/style does Kiro respond? Comments? Explanatory text?
Step 2 – Create the steering file
Create .kiro/steering/tech.md:
---
inclusion: always
---
# Team rules
- Always respond in English.
- Use TypeScript, no var declarations (only const/let).
- Comment each function with a short line describing what it does.
- Keep answers concise: code first, then at most two sentences of explanation.
At the very top is the front matter with inclusion: always. This means: these rules are included on every prompt. always is also the default — if you left the front matter out entirely, it would still apply. We write it out here on purpose so you can see what it looks like. How to control this specifically (e.g. only for certain files) is shown in the How does steering work? section further down.
Step 3 – Check the effect
Ask a similar question to Step 1, but without repeating the rules:
Write a small function that checks whether a string is a valid
email address.
Observe: Kiro now responds in English, in TypeScript, with const/let, a short comment and a concise explanation — even though you did not say so in the prompt.
Step 4 – Change a rule, effective immediately
Change a rule in tech.md (e.g. "Always respond in German") and save. Next prompt → the new behavior takes effect immediately on the next turn.
Key takeaways
- Steering is a persistent memory: once defined, it applies to every turn.
- Separation: steering = "how it's built", specs = "what is built".
- Global (
~/.kiro/steering/) vs. project (.kiro/steering/); project usually takes precedence. - Saves tokens/credits because you don't repeat rules in every prompt.
- Central team steering ensures consistent standards across all teams.
What is steering good for? Examples
Steering makes sense wherever something should apply permanently without you repeating it in every prompt. A few typical use cases:
Coding standards
Language, framework, naming conventions, formatting. For example: always TypeScript, always include tests, no deprecated APIs.
Project knowledge
What the project is about, which architecture, which important folders. So the agent doesn't have to guess each time.
Tone & language
Always respond in English, concise and factual. Or: explain technical terms because the team is mixed.
Team rules
Consistent guidelines for everyone: security rules, forbidden libraries, approval processes. Distributed globally, they apply to everyone on the team.
How does steering work?
Steering files are simple Markdown files in the .kiro/steering/ folder. Kiro reads them and puts their content into the conversation context at the start.
What is front matter?
Front matter is a small header block at the very top of the file, framed by two lines with three dashes (---). Inside it you put settings in YAML format — simple key: value pairs. For steering, this block controls when the file is loaded. Here's what it looks like:
---
inclusion: fileMatch
fileMatchPattern: "*.tsx"
---
# Rules for React components
- Use functional components, not classes.
- Every component gets a short comment.
Everything between the two --- is the configuration, everything below it is the actual content. Important: the front matter must be at the very start of the file, with no blank line before it. If you don't provide any front matter, always applies automatically — which is exactly the case for our tech.md above.
The four modes (the value of inclusion:)
- always – always loaded (default when there is no front matter). Good for core rules that apply everywhere.
- fileMatch – only when certain files are involved (e.g. only for
*.tsx, controlled viafileMatchPattern). Saves context space. - manual – only on demand, when you pull it with
#filenamein the chat. - auto – automatically active when your request fits the topic.
Note: In the Kiro CLI these modes are currently not evaluated — there, all steering files are always loaded.
How the steering reaches the agent
It's worth seeing what Kiro actually sends to the model. Your steering file is placed into the context as "Included Rules" — and Kiro automatically appends a small block about your working environment. For our tech.md it looks roughly like this:
---
inclusion: always
---
# Team rules
- Always respond in English.
- Use TypeScript, no var declarations (only const/let).
- Comment each function with a short line describing what it does.
- Keep answers concise: code first, then at most two sentences of explanation.
<EnvironmentContext>
This information is provided as context about user environment. Only consider it if it's relevant to the user request ignore it otherwise.
<OPEN-EDITOR-FILES>
No files are open
</OPEN-EDITOR-FILES>
<ACTIVE-EDITOR-FILE>
No file is active in editor
</ACTIVE-EDITOR-FILE>
</EnvironmentContext>
The upper part is your steering rule, exactly as you wrote it. The <EnvironmentContext> block below it comes from Kiro itself. It tells the model which files are currently open or active — none here. You don't write this block; it is added automatically on every turn.
Why is this good to know? For one, you see that steering really lands as text in the context and is not a magic switch. For another, it explains why answers sometimes change when a different file is open: Kiro shares that state with the model.
Why doesn't steering always work? Is it a bug?
Some context first: the official Kiro documentation describes steering positively — it is meant to make Kiro follow your conventions "consistently". There is no dedicated troubleshooting page there for "steering not being followed".
In practice, though, you'll notice the agent doesn't always stick to a steering rule. This is usually not a technical bug in Kiro, but lies in the nature of the thing: steering is not a hard if-then rule like in a program, but additional context for an AI model. The model tries to follow it, but under certain circumstances a rule gets lost.
That this behavior exists is openly documented — namely in Kiro's bug tracker. Kiro uses its GitHub repository (kirodotdev/Kiro) as the public place for bugs and feature requests. There you find real reports about it, for example:
- Issue #6518: The agent had the steering file in context but only followed it while running a spec task after the user pointed it out twice.
- Issue #2250: A rule with
inclusion: alwayswas "overruled" by generic task instructions, even though it was supposed to apply. - Issue #6171 / #9117: Steering files (partly the global ones from
~/.kiro/steering/) were not loaded into context at all.
This shows two things: first, it is a known, openly handled topic and no sign that you are doing something wrong. Second, it's worth checking the bug tracker when something doesn't behave as expected — often there is already an explanation or a workaround.
Typical causes from practice
- Conflict with the task. If a generic task instruction contradicts the steering rule, sometimes the task wins (see Issue #2250). Fix: keep rules clear and free of contradictions.
- File not loaded. With custom agents, steering is not loaded automatically — you must add it in the
resourcesfield. Global files also caused problems (Issues #6171/#9117). Fix: check whether the file is really in context (visible as "Included Rules" in the IDE). - Long chat, full context. In long conversations, older context is summarized. A rule set early on can then drop out of sight. Fix: start a new chat for a new topic.
- Phrased too vaguely. "Write good code" is not a checkable rule. Fix: concrete rules with examples (the official docs recommend this too).
- Error in the header. The front matter must be at the very start of the file (with
---, no blank line before it). Otherwise the inclusion mode doesn't apply. This is specified in the docs. - Wrong fileMatch pattern. If the glob doesn't match the file, the rule is never loaded. Fix: check the pattern.
Rule of thumb: steering is a strong lever, but not a guaranteed one. The shorter, clearer and more concrete the rules are, and the more targeted they are loaded, the more reliably the agent follows them. If a rule really must be hard-enforced, another mechanism is often the better choice (e.g. a lint/build step or a permission rule). And if something clearly doesn't work: check the bug tracker or report it there yourself.