2

Agentes em paralelo precisam de worktrees, não de mais abas

Você abre três sessões para acelerar uma feature. Um agente implementa o componente, outro cuida da acessibilidade e o terceiro prepara os testes. Nos primeiros minutos, a sensação é ótima: três tarefas andando ao mesmo tempo.

Só existe um detalhe. Todos trabalham no mesmo checkout.

O primeiro troca de branch. O segundo edita um arquivo que acabou de mudar debaixo dele. O terceiro executa os testes contra uma combinação de código que nenhuma das três tarefas vai entregar. Cada sessão tem seu próprio contexto de conversa, mas o Git, os arquivos e os processos continuam compartilhados.

Esse arranjo aumenta a disputa pelos mesmos recursos sem entregar mais trabalho integrado. O tempo que parecia economizado volta no fim como conflito, reexecução e uma revisão difícil de reconstruir.

Ferramentas de agentes já começaram a adotar uma saída prática: uma sessão independente ligada a um git worktree. É um bom começo, desde que o time não confunda um checkout separado com isolamento completo nem trate o merge como trabalho administrativo que acontece sozinho.

Mais sessões não criam mais linhas de trabalho

Um agente de código não atua apenas sobre o texto da conversa. Ele lê arquivos, altera o diretório de trabalho, instala dependências, inicia servidores, escreve caches e executa comandos. Se duas sessões apontam para a mesma árvore de trabalho, ambas mexem no mesmo estado operacional.

Até mudanças em arquivos diferentes podem interferir. Um git checkout altera a branch visível para todas as sessões naquele diretório. Um instalador atualiza o lockfile. Um servidor ocupa a porta que o outro agente esperava usar. Um teste deixa dados no banco local e muda o resultado da próxima execução.

Separar as conversas resolve apenas o contexto do modelo. Para executar em paralelo, cada tarefa precisa de um endereço próprio no repositório e de regras para os recursos que continuam compartilhados.

O worktree cria uma fronteira útil

Um worktree é outro checkout ligado ao mesmo repositório Git. Ele tem diretório e branch próprios, então dois agentes podem editar e testar estados diferentes sem disputar o mesmo índice nem trocar a branch um do outro.

Um ponto de partida simples seria registrar a base e criar uma área para cada tarefa:

git fetch origin
base_commit=$(git rev-parse origin/main)

git worktree add ../app-feature -b agent/feature "$base_commit"
git worktree add ../app-a11y -b agent/a11y "$base_commit"

Agora cada agente recebe um caminho, uma branch e o mesmo commit-base. Essa última informação importa. Se uma tarefa falhar ou produzir um diff estranho, quem integra consegue saber contra qual estado ela tomou suas decisões.

O worktree, porém, não é um container nem uma sandbox. Ele não separa credenciais, acesso à rede, serviços externos ou bancos locais. Também não impede dois agentes de alterarem o mesmo contrato em branches diferentes. A fronteira do checkout resolve uma classe de colisão; o restante precisa de configuração e coordenação.

Na prática, eu daria a cada agente uma porta própria e, quando houver escrita, um banco ou schema de teste separado. Secrets deveriam seguir a política normal do projeto, com o menor acesso necessário. Se uma tarefa puder disparar deploy, enviar mensagem ou alterar dados externos, paralelizar sem um controle adicional só aumenta a velocidade do risco.

Escreva o contrato antes do fan-out

Mandar "faça a acessibilidade" para uma sessão e "escreva os testes" para outra parece divisão de trabalho, mas deixa quase todas as decisões para depois. Um cartão curto já reduz bastante a ambiguidade:

task: adicionar navegação por teclado ao seletor de projetos
base: 4f3c2d1
branch: agent/a11y-project-picker
worktree: ../app-a11y
owned_paths:
  - src/components/project-picker/
shared_surfaces:
  - src/ui/popover.tsx
  - tests/fixtures/projects.ts
acceptance:
  - foco não escapa do popover
  - Escape fecha e devolve o foco ao gatilho
validate:
  - pnpm test project-picker
  - pnpm typecheck

O contrato deve deixar explícitos o objetivo, os caminhos sob responsabilidade da tarefa, as superfícies compartilhadas e os comandos de validação. Também precisa dizer o que o agente entrega no fim: commits, resumo do diff, resultados dos checks, falhas e pendências.

Se o agente descobrir que precisa alterar algo fora do escopo, ele pode parar e registrar a dependência em vez de ampliar a mudança silenciosamente. Assim, quem revisa descobre a mudança antes do merge, em vez de encontrá-la no meio de um diff de vinte arquivos.

Algumas tarefas parecem independentes até o código começar

Feature, acessibilidade e testes formam uma divisão bonita numa lista. No repositório, talvez as três dependam do mesmo componente e do mesmo contrato de eventos.

Eu desenharia um grafo pequeno antes de iniciar os agentes:

TrabalhoPode começar agora?Motivo
Implementar o componente e definir sua APISimproduz a interface usada pelas outras mudanças
Ajustar um utilitário isolado de acessibilidadeSimnão toca o componente nem um contrato em definição
Alterar a navegação por teclado do componenteDepois que a API estiver estávelconcorre na mesma superfície e depende das decisões da feature
Preparar fixtures dos testesSimpode avançar sem assumir o markup final
Escrever o fluxo completo de testeDepois da integração da featureseletores e comportamento ainda podem mudar

Quando duas tarefas alteram o mesmo schema, lockfile, contrato de API ou componente-base, dar um agente para cada uma costuma fabricar trabalho. É melhor escolher um dono ou definir uma ordem. Esperar alguns minutos pode ser mais barato do que resolver duas implementações coerentes isoladamente e incompatíveis entre si.

Escopos estreitos diminuem colisões e facilitam o review, mas não são gratuitos. Dois agentes podem duplicar um helper ou resolver o mesmo problema em lugares diferentes. Por isso, o mapa de dependências deve incluir as superfícies compartilhadas, não apenas uma lista de arquivos "permitidos".

O merge faz parte da execução

Uma branch pronta ainda não é um resultado aceito. Ela é uma proposta produzida contra uma base que pode ficar desatualizada assim que os agentes são distribuídos.

A integração precisa ter ordem e dono. Se a feature define um contrato consumido pelos testes, integre a feature primeiro. Depois, atualize a branch dependente contra a base já integrada, resolva os conflitos e repita os checks que cobrem o fluxo final.

Resolver os marcadores <<<<<<< não valida comportamento. O conflito mais caro costuma ser semântico: cada branch passa sozinha, mas a combinação quebra um estado, duplica uma regra ou muda uma premissa que o outro agente usou.

Eu colocaria estes passos na própria definição de pronto:

  1. conferir se o diff permaneceu no escopo combinado;
  2. integrar as branches na ordem declarada;
  3. atualizar cada trabalho dependente contra a base integrada;
  4. repetir testes, tipos e o fluxo afetado pela combinação;
  5. revisar primeiro contratos e arquivos compartilhados;
  6. remover o worktree quando a branch estiver integrada ou descartada.

O último item evita o acúmulo de diretórios e dependências que ninguém mais usa. Worktrees gastam disco e pedem limpeza. Ainda assim, esse custo costuma ser mais previsível do que deixar sessões concorrentes disputarem o mesmo checkout.

Peça um recibo curto de cada agente

O handoff não precisa trazer o histórico inteiro da sessão. Na maior parte do tempo, cinco campos bastam:

Base: 4f3c2d1
Commits: a12bc34
Arquivos alterados: 6
Checks: unitários e typecheck passaram; E2E não executado
Pendência: popover compartilhado exige revisão do responsável por UI

Se a integração falhar, aí sim vale abrir o log detalhado, filtrar eventos e guardar um snapshot para investigar comandos, respostas e reexecuções. Um formato como JSONL ajuda a pesquisar esse rastro, mas não prova que a alteração está correta. Também pode carregar caminhos locais, prompts, dados de ferramentas e outras informações que não deveriam ficar retidas para sempre.

O recibo serve para localizar a mudança e suas lacunas. O teste integrado e o review continuam responsáveis por avaliar o resultado.

Meça até a integração aceita

Contar agentes iniciados é fácil e diz pouco. O mesmo vale para tarefas marcadas como concluídas dentro de sessões isoladas.

A unidade mais honesta é o tempo entre distribuir o trabalho e aceitar a integração. Nesse intervalo entram os comandos repetidos, os conflitos, as branches refeitas e o esforço de revisão. Um fluxo com quatro agentes pode terminar as edições cedo e ainda perder para duas tarefas bem separadas se o merge exigir uma tarde inteira.

Para um primeiro experimento, eu acompanharia:

  • tempo do fan-out até a integração aprovada;
  • conflitos e alterações fora do escopo;
  • comandos reexecutados depois do merge;
  • branches descartadas ou refeitas;
  • tempo de review e regressões encontradas após a integração.

Tokens por chamada e quantidade de tarefas simultâneas ajudam a explicar custo de execução. Não substituem a medida do ciclo completo.

Comece com duas tarefas de verdade

Não estreie esse fluxo repartindo uma refatoração transversal entre cinco agentes. Escolha duas mudanças com poucos arquivos compartilhados, crie um worktree por tarefa e use o mesmo modelo de contrato e recibo.

Ao final, compare o tempo total com um trabalho serial parecido. Observe onde o segundo agente realmente reduziu espera e onde transferiu esforço para a integração. Se o merge continuou legível, os checks capturaram a combinação e as pendências vieram declaradas, existe base para ampliar o teste.

Mantenha o foco no tempo até o resultado integrado, em vez de tentar ocupar todos os agentes. Trabalhos independentes podem avançar juntos sem obrigar alguém a reconstruir manualmente o que aconteceu depois.

Checklist para o próximo PR

  • Cada tarefa tem worktree e branch próprios?
  • Todas partiram de um commit-base registrado?
  • O escopo de arquivos e as superfícies compartilhadas estão claros?
  • Contratos compartilhados têm um dono ou uma ordem de alteração?
  • Dependências reais continuaram seriais?
  • Portas, banco local, rede e efeitos externos têm uma regra definida?
  • Cada agente entregou commits, checks, falhas e pendências?
  • A integração atualizou a base e repetiu as validações relevantes?
  • O time mediu o trabalho até o merge aceito?

Um worktree por tarefa não elimina conflitos nem substitui revisão. Ele dá a cada agente um estado de trabalho identificável. Com escopo, dependências e ordem de integração definidos, o time consegue operar o paralelismo sem adivinhar o que cada sessão fez.

Fontes

Carregando publicação patrocinada...