Um projeto novo apareceu no Hacker News em 27 de setembro de 2026 chamado TinyAIArena. A proposta é simples: em vez de mais um benchmark com tabela de acertos, você abre o navegador e assiste quatro modelos de linguagem se enfrentando num tabuleiro 8×8. É um Show HN publicado pelo usuário hp6, com código aberto em github.com/hp6/ai-arena.
Este artigo não é sobre se o TinyAIArena é bom ou ruim como benchmark. Isso ainda não dá para afirmar. O artigo é sobre o mecanismo por trás dele, porque a mesma arquitetura aparece em vários projetos parecidos e vale entender de verdade como isso funciona por baixo.
O que foi publicado
TinyAIArena dá às batalhas entre agentes de IA os aparatos familiares de um esporte: um leaderboard, histórico de partidas, replays e um conjunto de controles para avançar frame a frame. O projeto apareceu no Hacker News em 27 de setembro, publicado por um desenvolvedor com o handle hp6. A submissão tinha 80 pontos e 36 comentários no momento em que escrevo.
O site rotula seu leaderboard com nome do modelo, Elo, partidas jogadas, vitórias, taxa de vitória, kills, dano causado e recebido, e colocação média. A tabela de histórico mostra data, vencedor, rounds, ações e kills por lutador. É esse conjunto de sinais que interessa: o que precisa existir por baixo para que essas colunas tenham valor.
Como uma arena de agentes LLM funciona por baixo
A arquitetura típica desse tipo de sistema tem quatro peças que precisam encaixar. Vou passar por cada uma.
1. O motor de jogo determinístico
No centro existe um simulador do jogo em si. No caso do TinyAIArena, é um grid 8×8 com quatro agentes, hit points, dano, movimento e ataques. Esse motor é a única fonte de verdade sobre o estado: onde cada agente está, quanto de vida tem, de quem é o turno, quem já morreu.
É importante que ele seja determinístico. Dado o mesmo estado inicial e a mesma sequência de ações, ele produz exatamente o mesmo resultado. Isso é o que permite o replay funcionar: você não regrava um vídeo, você grava só a sequência de ações e o cliente reconstrói a partida rodando de novo o motor.
2. A ponte entre o motor e o modelo
O modelo de linguagem não vê o grid. Ele vê texto. Alguém precisa traduzir o estado do jogo em algo que o LLM entenda, e traduzir a resposta do LLM em uma ação válida no motor.
Pense num jogo de xadrez por correspondência. O tabuleiro está na casa de um dos jogadores. O outro recebe um cartão descrevendo a posição (peão em e4, cavalo em f3) e responde com uma jogada em notação (Cxe5). Um funcionário dos correios traduz a jogada para o tabuleiro físico e escreve a próxima descrição. A analogia quebra num ponto importante: no xadrez as jogadas legais são um conjunto pequeno e bem definido, num jogo com movimento contínuo e várias ações por turno o espaço de saída é maior e a chance de o modelo produzir uma resposta inválida cresce.
Na prática, essa ponte é implementada como tool calls. O sistema descreve em texto:
Você é o agente RED em (2,4). HP: 80/100.
Outros: BLUE em (5,1) HP:60, GREEN em (7,7) HP:100, YELLOW morto.
Ações disponíveis: move(dx,dy), attack(target), wait().
Sua vez. Responda chamando exatamente uma ferramenta.
E define um schema JSON para a resposta. O modelo emite algo como {"tool": "move", "args": {"dx": 1, "dy": 0}}. A ponte valida esse payload contra o schema, verifica se a ação é legal no estado atual (não pode andar em cima de outro agente, não pode atacar quem está fora do alcance) e só então aplica no motor.
Um projeto irmão, o AI Arena de AyushChangedia, deixa isso explícito ao descrever seu harness: o payload é validado por schema e despachado. Uma chamada malformada é um erro real que o agente tem que se recuperar, não uma exceção. Essa distinção é o coração da coisa. Se você deixa passar chamada quebrada silenciosamente, seu leaderboard mede outra coisa.
3. O gerador de partidas e o ranking Elo
Elo veio do xadrez. A ideia é que cada jogador tem uma pontuação, e depois de cada partida a pontuação sobe ou desce em função da diferença entre o resultado esperado e o resultado real. Se um modelo com Elo 1600 ganha de um com Elo 1400, ele sobe pouco (era esperado). Se perde, cai muito (era muito esperado ganhar).
A fórmula clássica para dois jogadores: novo_elo = elo + K * (resultado - esperado), onde esperado = 1 / (1 + 10^((elo_oponente - elo)/400)). Com quatro jogadores por partida em vez de dois, precisa adaptar. A abordagem mais comum é converter a colocação final (1º, 2º, 3º, 4º) em uma série de resultados dois a dois, ou usar uma variante como TrueSkill.
Elo é uma forma familiar de atualizar rankings depois de resultados competitivos, mas a nota precisa de contexto: as regras do jogo, como os oponentes são selecionados, quantas partidas cada modelo jogou, e se posições iniciais ou times rotacionam. A interface visível do TinyAIArena menciona Elo e mostra categorias de estatísticas de partidas. A documentação disponível não explica a fórmula de rating, o processo de geração de partidas, os provedores de modelo suportados ou o processo de submissão de agentes. Guarde essa informação, ela volta na seção sobre limitações.
4. O gravador e o player de replay
O replay não é um vídeo. É um log estruturado. Para cada frame (ou para cada ação, dependendo do design), o sistema grava o estado do jogo mais a ação escolhida, e opcionalmente o raciocínio do modelo se ele expôs isso. O front-end lê esse log e renderiza. É por isso que o site do TinyAIArena aceita atalhos de teclado (setas para avançar frame, espaço para auto, home/end para começo e fim). O que você está fazendo é caminhar por uma linha de tempo de estados discretos, não fazer scrub num vídeo.
O que isso significa na prática
Se você quer construir uma arena parecida, o esqueleto mínimo tem cinco arquivos: motor de jogo, adapter para o LLM (com schema de tool call), loop de partida, atualizador de Elo, gravador de replay. Cada um faz uma coisa. O mais delicado, na minha experiência, é o adapter.
Um exemplo do loop principal, em pseudocódigo:
state = engine.initial_state(agents)
log = []
while not engine.is_over(state):
agent = state.current_agent
prompt = adapter.render(state, agent)
action = adapter.request_action(agent.model, prompt)
if not engine.is_legal(state, action):
action = engine.default_action() # ou penaliza
state = engine.apply(state, action)
log.append((state.snapshot(), action))
ranking = engine.final_ranking(state)
elo.update(agents, ranking)
storage.save_replay(log)
Quando construí uma extensão de navegador que escrevia direto num CRM, aprendi que essa parte do is_legal não é opcional. Uma chamada de API bem-sucedida (o LLM respondeu 200, o JSON parseou) não diz nada sobre o payload fazer sentido no domínio. Aqui é a mesma coisa: o modelo pode devolver attack(YELLOW) quando YELLOW já morreu, ou move(50,50) num grid 8×8. O motor tem que rejeitar.
Onde quebra
Três problemas concretos aparecem em qualquer arena desse tipo, e valem para o TinyAIArena.
Assimetria de custo. Rodar 100 partidas com quatro modelos cada uma são 400 chamadas de LLM por partida no mínimo (uma por turno por agente vivo), vezes o número de turnos. Um único torneio decente entra na casa de milhares de chamadas. Se você mistura GPT-5 e um modelo local, a conta de latência e dinheiro fica desbalanceada e isso influencia decisões de design (você vai reduzir o contexto? cortar a quantidade de partidas? isso enviesa o Elo).
Prompt como variável escondida. Cada modelo responde melhor a um estilo de prompt diferente. Se você usa o mesmo prompt para todos, está medindo em parte quão bem o prompt casa com cada modelo. Se você adapta o prompt por modelo, está medindo o prompt engineer, não o modelo. Não tem saída limpa, só escolha explícita.
O jogo é um domínio, não um teste geral. Ser bom num grid 8×8 tático não diz que o modelo é bom em raciocínio geral. Diz que é bom em raciocínio espacial de curto horizonte com espaço de ação pequeno. Um replay pode mostrar o que aconteceu dentro de uma partida específica. Uma pontuação Elo pode resumir resultados através de partidas. Nenhum dos dois, sozinho, estabelece que os agentes enfrentaram condições equivalentes ou que o ranking diz muito sobre desempenho além desse jogo.
O que ainda não dá para afirmar
Não sei quais modelos exatamente estão competindo no TinyAIArena hoje, porque a documentação pública não lista. Não sei que variante de Elo é usada com quatro jogadores. Não sei se as posições iniciais são sorteadas ou fixas, o que muda muito o resultado num tabuleiro pequeno. Não sei se cada modelo joga a mesma quantidade de partidas contra os mesmos oponentes. O próximo passo útil para o projeto não é um rótulo de ranking mais elaborado; é detalhe público suficiente para outra pessoa entender como uma partida é produzida e o que a pontuação pode sustentar. Até lá, o valor do site é como demonstração e ferramenta de inspeção, não como benchmark que decide algo.
Como testar isso você mesmo
Um caminho pequeno para experimentar, em um fim de semana:
- Escolha um jogo simples com regras determinísticas e estado observável. Tic-tac-toe estendido, Connect Four, ou um grid 4×4 com dois agentes. Fuja de jogos com informação oculta no primeiro protótipo.
- Implemente o motor em Python puro. Uma função
apply(state, action), umalegal_actions(state), umais_terminal(state), umawinner(state). Sem framework. - Escreva o adapter. Uma função que recebe o estado e devolve um prompt em texto, e outra que recebe a resposta do LLM (use tool calls ou JSON mode) e devolve uma ação estruturada. Valide contra
legal_actionsantes de aplicar. - Rode 10 partidas entre dois modelos diferentes via OpenRouter ou provider parecido. Loge cada turno em um JSON linha a linha.
- Só depois disso pense em Elo. Antes disso, olhe os replays. Você vai ver os modelos fazendo coisas absurdas e vai entender por que o adapter é onde mora a complexidade.
Quando você tiver rodado esse protótipo, olhar para o TinyAIArena vai fazer muito mais sentido, porque você vai reconhecer as mesmas peças e vai saber que perguntas fazer sobre o que ainda não está documentado.





