Pular para o conteúdo
Comunidade e open source

Rodar agentes em paralelo parece simples. A Síntese sabe onde a conta realmente pesa.

O Playmaker transforma seu agente em gerente de tarefas paralelas, deixando o código decidir o que pode rodar junto e validar os resultados. Aberto (MIT), e por enquanto usa as CLIs que você já tem.

PorErick Mendes

18 min de leitura
capa-playmaker
Seções deste artigo

Resumo

  • O Playmaker transforma o agente que você já está usando no gerente de uma rodada paralela. Ele propõe a divisão do trabalho, você aprova, e os workers rodam nas CLIs que você já tem (Claude Code, Codex, Gemini, Antigravity e Copilot), cada um no seu git worktree e na sua branch.
  • Nossa tese é que paralelizar agentes é um problema de colisão de arquivos e de integração, e que a parte que dá para calcular tem de ser código. O julgamento, que é ler o diff, decidir se devolve e escolher quem faz o quê, fica com o agente gerente.
  • O desenho se apoia em decisões como estas: o gerente nunca implementa e só ele integra, dependência significa mergeado e não iniciado, o relatório do worker é uma afirmação e não uma prova, duas rodadas falhas estacionam a tarefa, e só a pessoa marca Done.
  • Testamos o laço inteiro com CLIs de agente falsas, em Windows, macOS e Linux. Não publicamos número de ganho de tempo, porque ainda não o medimos com o método que um número desses exige, e isso fica para outro texto.
  • Repositório: github.com/sinteselabs/Playmaker (abre em outra aba)

Vinte agentes que renderam como dois ou três

Quando a Cursor descreveu como fez centenas de agentes trabalharem no mesmo projeto, a primeira versão era a mais intuitiva, com agentes de mesmo status coordenando-se por um arquivo compartilhado e um lock para que dois não pegassem a mesma tarefa. O resultado, nas palavras deles, foi que vinte agentes "desaceleravam até a vazão efetiva de dois ou três, com a maior parte do tempo gasta esperando" (Cursor (abre em outra aba)). Ou seja, o gargalo não estava nos agentes, estava no ponto em que eles se encontravam.

O relato da Anthropic sobre um compilador de C escrito por 16 instâncias do Claude em paralelo, com quase 2 mil sessões e cerca de US$ 20 mil em API, tem a mesma forma por outro caminho. Quando havia muitos testes distintos falhando, a paralelização era "trivial", porque cada agente pegava um teste diferente. Quando a tarefa virou compilar o kernel do Linux, todos esbarraram no mesmo bug, o consertaram e sobrescreveram as mudanças uns dos outros, e acrescentar agentes não adiantou (Anthropic (abre em outra aba)).

Um terceiro ângulo vem de um estudo do Google Research com 180 configurações de agentes. Com coordenação central, o desempenho em uma tarefa paralelizável melhorou 80,9% sobre um agente só, enquanto em uma tarefa de planejamento sequencial todas as variantes multiagente pioraram entre 39% e 70%. Agentes paralelos sem coordenação amplificaram o erro em 17,2 vezes, e com um orquestrador esse número caiu para 4,4 (Google Research (abre em outra aba)). Vale dizer que nenhum dos quatro benchmarks desse estudo é de programação, então ele informa o desenho e não prova nada sobre código.

Duas ressalvas sobre essas fontes. Cursor e Anthropic vendem ferramentas e modelos, e a própria Síntese trabalha com modelos da Anthropic, então lemos esses dois relatos como o que eles viveram e não como medição independente. E nenhum dos dois compara contra um baseline sem paralelo, o que quer dizer que nenhum entrega um fator de aceleração para código. O que as três fontes entregam é uma pista sobre onde o paralelo trava, e todas apontam para o mesmo lugar, que é o quanto o trabalho se divide sem que as partes se toquem e a existência de alguém, ou algo, que coordene.

Em suma, foi dessa leitura aí que saiu o Playmaker.


Dois problemas que a conversa não resolve

Quem calcula o que pode rodar junto

Dizer que três tarefas podem rodar em paralelo parece simples até você escrever as condições. Cada uma precisa depender só de coisas já mergeadas, nenhuma pode editar o mesmo arquivo que outra em andamento, nenhuma pode disputar um arquivo compartilhado como o lockfile ou o roteador, nenhuma pode precisar do mesmo recurso exclusivo (uma porta, um banco local, um emulador), e o total em execução tem de caber no teto de workers. Um agente consegue fazer essa conta, e a nossa convicção, sem medição, é que ele a faz bem na maior parte das vezes. O problema é que a conta precisa sair igual na décima rodada, na terceira sessão e depois que o contexto foi compactado, e um erro nela não aparece como erro. Dois workers que editam o mesmo arquivo só mostram o problema no rebase do segundo, bem depois de o primeiro ter sido dado como pronto.

Quem confere o que voltou

O segundo problema é que o worker termina e diz "gates passando". Esse relato é uma afirmação sobre o código, e quem o recebe tem duas saídas, aceitar ou conferir. Conferir significa ler o diff real, ver se o worker ficou dentro dos arquivos que eram dele, rebasear na base atual, rodar os gates de novo e só então fazer o merge. Cada passo é simples, e juntos são exatamente o tipo de coisa que se pula quando o terceiro worker acabou de entregar e o quarto está esperando.

Há ainda um custo que não some. Cada worker é uma sessão separada, com contexto próprio e cota própria na assinatura da CLI que ele usa. Paralelo gasta mais token que uma sessão só, e por isso o Playmaker avisa quantos workers vai iniciar antes de começar.


Antes da ferramenta havia uma regra em texto

A Síntese mantém no Lore, a nossa memória de longo prazo compartilhada entre pessoas e agentes, uma regra chamada parallel-run. Ela diz que uma rodada paralela tem um gerente, que é o agente com quem a pessoa falou e que nunca implementa tarefa, e vários workers, cada um com uma tarefa, um worktree e uma branch. Diz como calcular o conjunto pronto, como limitar o lote (quatro de cada vez por padrão), como o gerente revisa, rebaseia, roda os gates e faz o merge com fast-forward, e que depois de duas rodadas falhas a tarefa estaciona em ReFix com o problema escrito.

Uma regra em texto funciona porque o agente a lê e a segue. Ela também deixa a aritmética por conta de quem lê, a cada rodada, e é aí que a nossa convicção (de novo, sem medição) diz que o desenho precisa mudar. Não medimos quantas vezes um agente errou o conjunto pronto seguindo só o texto. O que podemos afirmar é que um script devolve o mesmo conjunto toda vez e que dá para escrever um teste para ele, o que um parágrafo de regra não permite.

O Playmaker é essa regra dividida em duas metades. O que tem resposta certa virou board.mjs, e o que depende de ler e de decidir ficou nas skills que o agente segue.


O Playmaker em uma conversa

O ponto de entrada é o próprio agente. Quando a conversa tem três ou mais tarefas independentes (uma lista de tarefas, um plano, uma spec que se parte em arquivos ou módulos) ele pode se oferecer, uma vez só, e nada começa sem o seu sim, a não ser que você já tenha dito "rodada paralela" ou digitado /sintese-playmaker:plan. A oferta tem um formato fixo, que é este (um exemplo do formato, não de uma rodada medida):

Vejo três tarefas que se dividem em ondas. Proponho assim:
• db: tabela de usuários e migração. Codex. Dono de src/db/ e migrations/.
• api: GET /users com paginação. Claude Code. Depende de db.
• docs: referência da API. Gemini. Espera api ser mergeada.
Até 4 workers ao mesmo tempo, e cada um é uma sessão separada, com contexto e cota próprios. Depois de cada entrega eu faço o rebase, rodo os gates e faço o merge, ou pergunto antes de cada um, como você preferir. Quer que eu comece?

Junto da oferta vêm as perguntas que mudam o comportamento da rodada: se o merge é automático quando os gates passam ou pede confirmação, se o trabalho chega à base por merge local ou por um pull request por tarefa, se a rodada é autônoma (uma tarefa que precisa de algo que só você pode fazer vira pendência em vez de parar tudo) e, quando o Lore está conectado, se a rodada usa memória de projeto.

A resposta vira um board.json em .playmaker/, pasta que o Playmaker exclui do git. Cada tarefa declara os arquivos de que é dona, e é essa lista, e não a descrição da tarefa, que alimenta a conta de colisão:

{ "id": "db",  "provider": "codex",  "owns": ["src/db/", "migrations/"], "deps": [] },
{ "id": "api", "provider": "claude", "owns": ["src/api/users.ts", "src/api/users.test.ts"], "deps": ["db"] }

Daí em diante o laço é curto. board ready calcula o lote, board start cria um worktree e uma branch por tarefa e inicia cada worker em segundo plano, e o monitor do plugin avisa o gerente no instante em que um worker entrega ou falha, para que nada fique em polling dentro da conversa. Quando uma entrega chega, o gerente lê o relatório, olha o diff de verdade, chama o agente revisor se a mudança tem mais que algumas linhas e roda board integrate, que faz o rebase na base atual, roda os gates no worktree do worker, faz o merge com fast-forward e remove o worktree e a branch. A entrega que desbloqueia outras tarefas as inicia na hora, sem esperar o resto do lote. Quando nada mais está rodando nem pronto, o gerente entrega o relatório final.

Quem usa Claude Code acompanha isso em um painel ao lado da conversa, que só lê a pasta .playmaker/:

Playmaker ──────────────────────────────────────────────
2 of 6 merged · base main · up to 3 at once

Running (1)
● api    Codex CLI · 7 min
Delivered, to review (1)
◆ ui     by Gemini CLI                          [ Merge ]
Next (1)
○ docs   waiting for api to be merged
Parked (1)
✗ cache  gate failed: npm test                  [ Retry ]
To test (1)
✓ auth   merged abcdef1                         [ Done ]

Cada botão roda um dos onze comandos (plan, go, board, merge, retry, park, totest, done, stop, scorecard e doctor) exatamente como se você os tivesse digitado, então o gerente continua sendo quem revisa e o único que altera o board.


O que virou código e o que ficou com o gerente

Esta é a divisão que organiza o resto do desenho. Nossa regra de bolso foi que, se a pergunta tem uma resposta certa que um teste consegue conferir, ela vai para o script, e se a resposta depende de ler um diff ou de entender o que a pessoa queria, ela fica com o agente.

Vai para o script (board.mjs)

Fica com o gerente (as skills)

Validar o board: ids, dependências, ciclos e colisões de posse

Decidir se vale oferecer uma rodada paralela

Calcular o lote pronto: dependências mergeadas, sem colisão em arquivos, arquivos compartilhados ou recursos, dentro do teto

Propor a divisão, o provedor de cada tarefa e escrever os briefs

Criar um worktree e uma branch por tarefa e iniciar cada worker

Ler o relatório e o diff, e chamar o revisor

Rebase, gates no worktree, merge com fast-forward, limpeza

Decidir se devolve a entrega, e com que nota

Contar rodadas e estacionar em ReFix depois de duas falhas

Completar o que um plano não diz: arquivos, provedor, gates

Montar o scorecard por provedor e a lista do que falta testar

Escolher o que da memória do projeto entra no brief de cada tarefa

Essa divisão tem uma consequência prática, que é o que dá para testar. Tudo da coluna da esquerda roda em um teste automático com CLIs falsas, sem gastar cota de ninguém. Tudo da coluna da direita depende do modelo, e só uma rodada real mostra como ele se comporta.

Seis decisões de desenho, quase todas contra a pressa

O gerente nunca implementa e só ele integra. Se o gerente também escrevesse código de tarefa, ele passaria a revisar o próprio trabalho, e a revisão virava formalidade. Por isso o worker não faz merge, não toca em outra tarefa e não inicia outros agentes, e o gerente também não corrige uma tarefa estacionada. Depois de duas rodadas falhas ela vai para ReFix com o problema escrito, e quem decide o que fazer é a pessoa.

Dependência significa mergeado. Uma tarefa só é considerada pronta quando tudo de que ela depende já chegou à base, e não quando começou. Começar em cima de trabalho não integrado cria exatamente o conflito que a ferramenta existe para evitar, e custa uma rodada de retrabalho quando o primeiro é devolvido.

O relatório é uma afirmação. Quem roda os gates é o gerente, em um worktree recém-criado, depois do rebase. Isso tem um efeito colateral que a documentação avisa logo na primeira linha dos limites: como o worktree é novo, os gates precisam incluir a instalação das dependências (algo como npm ci && npm test), senão toda integração falha. O comando doctor --gates mostra o problema antes da primeira rodada. Quanto ao agente revisor, ele lê, procura e roda comandos de leitura, e não edita nada, não faz merge e não roda os gates. Ele devolve um veredito (integrar, devolver ou perguntar à pessoa), quantos dos critérios de pronto foram atendidos e achados com arquivo e linha, e trata o relatório do worker e o código como dados, não como instruções, para que um worker não consiga mandá-lo aprovar.

Só a pessoa marca Done. O merge leva a tarefa a To test, com o "como testar" que o worker reportou (ou um escrito pelo gerente a partir do diff). O comando totest lista tudo o que foi mergeado e você ainda precisa testar, como um checklist para uma sentada só, e done marca o que você testou. Nenhum outro caminho muda uma tarefa para Done.

Nenhuma CLI sobe com flag de bypass. Cada uma começa no modo padrão de edição no worktree, sem --yolo, --dangerously-skip-permissions, danger-full-access ou --allow-all-tools. Se você quiser uma dessas flags para uma tarefa, você a nomeia e ela vai no extraArgs daquela tarefa, e o gerente nunca a acrescenta por conta própria. Há mais três travas no mesmo espírito: o worker tem 30 minutos por padrão antes de ser interrompido, a integração se recusa a rodar se a árvore principal não estiver na base ou tiver mudanças não commitadas, e nada é enviado a um remoto sem você pedir.

O brief nunca vai na linha de comando. O worker recebe um prompt curto mandando ler .playmaker/brief.md no seu worktree. A razão é prosaica e veio do Windows, onde aspas e limite de tamanho de linha de comando quebram briefs longos de jeitos difíceis de depurar.


Do plano do Blueprint ao paralelo

Um projeto que passou pelo Blueprint (abre em outra aba) já chega com as tarefas prontas, em um plano por fases e uma spec por tarefa que diz o que ela faz, o que não faz e quando está pronta. O /sintese-playmaker:plan docs/plan.md transforma isso em um board. O board import esboça uma tarefa por spec, com a spec como brief e cada fase depois da anterior, e o gerente completa o que o plano não pode dizer, que são os arquivos que cada tarefa edita, o provedor, os gates e os arquivos compartilhados.

O trecho que mais nos interessa é o último passo. O plano do Blueprint encadeia as fases por inteiro, porque é assim que se descreve uma ordem. Na prática, nem toda tarefa da fase seguinte precisa de toda a fase anterior, e é afrouxar essas dependências onde elas não são reais que cria o paralelismo. Cada worker, ao entregar, preenche as seções de entrega da própria spec, e assim o plano continua sendo o registro do projeto. O importador lê o plano no idioma em que o Blueprint o escreveu, e já testamos com um plano em português.

Lore e pull requests, dois opcionais

O Lore é opcional e o Playmaker funciona igual sem ele. Quando está conectado, a oferta pergunta se a rodada deve usar memória de projeto, e em caso de sim o gerente faz quatro coisas. Antes de iniciar cada worker, busca no Lore o que o projeto já sabe sobre os arquivos daquela tarefa (decisões, gotchas e regras) e coloca o que se aplica no brief, na seção "o que este projeto já sabe", de modo que o worker se beneficia mesmo que a CLI dele não tenha Lore. Durante a rodada, mantém uma página que expira uma semana depois. No fim, grava a retrospectiva e o scorecard por provedor. E, se um mesmo problema derrubou mais de uma tarefa, oferece transformá-lo em uma página de gotcha, que só é escrita se você disser que sim. O scorecard também existe sem Lore, em .playmaker/scorecard.json, e conta por provedor as tarefas mergeadas, as que passaram na primeira rodada, as estacionadas, as rodadas e os minutos. As próprias skills lembram que poucas tarefas não formam uma tendência, e que a oferta deve dizer em quantas se baseia a sugestão de provedor.

O modo pull request é para o projeto que passa por revisão e CI. Em vez de o gerente fazer o merge local, o Playmaker envia a branch da tarefa e abre um PR por tarefa, com título, como testar e o brief. O merge passa a ser do time, nunca do gerente. A tarefa fica em revisão, sem ocupar vaga de worker mas mantendo seus arquivos reservados, e o que depende dela espera. Quando o PR é mergeado, a tarefa vai para To test, e o que ela desbloqueia parte de origin/<base>. Mudanças pedidas, checks vermelhos ou PR fechado mandam a tarefa de volta para outra rodada, com as palavras de quem revisou no brief do próximo worker, e o PR novo fecha o antigo com um link. Precisa de um remoto chamado origin e do GitHub CLI logado, e o doctor confere os dois.


Como testamos

Os testes sobem CLIs de agente falsas, escritas em Node, e conduzem o laço de verdade em repositórios descartáveis. Usar CLIs falsas foi o que nos deixou rodar tudo no mesmo CI em Windows, macOS e Linux sem depender de login nem de cota. O teste do board roda seis tarefas com dependências, uma colisão e um arquivo compartilhado, faz um gate falhar e a tarefa ser refeita, e confere no fim que tudo está em To test, que a principal está limpa e que nenhum worktree ou branch ficou para trás. Há testes separados para o monitor (uma linha por entrega, nunca uma escrita), para sync, reject, stop e retry, para o doctor com seus gates, para o que uma rodada entrega à memória do projeto, para a importação de um plano do Blueprint em português (duas de suas tarefas são executadas, e o "como testar" delas chega à lista), e para o modo PR, que usa um repositório bare local como origem e um GitHub CLI falso, de modo que nada chega ao GitHub.

Isso prova que o laço, as colisões, o rebase, os gates, as rodadas e a limpeza se comportam como descrevemos quando os agentes se comportam como o roteiro manda. Mas não prova como Claude Code, Codex, Gemini, Antigravity ou Copilot de verdade se saem dentro dele.


O que levar mesmo sem usar o Playmaker

Três hábitos que valem para quem coordena agentes à mão, no terminal, com três abas abertas. O primeiro é escrever, para cada tarefa, os arquivos de que ela é dona e tratar qualquer sobreposição como dependência, em vez de torcer para o git resolver. O segundo é nunca iniciar uma tarefa em cima de trabalho que não foi integrado. O terceiro é rodar os gates você mesmo, em uma cópia limpa do repositório e depois do rebase, porque "passou na minha máquina" que vem de um agente tem o mesmo valor que vem de uma pessoa. E se o número de workers que você consegue acompanhar de verdade for dois, comece com dois.


Por que deixamos livre

Deixamos aberto por três razões. A primeira é prática: o que falta verificar depende de combinações de CLI, sistema e hábito que nós não temos todas, e uma comunidade com setups diferentes dos nossos testa isso melhor do que nós sozinhos. A segunda é que o Playmaker é o par do Blueprint, que também é livre, e fazia pouco sentido a parte que planeja ser aberta e a que executa não ser. A terceira é o que ainda não sabemos. Os testes mostram que a mecânica se sustenta, e não mostram o que acontece quando ela encontra a pressa de quem tem um prazo apertado.

Como contribuir. O repositório aceita issues e pull requests, e a revisão é nossa. A contribuição mais útil é uma rodada que deu errado, com o board.json, o board report, a CLI que o worker usou e o que você esperava no lugar. Também queremos saber das flags que não verificamos, rodando em outro sistema ou outra versão de CLI. Se você quer fazer parte de uma comunidade que constrói produtos e aprende fazendo, a candidatura é em sinteselabs.com/comunidade (abre em outra aba).


Como começar

Precisa de Node 22 ou mais novo e de git. São três caminhos.

# 1. Claude Code, pelo terminal (recomendado: é o que traz os hooks e o monitor)
claude plugin marketplace add sinteselabs/Playmaker
claude plugin install sintese-playmaker@sinteselabs-playmaker

# 2. claude.ai, app desktop e Cowork:
#    Customize → Plugins → Add → Add marketplace → sinteselabs/Playmaker

# 3. Qualquer outro agente, numa pasta de projeto
npx playmakerlabs init

Depois, rode /sintese-playmaker:doctor uma vez no projeto. Ele confere Node, git, o board e cada CLI de agente, e --gates roda os seus gates em um worktree novo, que é onde a maior parte das primeiras rodadas quebra. Na sequência, abra o agente na pasta e diga o que quer dividir, ou digite /sintese-playmaker:plan com um arquivo de plano. O init copia as skills com o prefixo playmaker- para .claude/skills/ e .agents/skills/, não sobrescreve nada que já exista e aceita --dry-run para mostrar o que faria sem escrever.


Fontes

Quem escreveu

Escrito por Erick Mendes.

Retrato de Erick Mendes

Erick Mendes

Produto e Capacitação

Sócio da Síntese Labs. Escreve sobre a evolução da Inteligência Artificial no Brasil.

LinkedIn
Comunidade e open sourceInteligência ArtificialProjetos da SínteseAgentes de IAAgentes de códigoDesenvolvimento paraleloOrquestração de agentesPlaymakerInteligência artificialEngenharia de softwareAutomação de códigoClaude CodeOpenAI CodexGemini CLIMultiagentesprogramação com inteligência artificialdesenvolvimento de software com IAferramentas de IA para programaçãoorquestração de agentes de IAsistemas multiagentesdesenvolvimento de software paraleloautomação de programaçãoGit worktreecomo usar agentes de IA para programarcomo executar agentes de IA em paralelocomo coordenar múltiplos agentes de IAconflitos de código com IAferramentas open source de IAPlaymaker Síntese LabsSíntese labsPlaymaker

Continuar lendo

Tem um problema parecido para resolver?

A Síntese constrói software sob medida e capacita times em desenvolvimento agêntico, com cada etapa observável e rastreável.

Falar com a Síntese