Toda equipe tem aquele conjunto de tarefas chatas que ninguém gosta de fazer, mas que precisam ser feitas sempre do mesmo jeito: abrir PR com o título no padrão, nomear a branch certo, montar o changelog, linkar o work item. São tarefas de baixo valor intelectual e alto custo de atenção — e, pior, qualquer desvio do padrão vira ruído na revisão.
Resolvi atacar isso de uma forma diferente: em vez de escrever mais um script bash gigante, montei agentes de IA especializados que encapsulam esses fluxos. Neste artigo mostro como estruturei esse setup usando o Kiro CLI, com um padrão que separa claramente configuração, conhecimento e regras de segurança.
Vou usar meus próprios agentes como exemplo — abstraindo nomes internos — mas o padrão serve para qualquer time.
O problema
No meu dia a dia eu repetia, várias vezes por dia, dois fluxos:
- Abrir um Pull Request: criar a branch no padrão, commitar com a convenção certa, inferir a branch de destino, abrir o PR com título e descrição padronizados e linkar o work item.
- Fechar um pacote de release: buscar os PRs já concluídos de uma demanda, gerar o changelog, commitar e abrir um PR de release para a branch certa.
Nenhum desses passos é difícil. O problema é que todos eles têm detalhes — e detalhe esquecido é retrabalho. Automatizar com um script puro seria frágil, porque boa parte das decisões depende de contexto (qual branch, qual título, qual destino).
Agente de IA é bom justamente nessa zona cinzenta: segue regras, mas interpreta contexto.
A ideia central: separar configuração, conhecimento e regras
O que mais me ajudou foi não jogar tudo em um prompt gigante. Em vez disso, dividi cada agente em quatro camadas, cada uma em um arquivo próprio:
.kiro/ ├── agents/ # Configuração: quais ferramentas o agente pode usar ├── prompts/ # Identidade: quem o agente é e seu contexto fixo ├── steering/ # Guardrails: o que ele NUNCA pode fazer ├── skills/ # Conhecimento: o passo a passo de cada tarefa └── settings/ # Integração com ferramentas externas (via MCP) A sacada é que cada camada tem uma responsabilidade única:
- Agent = o contrato (ferramentas permitidas, atalho, mensagem de boas-vindas)
- Prompt = a identidade (contexto que nunca muda)
- Steering = os limites (proibições inegociáveis)
- Skill = o manual (como executar cada passo, com exemplos)
Separar assim traz um benefício enorme: as skills viram reutilizáveis entre agentes. A skill de "criar commit" é a mesma para o agente que abre PR e para o que fecha release.
Camada 1 — O agente (configuração)
O arquivo de configuração do agente é enxuto. Ele diz o que o agente pode fazer, não como. Veja um exemplo (abstraído):
{ "name": "open-pr", "description": "Agente que abre Pull Requests: cria branch, commita, abre o PR e linka o work item.", "prompt": "file://./prompts/open-pr.md", "includeMcpJson": true, "tools": ["shell", "read", "write", "grep", "glob", "@git-provider"], "allowedTools": [ "shell", "read", "write", "@git-provider/create_pull_request", "@git-provider/create_branch", "@git-provider/link_work_item" ], "resources": [ "skill://.kiro/skills/commit/SKILL.md", "skill://.kiro/skills/create-branch/SKILL.md", "skill://.kiro/skills/open-pr/SKILL.md" ], "keyboardShortcut": "ctrl+shift+p", "welcomeMessage": "Me diga o ID da demanda ou descreva a feature. Eu cuido do resto." } Dois pontos importantes aqui:
-
allowedToolsé uma allowlist explícita. O agente só consegue chamar exatamente as ferramentas que eu listei. Isso é segurança por design: ele não vai, por engano, chamar uma ferramenta destrutiva que eu nunca autorizei. -
resourcesinjeta as skills. O agente carrega as instruções detalhadas sob demanda, em vez de carregar tudo o tempo todo.
Camada 2 — O prompt (identidade e contexto fixo)
O prompt define quem o agente é e qual contexto nunca muda. É aqui que eu "ancoro" o agente para ele não ficar perguntando o óbvio toda vez.
Você é um agente especializado em abrir Pull Requests para o repositório da equipe. ## Contexto Fixo - Provedor de git: <configurado via MCP> - Projeto / repositório: <fixos, injetados pela configuração> - Branch de origem padrão: `main` ## Regras de Operação - SEMPRE usar o projeto e repositório fixos — NUNCA perguntar ao usuário - Inferir a branch de destino a partir do contexto da demanda - Seguir as convenções de branch e commit definidas nas skills ## O que NÃO fazer - NÃO perguntar projeto ou repositório — são fixos - NÃO fazer push direto para branches protegidas Repare no padrão "Regras" + "O que NÃO fazer". Dizer ao agente o que não fazer é tão importante quanto dizer o que fazer. Isso reduz muito o comportamento imprevisível.
Dica: dados que não devem vazar (IDs internos, GUIDs, URLs) ficam fora do artigo/documentação pública e são injetados via configuração ou MCP. Nunca coloque isso no corpo de uma skill que vai pro repositório aberto.
Camada 3 — Steering (guardrails inegociáveis)
Essa é a camada que me deixa dormir tranquilo. O steering lista proibições absolutas, independentes de qualquer instrução que o agente receba.
# Open PR — Guardrails ## Proibições - NUNCA fazer force push - NUNCA push direto em branches protegidas - NUNCA criar PR sem pelo menos 1 commit na branch - NUNCA prosseguir se o git mostrar conflitos não resolvidos ## Confirmações Obrigatórias - SEMPRE mostrar o resumo (branch, commits, destino, título) antes de abrir o PR - SEMPRE confirmar se houver dúvida sobre a branch de destino ## Comportamento em Falha - Se o push falhar → mostrar o erro e sugerir ação (nunca forçar) - Se a branch de destino não existir → perguntar ao usuário A diferença entre prompt e steering é intencional: o prompt é a personalidade (pode ter nuance), o steering é a lei (não tem exceção). Mesmo que o usuário peça "faz um force push aí", o guardrail segura.
Camada 4 — Skills (o conhecimento reutilizável)
As skills são o coração do setup. Cada uma é um documento curto que ensina um procedimento, com formato e exemplos. A skill de commit, por exemplo, define a convenção completa:
# Responsabilidade Criar commits padronizados. ## Formato <type>(<scope>): <emoji> <descrição curta> ## Procedimento 1. Rodar `git status --short` 2. Analisar os caminhos para determinar tipo e escopo 3. Agrupar em commits lógicos 4. Fazer staging seletivo (nunca `git add .`) 5. Commitar com a mensagem formatada ## Exemplos feat(module-a): ✨ add product tag component fix(module-b): 🐛 correct price display refactor(shared): 🔨 simplify item props O ponto forte: a mesma skill de commit é usada pelo agente de PR e pelo agente de release. Escrevi uma vez, reaproveitei em todos. Quando a convenção muda, altero um arquivo só.
Meu segundo agente — o de fechar release — é basicamente uma orquestração de skills:
Recebe o ID da demanda → busca os PRs já concluídos → troca para a branch certa → gera o changelog → usa a skill de commit → usa a skill de open-pr para abrir o PR de release → linka o work item Ou seja: um agente complexo nasce da composição de skills simples. Isso é muito mais fácil de manter do que um prompt monolítico.
Camada 5 — Integração via MCP
Para o agente conseguir realmente abrir PRs e buscar demandas, ele precisa falar com o provedor de git. Eu faço isso via MCP (Model Context Protocol), que expõe as operações externas como ferramentas que o agente pode chamar.
{ "mcpServers": { "git-provider": { "command": "npx", "args": ["-y", "<pacote-mcp-do-provedor>", "--arg", "valor"], "env": { "PROVIDER_ORG_URL": "<url-da-organizacao>", "PROVIDER_DEFAULT_PROJECT": "<projeto>", "PROVIDER_DEFAULT_REPOSITORY": "<repo>" } } } } O MCP é o que conecta o "cérebro" (o agente) às "mãos" (as operações no provedor de git). E, combinado com a allowlist lá do agente, eu controlo exatamente quais dessas operações ficam disponíveis.
Camada 6 — Docs de onboarding
Por último, mantenho um doc curto por agente explicando o que ele é e como invocar. É o que eu passo pra qualquer pessoa nova do time:
# Agente `open-pr` ## Como invocar - Atalho: Ctrl+Shift+P - Ou: "Abre um PR para a demanda 123" / "Commita e abre PR" ## Fluxo Usuário informa demanda → busca contexto → cria branch → commit → push → abre PR → linka work item → retorna o link ## Onde vivem as regras | Assunto | Arquivo | |----------------------|-----------------------------| | Convenção de branch | skills/create-branch | | Convenção de commit | skills/commit | | Regras de PR | skills/open-pr | | Guardrails | steering/open-pr | O resultado na prática
Depois que esse setup entrou no fluxo, abrir um PR virou uma frase: "abre um PR pra demanda X". O agente infere a branch, commita no padrão, abre o PR com título e descrição corretos e linka o work item — sempre do mesmo jeito, sem eu precisar lembrar de cada detalhe.
E, olhando o histórico de commits do repositório, dá pra ver a convenção sendo seguida de forma consistente: tipo, escopo, emoji e descrição curta em inglês, commit após commit. Essa consistência é exatamente o que eu queria — e ela não depende mais da minha memória num dia cansado.
O que eu levaria pra qualquer projeto
Se eu fosse resumir o aprendizado em princípios reaproveitáveis:
- Separe configuração de conhecimento. O agente diz o que pode; a skill diz como fazer.
- Guardrails são uma camada à parte. Proibições não deveriam estar misturadas com instruções normais.
- Skills pequenas e reutilizáveis. Um agente complexo é composição de skills simples.
- Allowlist de ferramentas sempre. Segurança por design, não por confiança.
- Diga o que NÃO fazer. Isso reduz comportamento imprevisível mais do que qualquer instrução positiva.
- Mantenha dados sensíveis fora das skills. Injete por configuração/MCP, nunca no texto versionado.
No fim, não automatizei só tarefas — padronizei decisões. E isso, mais do que o tempo economizado, foi o que mudou meu fluxo de trabalho.
Se você também vive repetindo os mesmos passos de Git, vale experimentar esse padrão. Comece com uma skill só, como a de commit, e vá compondo a partir daí.
🇺🇸 English version: How I turned repetitive Git chores into AI agents with the Kiro CLI
