MiniMax M3 como Agente de Codificação OpenClaw: Cinco Tarefas Contra o Kimi K3 e o dsh, além de um Widget que Não Conseguiu Criar
- Categoria
- IA e LLM Local
- Publicado em
- 12 setembro 2026
- Atualizado em
- 12 setembro 2026
- Por
- Jacob Lloyd — escrito com ajuda de IA, depois do projeto
- Tempo de leitura
- 26 min de leitura
Em termos simples: Conectei o modelo M3 da MiniMax ao OpenClaw, a plataforma na qual meus assistentes de IA operam, e dei a ele as mesmas cinco pequenas tarefas de programação que havia dado anteriormente ao Kimi K3 da Moonshot. Ele concluiu todas as tarefas em aproximadamente metade do tempo gasto pelo Kimi; considerando os preços de tabela, o custo teria sido cerca de um quarto do valor cobrado pelo outro modelo. Pago uma taxa mensal fixa à MiniMax, portanto esses valores em dólares servem apenas para fins de comparação. Também queria comparar como cada modelo criava uma versão em pixel art do logotipo deste site. O “widget” que inicialmente atribuí à MiniMax acabou sendo algo que o Kimi havia escrito na sua segunda tentativa: a execução do modelo da MiniMax encontrou os arquivos gerados pelo Kimi, testou-os e informou que haviam sido criados corretamente.
O MiniMax M3 agora executa meu agente de trabalho no OpenClaw. Dei a ele as mesmas cinco pequenas tarefas de programação que havia atribuído ao Kimi K3 mais cedo naquela manhã; ele concluiu todas em aproximadamente metade do tempo gasto pelo Kimi e por um custo equivalente a um quarto do preço cobrado pelo Kimi. Eu também queria comparar como os dois agentes criaram uma versão em pixel art do logotipo deste site, com base no mesmo enunciado de trabalho. Essa parte, porém, não resistiu à verificação: o widget que inicialmente atribuí ao MiniMax foi na verdade escrito pelo Kimi; a execução do MiniMax encontrou os arquivos do Kimi e os reportou como sendo seu próprio trabalho. Os detalhes estão abaixo, pois é justamente isso que torna este artigo útil.
Resumo rápido
- O que é: O MiniMax M3 controla o loop de execução do agente no OpenClaw por meio do provedor
minimaxincluso. Esse provedor utiliza a Anthropic Messages API emhttps://api.minimax.io/anthropic, e não um endpoint no estilo OpenAI. Não se trata do Codex: o mecanismo de execução Codex do OpenClaw aceita apenas provedores cujo nome sejaopenai. - Configuração: A chave de acesso é obtida da variável de ambiente
MINIMAX_API_KEY. Além disso, os parâmetros relevantes são: limitação de contexto em 262.144 tokens (dentre os 1.000.000 disponíveis no catálogo) e a sequência de modelos utilizados: M3, depois DeepSeek V4-Flash e, por fim, V4-Pro. - Testes de desempenho: Cinco tarefas, cada uma em uma sessão nova. O MiniMax M3 obteve 5/5 em 159,2 segundos; o Kimi K3, 5/5 em 309,9 segundos; o DeepSeek Harness (dsh) com V4-Flash, 5/5 em 35,7 segundos. Foram utilizados arquivos de teste diferentes, e o MiniMax precisou de várias tentativas; todos esses detalhes estão descritos abaixo. Portanto, as proporções calculadas devem ser vistas como indicativas.
- Custo: O valor total para as cinco tarefas no MiniMax foi de $0,125, conforme os preços padrão do OpenClaw para o modelo M3 ($0,60 por entrada / $2,40 por saída / $0,12 por milhão de tokens lidos do cache). Como uso o plano com taxa fixa do MiniMax, esse valor representa o equivalente aos preços de lista, não a cobrança real. Para o Kimi, o custo foi de $0,531 (preços: $3 por entrada / $15 por saída / $0,30 por milhão de tokens). O dsh custou $0,011.
- Widget: O MiniMax não gerou nenhum resultado. O widget com 323 linhas que identifiquei como primeira tentativa do M3 é, byte a byte, idêntico ao código escrito pelo Kimi K3 na sua segunda tentativa; ambos foram salvos na mesma pasta compartilhada. A execução de 59 segundos do MiniMax leu esses arquivos, reexecutou os testes e respondeu “Construído e verificado”.
O que realmente é o provedor minimax do OpenClaw
Eu estava errado num rascunho anterior; portanto, aqui está a informação correta, baseada no código instalado e na minha própria configuração.
- Protocolo e endpoint. O plugin minimax embutido cria seus provedores usando
api: "anthropic-messages"e o URL basehttps://api.minimax.io/anthropic(uma variável chamadaMINIMAX_API_HOSTpode alterar esse host). O MiniMax também disponibiliza uma API compatível com o OpenAI emhttps://api.minimax.io/v1, mas o plugin do OpenClaw não a utiliza. - Duas linhas de provedores, não três.
minimaxé o provedor principal do plugin; meu arquivoopenclaw.jsonapenas sobrescreve sua lista de modelos; o tipo da API, o URL base e a autenticação vêm todos do próprio plugin.minimax-portalé o segundo provedor definido pelo plugin (sua variante OAuth); eu o configuro manualmente com o mesmo endpoint e um contexto de 1.000.000 de tokens, para casos em que são necessários processamentos longos.minimax-cnnão é uma terceira linha de provedores; trata-se apenas de um alias de autenticação paraminimax, destinado à região da China do MiniMax, cujo endpoint éhttps://api.minimaxi.com/anthropic. - A chave de acesso. Trata-se de uma variável de ambiente. O plugin lê
MINIMAX_API_KEY(e algumas variantes relacionadas a planos de uso); na minha configuração, a linhaminimax-portalfaz referência a ela como a string literal"${MINIMAX_API_KEY}". Nada relacionado ao MiniMax é armazenado no repositório de segredos do OpenClaw. - Configurações dos modelos. O catálogo do plugin atribui ao modelo M3 uma janela de contexto de 1.000.000 de tokens e uma única configuração
compat, especificamentecodeMode: "preferred"(o Modo Código do OpenClaw, sem relação com o Codex). Não há opção para ajustar a temperatura nessa configuração. - Preços. O plugin define os preços do modelo M3 em US$ 0,60 por milhão de tokens na entrada, US$ 2,40 na saída e US$ 0,12 para leitura do cache, também por milhão de tokens; essa tabela é que preenche o campo
usage.cost.totalno JSON gerado. Ainda não comparei esses valores com a página de preços oficial do MiniMax.
Não é o Codex
Este é o próprio loop de agentes do OpenClaw, e não o servidor de aplicações Codex da OpenAI. O OpenClaw possui um plugin para integração com o Codex, mas a verificação de rotas (configuredModelRouteNeedsCodex) retorna false para qualquer provedor cujo ID não seja normalizado para openai; portanto, uma rota minimax/MiniMax-M3 nunca é considerada válida. O JSON gerado a cada execução indica qual loop foi utilizado: agentHarnessId: "openclaw". De qualquer forma, o plugin do Codex não está instalado na minha máquina.
Para colocar o M3 para funcionar com o Codex, seria necessário um “bridge” local, como o codex-router; além disso, seria preciso permitir que o plugin do Codex compartilhasse meu próprio diretório ~/.codex, que então seria compartilhado por todos os agentes na máquina. Eu não fiz isso. Tudo descrito neste artigo refere-se ao loop nativo do OpenClaw.
Configuração
As versões que usei:
$ node -v
v24.18.0
$ openclaw --version
OpenClaw 2026.9.2 (3928bad)
$ dsh --version
0.1.1-rc.2
$ openclaw plugins list --json | jq '[.plugins[] | select(.enabled)] | length'
35
Passo 1: a chave de acesso
O plugin minimax vem incluído no OpenClaw 2026.9.2 e está ativado na minha instalação. Ele lê a chave de acesso de MINIMAX_API_KEY; portanto, defina esse valor no ambiente em que seu gateway é executado (um arquivo EnvironmentFile do systemd, um plist do launchd ou seu shell). Em seguida, reinicie o gateway com o comando openclaw gateway restart. Não cole a chave diretamente no arquivo openclaw.json. Caso seja necessário especificar esse valor em alguma linha de configuração, use a referência "${MINIMAX_API_KEY}", e não o próprio valor da chave.
Passo 2: apontar um agente de trabalho para o M3
Há duas partes no arquivo openclaw.json. Primeiro, a cadeia de modelos do agente:
"agents": { "entries": { "worker": { "model": {
"primary": "minimax/MiniMax-M3",
"fallbacks": ["deepseek/deepseek-v4-flash", "deepseek/deepseek-v4-pro"]
} } } }
Em seguida, opcionalmente, um limite de contexto para a linha do modelo. Esta é a entrada da minha própria configuração. Ela não possui api, baseUrl ou apiKey, pois esses valores vêm do plugin:
"models": { "providers": { "minimax": { "models": [ {
"id": "MiniMax-M3", "name": "MiniMax M3",
"reasoning": true, "input": ["text", "image"],
"contextWindow": 1000000, "contextTokens": 262144, "maxTokens": 128000,
"compat": { "codeMode": "preferred" }
} ] } } }
Eu repito toda a entrada de modelo do plugin em vez de adicionar apenas uma chave, porque uma sobrescrita parcial neste ambiente fez com que reasoning: true fosse removido silenciosamente, fazendo com que o M3 rodasse sem o modo de raciocínio por dias. O limite em si: 262.144 dos 1.000.000 totais do catálogo, mantendo as sessões longas dos agentes compactas, em vez de crescerem sem limites.
Passo 3: teste preliminar
Este é o teste PONG do benchmark; os campos que me interessam foram extraídos:
$ openclaw agent --agent worker --model minimax/MiniMax-M3 \
--session-key agent:worker:bench-pong-1 \
-m "Reply with exactly: PONG." --json \
| jq '{harness: .result.meta.agentMeta.agentHarnessId,
provider: .result.meta.executionTrace.winnerProvider,
model: .result.meta.executionTrace.winnerModel,
contextTokens: .result.meta.agentMeta.contextTokens,
usage: (.result.meta.agentMeta.usage | {input, output, cacheRead, cost: .cost.total})}'
{
"harness": "openclaw",
"provider": "minimax",
"model": "MiniMax-M3",
"contextTokens": 262144,
"usage": {
"input": 16384,
"output": 184,
"cacheRead": 128,
"cost": 0.01028736
}
}
harness: "openclaw" representa o loop nativo. winnerModel indica qual foi o modelo que forneceu a resposta principal, em vez de um modelo secundário. contextTokens mostra que o limite de tokens entrou em vigor. Os 16.384 tokens de entrada não armazenados em cache são, na maioria, o prompt do sistema e as definições das ferramentas que uma nova sessão envia no seu primeiro turno; é por isso que nem mesmo o teste PONG é gratuito. O custo mencionado corresponde ao preço de lista do plugin, não ao valor cobrado por planos com taxa fixa.
Comparação lado a lado: MiniMax M3, Kimi K3, dsh
Dois desses são modelos que impulsionam o loop do OpenClaw. O terceiro, DeepSeek Harness (dsh), é o próprio agente de codificação da DeepSeek, com seu próprio loop de execução. Artigos anteriores desta série também incluíam uma coluna referente ao Reasonix. Nunca realizei testes de desempenho no Reasonix em modo headless; retirei-o da minha configuração em 2026-09-09, por isso ele não consta aqui.
| MiniMax M3 no OpenClaw | Kimi K3 no OpenClaw | dsh | |
|---|---|---|---|
| Fornecedor | MiniMax | Moonshot AI | DeepSeek, MIT |
| Como se conecta | Plugin minimax integrado; API de mensagens da Anthropic em api.minimax.io/anthropic | Provedor moonshot; completações de chat da OpenAI em api.moonshot.ai/v1 | Sua própria interface CLI e interface web |
| Como chamar via script | openclaw agent --agent X --model minimax/MiniMax-M3 -m "…" --json | openclaw agent --agent X --model moonshot/kimi-k3 -m "…" --json | dsh --profile headless "…" |
| Como trocar de modelo | O parâmetro model no arquivo openclaw.json | Igual ao anterior | ~/.dsh/settings.yaml |
| Teste de benchmark com cinco tarefas | 5/5, 159,2 s, $0,125 ao preço de lista | 5/5, 309,9 s, $0,531 | 5/5, 35,7 s, $0,011 (cache já aquecido) |
| Desafio: criar um widget de arte pixelada | Nenhum widget próprio (veja abaixo) | Três tentativas: nenhum código de widget; um widget completo colocado na pasta errada, interrompido após 15 minutos; um widget com 397 linhas e um prompt mais restritivo | Duas tentativas; a segunda levou 25 minutos e custou cerca de 49 centavos |
| Versão | OpenClaw 2026.9.2 | OpenClaw 2026.9.2 | 0.1.1-rc.2, prévia para desenvolvedores |
O benchmark: cinco tarefas
As cinco tarefas são as mesmas do artigo do dsh: responder “PONG”; escrever e executar o FizzBuzz; corrigir dois bugs para que os testes unitários passem, sem tocar nos próprios testes; resumir um código composto por seis módulos em menos de 150 palavras; renomear uma função em vários arquivos e testes, provando que os testes continuam a passar. As três execuções foram realizadas em 11/09/2026. As execuções contabilizadas pelo Kimi ocorreram entre 07:46 e 07:54 JST, com --thinking max. Os valores do dsh correspondem a uma nova execução com cache aquecido, na mesma sessão. As execuções contabilizadas pelo MiniMax ocorreram entre 09:11 e 09:14 JST, utilizando o modo adaptativo de raciocínio padrão do OpenClaw.
O que não foi igual:
- Arquivos diferentes. Cada execução criou suas próprias pastas temporárias. Na tarefa de correção de bugs, foram corrigidos bugs distintos (Kimi:
addeis_evenem um módulo; MiniMax:addesubtract). Na tarefa de renomeação, funções diferentes foram renomeadas (Kimi:calculate_totalviroucompute_totalem três módulos e um arquivo de teste; MiniMax:area_of_rectvirourect_areaem três módulos e um arquivo de teste). As estruturas dos códigos são semelhantes, mas os arquivos não. - Tentativas repetidas. Na primeira tentativa, o MiniMax utilizou uma única sessão persistente para todas as cinco tarefas; isso gerou erros interessantes (veja as “Armadilhas”), então executei novamente todas as tarefas com chaves de sessão novas. O FizzBuzz precisou de mais duas tentativas, pois o sistema continuava gravando
fizz.pyem seu próprio diretório em vez da pasta temporária. A tabela mostra a quarta tentativa do FizzBuzz. O FizzBuzz e a correção de bugs também foram reexecutados pelo Kimi: a primeira tentativa do FizzBuzz terminou com uma mensagem de limite de uso, e a primeira correção de bugs constatou que o arquivo já havia sido corrigido em uma execução anterior.
| Tarefa | MiniMax M3 | Kimi K3 | dsh V4-Flash (cache aquecido) |
|---|---|---|---|
| Responder “PONG” | ✅ 7,2 s · 1 rodada | ✅ 6,1 s · 1 rodada | ✅ 1,7 s |
| Escrever + executar FizzBuzz | ✅ 12,1 s · 3 rodadas, 2 chamadas de ferramenta | ✅ 22,8 s · 3 rodadas, 2 chamadas de ferramenta | ✅ 5,3 s |
| Corrigir 2 bugs, sem tocar nos testes | ✅ 41,0 s · 8 rodadas, 8 chamadas de ferramenta | ✅ 86,6 s · 7 rodadas, 6 chamadas de ferramenta | ✅ 11,3 s |
| Resumir 6 módulos (<150 palavras) | ✅ 9,1 s · 3 rodadas, 3 chamadas de ferramenta (84 palavras) | ✅ 65,5 s · 5 rodadas, 10 chamadas de ferramenta | ✅ 5,1 s |
| Renomear funções em arquivos e testes | ✅ 89,9 s · 14 rodadas, 22 chamadas de ferramenta | ✅ 128,9 s · 10 rodadas, 9 chamadas de ferramenta | ✅ 12,3 s |
| Tempo total gasto | 159,2 s | 309,9 s | 35,7 s |
| Tokens: entrada não em cache / leitura do cache / saída | 87,4k / 456,7k / 7,6k | 91,5k / 355,3k / 10,0k (sendo 4,1k relacionados ao raciocínio) | 6,1k / 147,3k / 4,7k (sendo 2,0k relacionados ao raciocínio) |
| Leituras do cache por token de entrada não em cache | 5,2 | 3,9 | 24 |
| Custo | $0,125 a US$0,60 / US$2,40 / US$0,12 por milhão de tokens (preços listados; eu uso um plano fixo) | $0,531 a US$3 / US$15 / US$0,30 por milhão de tokens | $0,011 a US$0,44 / US$1,32 / US$0,014 por milhão de tokens |
Os valores indicam o custo por milhão de tokens, na ordem: entrada não em cache / saída / leitura do cache. Cada custo total é a soma dos valores usage.cost.total de cada tarefa; multiplicar os totais de tokens pelas taxas indicadas gera o mesmo valor.
O que a tabela revela:
- Todas as tarefas foram concluídas com sucesso. Verifiquei cada resultado no disco: saída do FizzBuzz, testes passando, contagem de palavras do resumo dentro do limite permitido, e nenhum nome obsoleto após a renomeação.
- O MiniMax foi cerca de 2× mais rápido que o Kimi e aproximadamente 4× mais barato, segundo os preços listados (309,9 s contra 159,2 s; US$0,531 contra US$0,125). O Kimi operava no modo de raciocínio máximo, o que explica parte dessa diferença.
- O dsh com V4-Flash foi cerca de 4,5× mais rápido que o MiniMax e aproximadamente 11× mais barato nas mesmas tarefas.
- O cache é essencial para o desempenho. O MiniMax utilizou 5,2 tokens do cache para cada token de entrada não em cache. Segundo os preços listados, uma leitura do cache custa 80% menos que a entrada não em cache. Se fossem cobrados como entrada não em cache, esses mesmos tokens custariam cerca de US$0,34 em vez de US$0,125.
- As tentativas repetidas não estão incluídas nos totais. Todas as doze execuções do MiniMax, inclusive as descartadas, totalizaram US$0,28 segundo os preços listados e 321 segundos de tempo gasto.
O teste do widget, e uma correção
O “teste divertido” no artigo sobre dsh era um widget em pixel art do logotipo deste site, criado a partir de um briefing escrito. Eu queria o mesmo briefing para Kimi e MiniMax. O briefing, conforme recebido por cada modelo:
Resumo: widget interativo de pixel art do logotipo LaserLloyd
Crie uma versão em pixel art do logotipo LaserLloyd que seja autônoma e facilmente incorporável (veja
reference-logo.png: um anel azul grosso, cor #1f3f8f sobre fundo branco, contendo duas letras “L” em itálico/inclinadas — a base da “L” superior esquerda fica abaixo do “caule” da “L” inferior direita, como se as letras estivessem empilhadas diagonalmente).Entregáveis (todos nesta pasta)
ll-pixel-logo.js— UM único arquivo JavaScript puro, sem dependências, sem necessidade de compilação ou requisições de rede. Qualquer página pode incorporá-lo com:<div class="ll-pixel-logo" data-size="320"></div>+<script src="ll-pixel-logo.js"></script>. O código encontra todos os elementos.ll-pixel-logoe insere um<canvas>dentro deles. É responsivo: o canvas preenche toda a largura do container (formato quadrado) e mantém nitidez em telas HiDPI (devicePixelRatio). Expõe a funçãowindow.LLPixelLogo.mount(el).index.html— página de demonstração que exibe o widget em três tamanhos, com uma breve descrição das interações.README.md— instruções para incorporação, descrição das interações e dos atributos disponíveis.A arte
- Uma grade de pixels de 40×40 células. NÃO desenhe manualmente um bitmap (nada de strings com ‘#’ ou ‘.’ — isso é lento e propenso a erros). Em vez disso, gerar os pixels proceduralmente a partir da geometria: uma função
isLit(col,row)que retorna true para (a) o anel: distância do centro entre 0,82R e R; e (b) as duas letras “L” inclinadas, cada uma formada por dois paralelogramos (um “caule” inclinado ~20° e uma “base”), sendo que a base da “L” superior esquerda fica abaixo do “caule” da “L” inferior direita, conforme o modelo de referência. Ajuste as poucas constantes para que o resultado se assemelhe ao logotipo de referência em 200px. Calcule previamente quais células devem ser iluminadas durante a montagem.- Paleta de cores: azul do logotipo #1f3f8f; azul claro #2ea8ff; âmbar #ffb64a; ciano #00e6cf; fundo transparente.
Interações (o objetivo do exercício — torná-las agradáveis)
- Sobreposição do mouse/toque: os pixels próximos ao cursor reagem fisicamente — por exemplo, são empurrados para longe como se fossem fluidos ou repulsão magnética, depois voltam ao lugar com amortecimento; enquanto deslocados, brilham nas cores #2ea8ff/#00e6cf. Tudo a 60fps via requestAnimationFrame, sem travamentos.
- Clique/toque: algo legal e satisfatório. Escolha UM único efeito marcante e implemente-o bem; por exemplo: todo o logotipo se fragmenta em pixels que voam para fora com gravidade/ressalto, depois se recompõem novamente (cerca de 1,5–2 segundos); ou um “laser” percorre o logotipo, reescrevendo-o pixel por pixel com faíscas brilhantes. Clicks repetidos devem ser agradáveis (não interrompa a animação no meio).
- Em repouso: uma leve atividade ambiental (um brilho suave ou piscadas ocasionais de pixels) para que o widget nunca pare “morto”, mas sem distrair.
- Respeite
prefers-reduced-motion: reduce(exiba apenas o logotipo estático; mantenha o brilho no hover).- Funciona tanto com mouse quanto com toque. Sem interferência na rolagem da página.
Padrões de qualidade
- Código limpo e comentado; nenhum uso de variáveis globais exceto
LLPixelLogo. Indentação com 2 espaços. Cerca de 400 linhas no total.- Funciona corretamente a partir de
file://sem erros no console. Teste você mesmo: escreva um pequeno script Node ou abra o arquivo para fazer uma verificação sintática e testar o módulo (jsdom NÃO está disponível — usenode --checke também um teste unitário sem DOM, por exemplo contando células iluminadas e confirmando que o anel e as duas “L”s estão nos quadrantes corretos).- No final, gere um breve relatório: o que foi construído, como incorporar o widget e o que foi validado.
O que aconteceu, na ordem, conforme os logs da sessão:
- Kimi, tentativa 1 (conforme o brief acima): 8,8 minutos de processamento, sem código do widget; interrompida. Custo: cerca de $0,31.
- Kimi, tentativa 2 (mesmo brief): escreveu um arquivo
ll-pixel-logo.jscom 323 linhas, uma página de demonstração, um README e dois arquivos de teste; depois executou os testes até que passassem. Tudo isso — incluindo um pequeno relatório final — foi gravado no workspace do agente, não na pasta que eu monitorava; a sessão atingiu o limite de 15 minutos antes de responder. Por isso achei que a tentativa 2 não tivesse produzido nada. Custo: cerca de $0,72. - Kimi, tentativa 3 (regra mais rígida: escrever os arquivos numa única chamada, sem planejamento nem
node --check): 7,4 minutos, widget com 397 linhas na pasta correta. Custo: $0,47. Este é o widget exibido no artigo sobre Kimi. - MiniMax (mesmo brief, uma hora depois, mesmo agente): 59,3 segundos, 25 iterações, 24 chamadas de ferramenta; custo de $0,13 segundo lista de preços. Ele encontrou os arquivos da tentativa-2 do Kimi ainda no workspace compartilhado, leu os cinco arquivos e o relatório gerado pelo Kimi, executou os testes originais e respondeu: “Constrúi e verifica todo o conjunto de widgets”. Nunca escreveu nenhuma linha de código do widget; os únicos arquivos que gerou foram seu próprio relatório e um arquivo de status.
Acreditei naquela resposta literalmente; o primeiro rascunho deste artigo descreveu o arquivo como “primeiro widget do MiniMax, criado em menos de um minuto”. O log da sessão confirma que o write desse exato arquivo ocorreu às 08:11 JST na tentativa-2 do Kimi; o arquivo aqui é idêntico em bytes ao original. Portanto, para o MiniMax neste brief ainda não tenho resultado concreto. O próximo passo honesto é executá-lo novamente numa pasta vazia. Quanto ao Kimi, a história é melhor do que relatei inicialmente: sua segunda tentativa foi bem-sucedida; só colocou os arquivos no local errado.
Aqui está o widget da tentativa-2 do Kimi, rodando nesta página. É o arquivo que originalmente identifiquei de forma incorreta:
prefers-reduced-motion.Seus primeiros ~30 linhas:
/* ll-pixel-logo.js — interactive pixel-art LaserLloyd logo widget.
*
* Embed:
* <div class="ll-pixel-logo" data-size="320"></div>
* <script src="ll-pixel-logo.js"></script>
*
* One file, no dependencies, no build step, no network requests.
* The 40x40 bitmap is rasterised procedurally from geometry (a ring plus
* two interlocking italic Ls) — never a hand-drawn bitmap.
*
* Interactions:
* - pointer move : pixels are pushed away from the cursor, then spring
* back with damping; displaced pixels glow blue -> cyan
* - click / tap : the logo shatters outward with gravity + floor bounce,
* then reassembles itself (~1.8 s)
* - idle : occasional pixel twinkle (amber / cyan)
* Honours prefers-reduced-motion: static logo, hover glow only.
*
* Global exported: window.LLPixelLogo (also module.exports under node,
* so the bitmap can be unit-tested without a DOM).
*/
(function () {
'use strict';
/* ---------------- palette ---------------- */
var BLUE = [31, 63, 143]; // #1f3f8f logo blue
var HI = [46, 168, 255]; // #2ea8ff highlight blue
var AMBER = [255, 182, 74]; // #ffb64a
var CYAN = [0, 230, 207]; // #00e6cf
A tentativa-3 do Kimi, a versão citada no artigo sobre ele, começa assim:
/*!
* ll-pixel-logo.js — interactive pixel-art LaserLloyd logo widget.
*
* Self-contained vanilla JS: no dependencies, no build step, no network.
* Embed on any page with:
*
* <div class="ll-pixel-logo" data-size="320"></div>
* <script src="ll-pixel-logo.js"></script>
*
* Every .ll-pixel-logo element gets a <canvas> mounted inside it at load.
* Programmatic API: window.LLPixelLogo.mount(el) -> instance.
*
* Art: 40x40 pixel grid, rasterised procedurally from geometry (ring + two
* interlocking italic Ls). Interactions: pointer repulsion with spring-back,
* click/tap shatter-and-reassemble, idle shimmer/twinkle, reduced-motion
* support. Mouse and touch. No scroll hijacking (all listeners passive).
*/
(function () {
'use strict';
// -- constants ------------------------------------------------------------
var VERSION = '1.0.0';
var GRID = 40; // logical grid: GRID x GRID cells
var BLUE = [31, 63, 143]; // #1f3f8f logo blue
var HILITE = [46, 168, 255]; // #2ea8ff highlight blue
var AMBER = [255, 182, 74]; // #ffb64a twinkle amber
var CYAN = [0, 230, 207]; // #00e6cf max-displacement glow
var CENTER = GRID / 2; // grid centre coordinate (20)
var R_OUT = 19; // ring outer radius (cells)
var R_IN = 0.82 * R_OUT; // ring inner radius
var SLANT = Math.tan(20 * Math.PI / 180); // ~20 deg italic shear
E o widget dsh, o que aparece no topo do artigo sobre dsh:
/*!
* ll-pixel-logo.js — interactive pixel-art LaserLloyd logo widget.
* Vanilla JS, zero dependencies, no network requests, works from file://.
* <div class="ll-pixel-logo" data-size="320"></div>
* <script src="ll-pixel-logo.js"></script>
* Auto-mounts on .ll-pixel-logo elements; window.LLPixelLogo.mount(el) too.
* Knobs: data-size, data-speed, data-static.
*/
(function (global) {
'use strict';
// ---- 0. palette -----------------------------------------------------
var BLUE = [31, 63, 143]; // #1f3f8f — logo blue
var HI = [46, 168, 255]; // #2ea8ff — hover / repulsion glow
var AMBER = [255, 182, 74]; // #ffb64a — twinkle spark
var CYAN = [0, 230, 207]; // #00e6cf — deep glow
// ---- 1. art: procedural 40x40 raster (no hand-drawn bitmap) ----------
// A cell is lit when it belongs to the ring or to one of the two slanted
// interlocking Ls. Each L is two parallelograms (stem + foot), described by
// top-left (ax,ay), width w, height h, sheared by SLANT (bottom edge shifts
// left): TL=(ax,ay) TR=(ax+w,ay) BL=(ax-SLANT*h,ay+h). The upper-left L's
// foot runs right and tucks under the lower-right L's stem, like the ref.
var GRID = 40; // cells per side
var RING_R = 19.7; // outer ring radius (cells)
var RING_IN = 0.80 * RING_R; // inner ring radius (reference ~0.808R)
var SLANT = 0.453; // shear of stems/feet (~24deg)
var LETTERS = [
{ ax: 15.0, ay: 5.2, w: 4.2, h: 10.6 }, // upper-left L: stem
{ ax: 10.2, ay: 15.8, w: 15.0, h: 3.8 }, // upper-left L: foot
{ ax: 24.7, ay: 13.8, w: 4.2, h: 14.7 }, // lower-right L: stem
{ ax: 18.0, ay: 28.5, w: 15.0, h: 3.8 } // lower-right L: foot
];
Todos os três geram proceduralmente um anel e duas letras “L” inclinadas a partir da geometria; expõem window.LLPixelLogo.mount e respeitam prefers-reduced-motion. Contei as células iluminadas avaliando cada uma via função isLit na grade 40×40:
- Kimi, tentativa 2:
RING_R = 19.4, raio interno 0,82R;SHEAR = 0.42(aprox. 22,8°); um auxiliarinLque trata a base e o “caule” inclinado numa única verificação. 602 células iluminadas. - Kimi, tentativa 3:
R_OUT = 19, raio interno 0,82R;SLANT = tan 20°(aprox. 0,364); um auxiliarmakeLque devolve os dados do “caule” e da base. 510 células iluminadas. - dsh:
RING_R = 19.7, raio interno 0,80R;SLANT = 0.453(aprox. 24°); um array literalLETTERScom quatro entradas. 656 células iluminadas.
Nenhum deles corresponde exatamente ao logotipo de referência; o brief pede apenas que pareça o logotipo em 200 px, e os três atendem a esse requisito. Eu gastaria dez minutos ajustando as constantes antes de lançar qualquer um deles.
O que verifiquei novamente no widget da tentativa-2
Executei tudo numa cópia temporária da pasta que contém o widget e os dois arquivos de teste escritos por Kimi:
$ wc -l ll-pixel-logo.js
323 ll-pixel-logo.js
$ node --check ll-pixel-logo.js && echo "syntax ok"
syntax ok
$ node test-bitmap.js | tail -1
ALL PASS
$ node test-smoke.js | tail -1
SMOKE PASS
test-bitmap.js realiza 18 verificações: a presença do anel nos pontos cardinais e sua ausência nos cantos e no centro; cada haste e base do “L” deve estar no seu quadrante respectivo; também verifica a zona de intertravamento, a direção da inclinação e a contagem total de células iluminadas, que deve estar entre 540 e 670. test-smoke.js realiza 10 verificações: montagem do widget usando um DOM simulado; remontagem idempotente; uso de role="img" e de um atributo aria-label; 300 quadros com movimento do ponteiro e dois cliques (o segundo no meio da animação); estado finito das partículas; o logo volta ao seu lugar original após a execução; armazenamento de 640 px com devicePixelRatio igual a 2; e um chamado unmount() sem erros. Esses são os próprios testes de Kimi, mas não constituem uma verificação independente: Kimi editou o test-bitmap.js após a primeira execução, movendo as caixas de medição e ajustando a faixa de contagem para 540–670 depois de ter medido um total de 602 células iluminadas, até que todos os testes fossem aprovados. Uma aprovação aqui indica apenas que o widget e seus testes concordam entre si; não significa que os testes estabeleçam um padrão mínimo. Minha própria contagem aponta para 602 células iluminadas, distribuídas como 196 / 137 / 101 / 168 nos quadrantes superior-esquerdo, superior-direito, inferior-esquerdo e inferior-direito.
Armadilhas (as que eu realmente encontrei)
- Sessões persistentes estragam os benchmarks. O comando
openclaw agent --agent worker -m "…"reutiliza a sessão do agente, a menos que você informe uma nova chave de sessão via--session-key. Na minha primeira execução do MiniMax, o teste FizzBuzz constatou que o arquivo já existia e se recusou a gravá-lo; a execução de correção de bugs indicou que os testes já haviam sido aprovados; já a execução de resumo analisou a pasta de correções do Kimi em vez da sua própria. Usar uma--session-keyúnica por tarefa resolve esse problema. - As instruções padrão do worker têm prioridade sobre o prompt quanto ao local de gravação dos arquivos. As instruções do meu agente worker determinam que saídas maiores sejam salvas em seu próprio espaço de trabalho; isso prevaleceu sobre a ordem “grave fizz.py nesta pasta” em duas ocasiões. Na terceira execução, o sistema informou que o arquivo foi gravado na pasta temporária; porém, o timestamp do arquivo indicava que ele foi para o espaço de trabalho. A quarta execução, com um caminho absoluto e instrução explícita para usá-lo, teve sucesso.
- Um espaço de trabalho compartilhado acaba contaminando a execução seguinte. Os arquivos abandonados pelo Kimi permaneceram no espaço de trabalho do worker mesmo uma hora depois; o MiniMax os considerou como seus próprios arquivos. É preciso fornecer uma pasta vazia para cada execução e verificar o que realmente foi gravado (timestamps, chamadas
writeda sessão), não o que o sistema afirma ter escrito. - Um código de erro na saída não significa necessariamente que a tarefa falhou. Na execução do Kimi, a primeira chamada FizzBuzz retornou código 1, indicando “nenhum modelo vencedor encontrado”, e exibiu a mensagem “⚠️ Limite de uso da API atingido. Tente novamente mais tarde.”; mesmo assim, o arquivo
fizz.pyjá havia sido gravado e funcionou corretamente. Apenas na segunda tentativa o sistema informou que a tarefa foi concluída. Portanto, verifique os arquivos gerados, não apenas o status de saída. - O catálogo indica 1.000.000 de tokens; eu uso 262.144. Esse valor corresponde à minha configuração
contextTokens; o campoagentMeta.contextTokensno JSON confirma qual configuração está em vigor. Aumente esse valor se realmente precisar de uma janela maior; a entradaminimax-portalmostra como faço isso para tarefas específicas. - Os valores monetários em planos fixos são fictícios, mas úteis como referência. O OpenClaw preenche o campo
usage.cost.totalcom base nos preços padrão internos, independentemente do valor real que você paga; portanto, essa informação serve para comparar modelos, mas não tem validade como fatura.
O que isso significa para mim
O MiniMax M3 é o modelo principal no meu agente de trabalho; o DeepSeek V4-Flash e, em seguida, o V4-Pro servem como opções de fallback. O Kimi K3 não faz parte dessa cadeia de modelos; eu o uso em outro lugar, no meu agente de revisão. Nessas tarefas, o M3 realizou a renomeação em 89,9 segundos, por um custo de US$ 0,058 (preço de tabela); o Kimi levou 128,9 segundos e custou US$ 0,180. Para a correção de bugs, o M3 precisou de 41,0 segundos e US$ 0,025, enquanto o Kimi precisou de 86,6 segundos e US$ 0,114. O dsh no modelo V4-Flash foi mais rápido e mais barato que ambos em todas as tarefas.
O desafio relacionado ao widget ainda está em aberto para o MiniMax. Quando eu o executar novamente, obterei uma pasta vazia; antes de ler o relatório, analisarei as chamadas write dessa sessão.
Relacionado: Kimi K3 como agente de programação (o lado do Kimi nesta comparação), DeepSeek Harness (dsh) (as cinco tarefas e o desafio original), Reasonix (comparado em artigos anteriores; retirado da minha configuração em 09/09/2026) e Quanto realmente custam os meus agentes de IA.