
Criei um editor LaTeX onde a IA corrige seus próprios erros
Aqui está um loop que executei mais vezes do que gostaria de admitir.
Peça a um modelo por uma equação. Receba LaTeX de volta. Cole no Overleaf. Não compila. Copie o erro para o chat. Receba um pedido de desculpas e uma correção. Cole isso de volta. Repita até que seja renderizado, ou até que eu desista e escreva a coisa eu mesmo.
Qualquer um que esteja fazendo matemática séria com um LLM conhece essa dança. Modelos de ponta ficam perto de 50% em tarefas de LaTeX no benchmark TeXpert, e o ciclo permanece lento por um motivo bobo: o renderizador sabe exatamente o que está quebrado, e o modelo nunca vê isso. Eles vivem em janelas diferentes.
Então, quando o Desafio WebMCP da OpenAI surgiu, eu tinha uma coceira específica para coçar. E se o renderizador estivesse dentro do loop? O agente escreve LaTeX diretamente no documento, a página o renderiza ao vivo, e quando quebra, o agente lê o erro de renderização como qualquer outro resultado de ferramenta.
Isso se tornou o Lemma. Está ao vivo em https://lemma-webmcp.netlify.app.
O que é
Lemma é um bloco de LaTeX local-first para escrever matemática com um agente. Você obtém um painel de origem CodeMirror, uma pré-visualização KaTeX ao vivo, visualização dividida e um agente que lê e edita o mesmo documento através de 16 ferramentas WebMCP. Documentos ficam no IndexedDB dentro da aba. Sem backend, sem conta, nada do que você digita sai do navegador.
Pilha: Next.js 16 como uma exportação estática, React 19, TypeScript em modo estrito, Tailwind 4, Zustand. A construção levou cerca de uma semana, 57 commits.
A parte que me importa é o loop no meio:
você: "corrija os erros de renderização em minhas anotações"
agente: get_render_errors -> Sequência de controle indefinida: \alpa (bloco blk_a7f3, posição 22)
agente: update_block -> \alpha
página: a matemática re-renderiza, o bloco brilha
O documento semente é enviado com um erro de digitação deliberado \alpa para que qualquer um possa assistir a um agente capturá-lo e corrigi-lo em uma única passagem.
Erros como dados
get_render_errors não retorna uma parede de texto. Ele retorna coordenadas:
{
"blockId": "blk_a7f3",
"message": "Sequência de controle indefinida: \alpa",
"suggestion": "\alpha",
"position": 22,
"context": "&= \alpa \cdot 0 + 1",
"fix": "Substitua o comando ofensivo por \alpha via update_block."
}
Um ID de bloco, uma posição de caractere, uma sugestão de distância de edição e a próxima ação descrita. O erro se torna dados que o agente pode agir em vez de uma sensação que ele tem que interpretar. Essa única ferramenta é todo o projeto.
Blocos, não strings
A maneira usual como um LLM edita um documento é a correspondência de citações. Encontre o parágrafo que diz X, substitua-o por Y. Isso quebra no momento em que o texto muda, e em um editor ao vivo o texto muda constantemente.
O Lemma divide cada documento em blocos. Cada equação, teorema, parágrafo, tabela e figura recebe um ID estável. O agente edita blk_a7f3, nunca uma correspondência de string.
As edições manuais são a parte complicada. Você digita no código-fonte bruto, o documento reanalisa a cada tecla pressionada, e os IDs podem se deslocar, o que deixaria um comentário do agente ancorado ao parágrafo errado. Uma passagem de reconciliação é executada após cada reanálise e mantém os IDs fixos: correspondência exata do bloco primeiro, depois pontuação de similaridade com uma penalidade de posição. Sobrevive a reordenações, inserções, exclusões e edições de erros de digitação, e há testes unitários que fixam cada caso.
O conjunto de ferramentas
Quinze ferramentas imperativas através de document.modelContext.registerTool, além de uma ferramenta de formulário declarativa na pesquisa da barra lateral.
Leituras: list_documents, get_document, get_document_outline, search_documents, get_render_errors. Escritas: create_document, insert_blocks, update_block, delete_block, undo_last_change, add_comment, reply_to_comment, resolve_comment, set_view, export_document.
Regras de design que estabeleci após ler a especificação e os documentos do Chrome mais de uma vez:
-
Erros são valores, nunca throws. Se
executerejeitar, o agente recebe umUnknownErrorgenérico e sua mensagem morre no caminho. Cada caminho de falha retorna{ error, hint }com a próxima ação nele. -
Anotações honestas. WebMCP tem exatamente duas,
readOnlyHinteuntrustedContentHint. Leituras carregam a primeira. Qualquer coisa que retorne LaTeX ou comentários escritos pelo usuário carrega a segunda, porque a injeção de prompt viaja através da matemática também. - Orçamentos. 500 caracteres para uma descrição de ferramenta, 150 para parâmetros, saídas reduzidas ao que o agente precisa a seguir.
- Limites de entrada com mensagens úteis. 50 blocos por inserção, 50k caracteres por bloco, 4k por comentário. Cada limite informa ao chamador o que fazer em vez de apenas falhar.
Duas ferramentas merecem destaque. set_view permite que o agente mude você para a visualização dividida e role até o bloco que ele acabou de editar, o que demonstra lindamente. E undo_last_change é consciente do autor: o armazenamento registra quem fez cada alteração, o agente pode reverter sua própria edição, mas se você digitou algo mais recentemente, ele se recusa e explica o porquê. Eu não queria que um agente apagasse silenciosamente meu trabalho enquanto eu não estava olhando.
Armadilhas que a especificação me ensinou
A especificação é curta, mas morde.
- registerTool precisa de isolamento de origem
O Lemma pode revolucionar a forma como profissionais de matemática e ciência utilizam LaTeX, permitindo correções instantâneas e uma interação mais fluida com a IA. Isso pode aumentar a produtividade e reduzir frustrações em tarefas complexas de edição.



