Kiro & AWS
Kiro no dia a dia: specs, hooks e steering (guia prático com código)
Como transformar padrões de time e automação de repositório em artefatos versionados que o agente respeita — com YAML, JSON e uma rotina real de ponta a ponta.
TL;DR
- Steering (
.kiro/steering/*.md) injeta convenções do projeto no agente. São arquivos Markdown com front matter YAML e 4 inclusion modes:always,fileMatch,manualeauto. - Hooks (
.kiro/hooks/*.json) disparam automações por evento (PostFileSave,PreToolUse, etc.). A ação pode ser umcommandshell ou umpromptde agente. - Specs (
.kiro/specs/<nome>/) estruturam a intenção emrequirements.md→design.md→tasks.md. É o assunto do artigo 1 desta série; aqui elas entram como o terceiro pilar da rotina. - O ganho real aparece na combinação dos três: a spec diz o que fazer, o steering diz como, e os hooks garantem que nada escape.
- Armadilha número um: o front matter YAML precisa ser a primeira linha do arquivo, sem linha em branco antes. Se não for, o inclusion mode é ignorado.
O problema: padrões que ninguém segue e automação que ninguém dispara
Todo time tem um documento de convenções. Ele mora no Confluence, no README ou na cabeça do tech lead que entrou há três anos. E todo time sabe o que acontece na prática: o padrão é seguido nos dois primeiros dias depois do onboarding e depois vira folclore. Alguém usa any em TypeScript “só nesse caso”, outro esquece de rodar o linter, um terceiro escreve um endpoint sem o tratamento de erro que o time combinou. Não é má-fé — é atrito. Quanto mais longe o padrão está do momento em que o código é escrito, menor a chance de ele ser aplicado.
Com um agente de IA escrevendo código, esse problema não desaparece: ele escala. O agente não leu o Confluence. Ele vai gerar código idiomático genérico, não o código idiomático do seu projeto. Se você não disser que o banco é acessado via Prisma e que exceções nunca podem ser engolidas, ele vai adivinhar — e vai adivinhar de um jeito diferente a cada sessão.
O Kiro resolve isso movendo os padrões e a automação para dentro do repositório, como artefatos versionados que o agente lê automaticamente. Três mecanismos fazem esse trabalho: steering (as regras), hooks (os gatilhos) e specs (o plano). Este artigo é um guia prático dos três, com o YAML e o JSON reais que você vai colar no seu projeto.
Se o padrão não está a um arquivo de distância do código, ele não vai ser seguido — nem por humanos, nem por agentes.
Steering: ensinando as convenções do projeto ao agente
Steering são arquivos Markdown que ficam em .kiro/steering/ (no workspace) ou em ~/.kiro/steering/ (global, valendo para todos os seus projetos). Cada arquivo carrega um pedaço de contexto que o agente passa a tratar como verdade sobre o seu projeto.
Os arquivos fundacionais mais comuns são três, e vale a pena criá-los cedo:
- product.md — o que o produto faz e para quem.
- tech.md — stack, frameworks, convenções de código.
- structure.md — organização de pastas e onde cada coisa mora.
Front matter e os 4 inclusion modes
O que torna o steering poderoso é o inclusion mode, declarado no front matter YAML no topo do arquivo. Ele controla quando aquele contexto é injetado. São quatro modos.
1. always — sempre incluído, em toda interação. Use para convenções universais do projeto.
---
inclusion: always
---
2. fileMatch — incluído só quando o arquivo em foco casa com um padrão glob. Ideal para regras específicas de uma camada (componentes, migrations, infra).
---
inclusion: fileMatch
fileMatchPattern: "components/**/*.tsx"
---
Precisa de mais de um padrão? Passe uma lista:
---
inclusion: fileMatch
fileMatchPattern: ["**/*.ts", "**/*.tsx"]
---
3. manual — só entra quando você chama explicitamente com #nome-do-arquivo no chat. Ele aparece como um slash command. Bom para checklists ou guias pesados que você não quer no contexto o tempo todo.
---
inclusion: manual
---
4. auto — o agente decide se o contexto é relevante, usando o name e a description que você fornece. É o modo mais inteligente para regras condicionais.
---
inclusion: auto
name: api-design
description: Padrões de design de API REST. Use ao criar ou modificar endpoints.
---
Um steering tech.md real
Teoria é fácil. Veja como fica um tech.md de verdade — curto, imperativo, sem enrolação. O agente lê isto e passa a escrever código no seu dialeto:
---
inclusion: always
---
# Stack e convenções
- Backend: Node.js 20 + TypeScript strict. Sem `any`.
- Framework HTTP: Fastify. Validação com zod.
- Banco: PostgreSQL via Prisma. Migrations versionadas.
- Testes: Vitest. Cobertura mínima 80% em `src/domain`.
- Erros: nunca engolir exceção; sempre logar com correlação (requestId).
Cinco linhas de bullets mudam radicalmente o output do agente. Sem esse arquivo, ele poderia gerar um endpoint com Express, validação manual e um catch vazio. Com ele, o código já nasce no padrão.
#[[file:...]] e AGENTS.md
Duas facilidades importantes fecham a seção:
-
Referência a arquivos vivos: dentro de um steering, você pode apontar para outro arquivo do repositório com a sintaxe
#[[file:<caminho-relativo>]]. Por exemplo,#[[file:api/openapi.yaml]]traz o contrato de API atualizado para o contexto sem você copiar e colar. É uma referência viva: se o arquivo muda, o steering acompanha. -
AGENTS.md: o Kiro suporta o padrão aberto
agents.md. Esse arquivo é sempre incluído e não tem inclusion mode — é o denominador comum. Ele pode ficar na raiz do workspace ou em~/.kiro/steering/. Se você já mantém umAGENTS.mdpara outras ferramentas, o Kiro o respeita sem configuração extra.
Hooks: automação disparada por evento
Se o steering é o o que fazer, os hooks são o faça isto quando acontecer aquilo. São arquivos JSON em .kiro/hooks/ (workspace) ou ~/.kiro/hooks/ (usuário). Cada hook liga um evento a uma ação.
Os campos são poucos e diretos:
| Campo | Obrigatório | O que faz |
|---|---|---|
name | sim | Identificador do hook. |
description | não | Texto livre. |
trigger | sim | O evento que dispara (ver tabela abaixo). |
matcher | não | Regex que filtra por nome de tool ou por caminho de arquivo. |
action | sim | {type:"command", command:"..."} ou {type:"agent", prompt:"..."}. |
timeout | não | Segundos; default 60; 0 desliga. Ignorado para ações agent. |
enabled | não | Default true. |
Tabela de triggers
| Trigger | Bloqueia? | Quando dispara |
|---|---|---|
SessionStart | não | Início da sessão. |
Stop | não | Fim da resposta do agente. |
PreToolUse | sim | Antes de o agente usar uma tool. |
PostToolUse | não | Depois do uso de uma tool. |
PreTaskExec | sim | Antes de executar uma task de spec. |
PostTaskExec | não | Depois de executar uma task. |
UserPromptSubmit | sim | Ao enviar um prompt. |
PostFileCreate | não | Após criar um arquivo. |
PostFileSave | não | Após salvar um arquivo. |
PostFileDelete | não | Após deletar um arquivo. |
Os triggers marcados como “bloqueia” (Pre* e UserPromptSubmit) podem interromper a ação. É aí que entram os exit codes de uma ação command:
0— sucesso. EmSessionStarteUserPromptSubmit, o STDOUT é injetado no contexto do agente.2— bloqueia a ação (só funciona nos triggersPre*/UserPromptSubmit). O STDERR volta para o agente como explicação.- Qualquer outro — tratado como aviso; a execução continua.
Hook 1: lint on save (ação de comando)
O clássico: sempre que o agente salvar um arquivo .ts, roda o linter. O matcher é uma regex sobre o caminho, e timeout de 30 segundos evita travar a sessão se algo pendurar.
{
"version": "v1",
"hooks": [
{
"name": "lint-on-save",
"description": "Roda o linter quando um .ts é salvo pelo agente",
"trigger": "PostFileSave",
"matcher": "\\.ts$",
"action": { "type": "command", "command": "npm run lint" },
"timeout": 30,
"enabled": true
}
]
}
Hook 2: sync-tests (ação de agente)
Este é mais interessante e mostra o poder da ação agent. Em vez de rodar um comando, ele dispara outro prompt de agente: quando um componente .tsx muda, o Kiro atualiza o arquivo de teste correspondente. Note que ações agent ignoram o timeout.
{
"version": "v1",
"hooks": [
{
"name": "sync-tests",
"trigger": "PostFileSave",
"matcher": "src/components/.*\\.tsx$",
"action": {
"type": "agent",
"prompt": "O componente foi alterado. Atualize o arquivo de teste correspondente (.test.tsx) cobrindo os novos casos e mantendo os existentes."
}
}
]
}
A diferença conceitual é enorme: o hook command executa algo determinístico; o hook agent delega uma tarefa cognitiva ao Kiro. Você automatiza não só a checagem, mas o próprio trabalho de manter os testes em dia.
Um hook
commandvalida. Um hookagenttrabalha. Escolher entre os dois é escolher entre um portão e um colega de par.
Specs: o plano que amarra tudo (recapitulando o artigo 1)
Cobri specs em profundidade no primeiro artigo desta série, então aqui vai o resumo funcional. Specs vivem em .kiro/specs/<nome-da-spec>/ e geram três arquivos, seguindo um fluxo de três fases: Requirements → Design → Tasks.
- requirements.md — user stories com critérios de aceitação em notação EARS (
WHEN... THE SYSTEM SHALL...). - design.md — arquitetura, diagramas de sequência, modelo de dados, estratégia de testes.
- tasks.md — tarefas discretas e rastreáveis, que você roda uma a uma ou todas de uma vez.
O detalhe que importa para a rotina de hoje: ao rodar “Run all Tasks”, o Kiro monta um grafo de dependências e agrupa tarefas independentes em waves (Wave 1 = sem dependências), executando em paralelo o que pode ser paralelizado. E as specs ficam sincronizadas com o código conforme ele evolui. Use specs para features complexas e bugs onde regressão é cara; use o modo vibe para exploração rápida sem meta definida.
Mão na massa: os três pilares em uma rotina só
Vamos juntar tudo em um cenário real. Você vai adicionar um sistema de avaliações de produtos a uma API Node/TypeScript. Veja como os três mecanismos se encaixam.
Passo 1 — Steering define o terreno. Você já tem .kiro/steering/tech.md com inclusion: always (o exemplo lá de cima). Toda geração de código já respeita Fastify + zod + Prisma + Vitest. Você adiciona um steering auto só para endpoints:
---
inclusion: auto
name: api-design
description: Padrões de design de API REST. Use ao criar ou modificar endpoints.
---
# Padrões de endpoint
- Toda rota valida input com zod antes do handler.
- Respostas de erro seguem { error: { code, message } }.
- Status codes: 201 na criação, 403 sem autorização, 422 em validação.
Passo 2 — Spec define o plano. Você cria a spec reviews. O requirements.md sai em EARS (“WHEN um cliente autenticado envia uma avaliação… THE SYSTEM SHALL persistir…”; “IF o usuário não comprou… THEN… HTTP 403”). O design.md traz o diagrama de sequência e o modelo de dados. O tasks.md lista as tarefas:
# Plano de implementação
- [ ] 1. Criar migration da tabela reviews (Req 1)
- [ ] 2. Implementar ReviewRepository com verificação de compra (Req 1)
- [ ] 2.1 Testes unitários do repositório
- [ ] 3. Endpoint POST /products/{id}/reviews (Req 1)
- [ ] 3.1 Teste de integração (403 sem compra)
- [ ] 4. Filtro de moderação (Req 1 - WHERE)
Passo 3 — Hooks garantem a disciplina. Com o lint-on-save ativo, cada arquivo .ts que o Kiro salvar ao executar as tasks passa pelo linter automaticamente. Se você trabalha com componentes de front-end para exibir as avaliações, o sync-tests mantém os .test.tsx alinhados a cada mudança. Você não precisa lembrar de nada disso — os gatilhos disparam sozinhos.
O resultado: você aprova o plano da spec, manda executar, e enquanto o Kiro implementa a Wave 1, o steering mantém o código no padrão e os hooks fazem o policiamento. Cada peça cobre um buraco que as outras deixariam.
Armadilhas comuns
Alguns tropeços que custam tempo e são fáceis de evitar:
- Front matter tem que ser a primeira linha. No steering, o bloco
---do YAML precisa ser literalmente a primeira coisa do arquivo, sem linha em branco ou comentário antes. Se houver qualquer coisa acima, o inclusion mode é ignorado e o arquivo pode virar umalwayssilencioso — ou nem ser lido como esperado. matcheré regex, não glob. No hook, omatcheré uma expressão regular.\\.ts$casa arquivos.ts;*.tsnão faz o que você imagina. Escape os pontos (\\.) e ancore com$quando quiser casar a extensão no fim do caminho. Isso é diferente dofileMatchPatterndo steering, que é glob.timeoutsó vale para açãocommand. Se sua ação é do tipoagent, otimeouté ignorado — a tarefa cognitiva roda até concluir. Não conte com ele para limitar um hook de agente.- Exit code
2só bloqueia em triggersPre*. Fazer um script sair com código 2 em umPostFileSavenão impede nada; ali o evento já aconteceu. O bloqueio só existe emPreToolUse,PreTaskExeceUserPromptSubmit. - Steering demais polui o contexto. Cada arquivo
alwaysentra em toda interação e consome contexto (e créditos). Reserve oalwayspara o essencial e prefirafileMatch/autopara regras específicas.
Principais aprendizados
- Steering, hooks e specs movem padrões, automação e planejamento para dentro do repositório, onde o agente os lê sem depender da sua memória.
- Steering usa front matter YAML com 4 inclusion modes; escolha entre
always,fileMatch,manualeautoconforme a regra seja universal, contextual, sob demanda ou condicional. - Hooks ligam eventos a ações; uma ação
commandvalida de forma determinística, uma açãoagentdelega trabalho cognitivo ao Kiro. - Specs dão o plano rastreável (EARS → design → tasks) e executam em waves paralelas.
- Comece pequeno: um
tech.mdcomalways, umlint-on-save, e cresça a partir daí. O valor composto aparece quando os três operam juntos.
Referências
- Specs — documentação: https://kiro.dev/docs/specs/
- Steering — documentação: https://kiro.dev/docs/steering/
- Hooks — documentação: https://kiro.dev/docs/hooks/
- Hooks: tipos e triggers: https://kiro.dev/docs/hooks/types/
- Introducing Kiro (blog oficial): https://kiro.dev/blog/introducing-kiro/
Este artigo foi publicado originalmente no Medium. Preços, nomes de modelos e detalhes de produto refletem o estado do Kiro em meados de 2026 e podem mudar — confirme em kiro.dev antes de tomar decisões. Este é um conteúdo educacional independente, sem vínculo oficial com a AWS.
Tags: kiro, aws, steering, automation, devtools
Publicado originalmente em prompt.victorbatistax.com. Se você chegou por outra plataforma, esta é a versão canônica.