- LLM 0.26 é um grande lançamento que permite conectar ferramentas criadas como funções Python a modelos locais do OpenAI, Anthropic, Gemini e Ollama tanto na CLI quanto na biblioteca Python
- As ferramentas podem ser instaladas como plugins e chamadas com
--tool/-T name_of_tool, ou usadas diretamente a partir da linha de comando com funções Python temporárias via --functions
- Além das ferramentas embutidas
llm_version e llm_time, há plugins para simpleeval, QuickJS, SQLite e Datasette, e o modelo pode tentar novamente após uma chamada com falha consultando o schema ou usando outra expressão
- O novo
model.chain() da API Python detecta solicitações de chamada de ferramenta, executa e devolve o resultado ao modelo, com suporte tanto a funções síncronas quanto a ferramentas com asyncio
- Isso se tornou possível à medida que as formas de uso de ferramentas e chamada de funções entre vários fornecedores convergiram, e os próximos passos incluem expansão de plugins, suporte a mais plugins de modelo e suporte a cliente do Model Context Protocol
Suporte à execução de ferramentas no LLM 0.26
- LLM 0.26 adiciona suporte a ferramentas, o maior recurso desde o início do projeto
- Na LLM CLI e na biblioteca Python, é possível conceder a modelos locais do OpenAI, Anthropic, Gemini e Ollama acesso a ferramentas representáveis como funções Python
- Ao instalar novos plugins de ferramentas, dá para adicionar novas capacidades ao modelo em uso
- Há quatro formas principais de uso
- instalar uma ferramenta de plugin e carregá-la com
--tool/-T name_of_tool
- passar código de função Python diretamente na linha de comando com a opção
--functions
- também enviar ferramentas pela API Python com algo como
tools=[locals]
- as ferramentas funcionam tanto em contexto síncrono quanto assíncrono
Executando ferramentas na CLI
- A versão mais recente do LLM pode ser instalada com
uv tool install llm, e uma instalação existente pode ser atualizada com uv tool upgrade llm
- Um exemplo com OpenAI define a chave de API com
llm keys set openai e depois executa assim
llm --tool llm_version "What version?" --td
llm_version é uma ferramenta simples de demonstração incluída no LLM, e --tool llm_version expõe essa ferramenta ao modelo
--tool pode ser especificado várias vezes, e a opção curta -T também pode ser usada
--td é abreviação de --tools-debug e exibe informações de chamadas e respostas de ferramentas para permitir verificar o funcionamento interno
- O modelo padrão costuma ser
gpt-4o-mini, mas no exemplo ele é alterado para gpt-4.1-mini com llm models default gpt-4.1-mini
- A opção
-m permite especificar outro modelo, e há também um exemplo usando o4-mini junto da ferramenta embutida llm_time
llm --tool llm_time "What time is it?" --td -m o4-mini
- A resposta da ferramenta
llm_time inclui campos como utc_time, utc_time_iso, local_timezone, local_time, timezone_offset e is_dst
Funcionamento em vários modelos e plugins
- O mesmo padrão de comando pode ser usado em plugins de modelo que oferecem suporte a ferramentas
- O exemplo com Anthropic Claude Sonnet 4 segue este fluxo
llm install llm-anthropic -U
llm keys set anthropic
llm --tool llm_version "What version?" --td -m claude-4-sonnet
- O exemplo com Google Gemini 2.5 Flash segue este fluxo
llm install llm-gemini -U
llm keys set gemini
llm --tool llm_version "What version?" --td -m gemini-2.5-flash-preview-05-20
- O
qwen3:4b executado com Ollama também consegue usar ferramentas simples
qwen3:4b é um modelo pequeno de 2.6GB
ollama pull qwen3:4b
llm install 'llm-ollama>=0.11a0'
llm --tool llm_version "What version?" --td -m qwen3:4b
Plugins de ferramentas para matemática, JavaScript, SQLite e Datasette
- Tarefas em que o LLM é fraco, como multiplicação de números grandes, podem ser complementadas com chamadas de ferramentas
- llm-tools-simpleeval expõe a biblioteca simpleeval, de Daniel Fairhead
- simpleeval é uma biblioteca “Simple Safe Sandboxed Extensible Expression Evaluator for Python”
- ela fornece um sandbox suficientemente robusto para executar expressões Python simples
- O exemplo de cálculo pode ser executado assim
llm install llm-tools-simpleeval
llm -T simple_eval 'Calculate 1234 * 4346 / 32414 and square root it' --td
- Na execução do exemplo, o modelo primeiro calcula
1234 * 4346 / 32414 e obtém 165.45208860368976; depois falha porque sqrt(...) não está definido, então troca para ** 0.5 e obtém 12.862818066181678
- Há quatro plugins de ferramentas publicados
Toolbox do Datasette e nova tentativa após erro
- O plugin do Datasette funciona como uma toolbox com várias ferramentas internamente
- a toolbox é um plugin configurável via construtor
- O exemplo de uso é o seguinte
llm install llm-tools-datasette
llm -T 'Datasette("https://datasette.io/content")' --td "What has the most stars?"
Datasette("https://datasette.io/content") passa ao plugin a URL da instância Datasette que será usada
- Esse exemplo usa o content database que alimenta o site do Datasette
- O modelo realiza três chamadas
- primeiro ele supõe
SELECT name, stars FROM repos ORDER BY stars DESC LIMIT 1, mas falha porque a coluna stars não existe
- após receber o erro, consulta o schema do banco com a ferramenta
Datasette_schema()
- com base no schema, monta e executa a consulta correta
- Segundo a resposta final, o repositório com mais estrelas é
datasette, com 10.020 stars
Criando ferramentas temporárias com --functions
- A opção
--functions oferece uma forma temporária de usar ferramentas menos estruturada do que plugins
- Ao passar diretamente um bloco de código Python na linha de comando, as funções definidas nele se tornam ferramentas que o modelo pode usar
- O exemplo de ferramenta de busca em blog usa
httpx para chamar a página de busca e retorna o HTML bruto ao modelo
llm --functions '\nimport httpx\n\ndef search_blog(q):\n "Search Simon Willison blog"\n return httpx.get("https://simonwillison.net/search/", params={"q": q}).content\n' --td 'Three features of sqlite-utils' -s 'use Simon search'
- A implementação funciona mesmo apenas devolvendo o HTML bruto da página de busca
- Considera-se que a linha GPT-4.1 consegue lidar com esse HTML mais bruto por suportar 1 milhão de tokens
- É preciso adicionar
use Simon search ao prompt de sistema para que o modelo use a ferramenta de busca fornecida em vez de responder por conta própria
- Uma ferramenta de busca melhor precisaria de instruções mais detalhadas e de trechos relevantes dos resultados
- No resultado do exemplo, aparecem como recursos do
sqlite-utils a combinação de CLI e biblioteca Python, a adição automática de colunas com alter=True e o suporte a plugins
Suporte a ferramentas na API Python
- O LLM é tanto uma ferramenta de CLI quanto uma biblioteca Python, e a versão 0.26 adiciona suporte a ferramentas também à API Python
- O exemplo resolve com uma ferramenta em função o problema de contar quantos
r há em “strawberry”
import llm
def count_char_in_text(char: str, text: str) -> int:
"How many times does char appear in text?"
return text.count(char)
model = llm.get_model("gpt-4.1-mini")
chain_response = model.chain(
"Rs in strawberry?",
tools=[count_char_in_text],
after_call=print
)
for chunk in chain_response:
print(chunk, end="", flush=True)
after_call=print é uma forma de verificar a chamada de ferramenta, semelhante à opção --td vista antes
- O novo método
model.chain() é parecido com model.prompt(), mas detecta solicitações de chamada de ferramenta retornadas pelo modelo, executa essas chamadas e então invoca o modelo novamente com o resultado
model.chain() pode executar várias respostas até chegar à resposta final
- Ao iterar sobre
chain_response, é possível exibir em streaming os tokens retornados ao longo de várias respostas
- No resultado do exemplo, a ferramenta
count_char_in_text é chamada com char='r' e text='strawberry', e com base no resultado 3 responde que há 3 letras r em strawberry
- A biblioteca Python também oferece suporte a
asyncio, e as ferramentas podem ser funções async def
- Se o modelo solicitar várias ferramentas assíncronas ao mesmo tempo, a biblioteca as executa em paralelo com
asyncio.gather()
- A toolbox também é suportada, então passar
tools=[Datasette("https://datasette.io/content")] para chain() produz o mesmo efeito de --tool 'Datasette(...)' na CLI
Contexto da implementação e padrão de uso de ferramentas
- O padrão de uso de ferramentas é algo que vem sendo acompanhado desde sua primeira apresentação pública, em outubro de 2022, no artigo ReAcT
- O padrão básico é simples
- informar ao modelo que há ferramentas disponíveis para uso
- o modelo solicita a execução da ferramenta e para, usando uma sintaxe especial como JSON, XML ou
tool_name(arguments)
- o código faz o parsing dessa saída e executa a ferramenta solicitada
- um novo prompt é enviado ao modelo, incluindo o resultado da execução
- Essa abordagem hoje funciona em praticamente todos os modelos
- Muitos modelos são treinados especificamente para uso de ferramentas, e há até rankings como o Berkeley Function-Calling Leaderboard
- OpenAI, Anthropic, Google, Mistral e Meta incluem recursos de uso de ferramentas ou chamada de funções em suas APIs
- No lado dos modelos locais, o Ollama adicionou suporte a ferramentas no ano passado, e isso também está incluído no servidor do llama.cpp
- Em fevereiro de 2025, o LLM lançou primeiro suporte a schema, tratado como uma etapa rumo ao suporte a ferramentas
- O desafio era projetar uma camada de abstração que funcionasse em vários modelos, e isso só se tornou implementável agora que as abordagens dos fornecedores convergiram de forma clara
- O workshop Building software on top of Large Language Models na PyCon US foi o impulso para concluir a implementação alfa, e há também uma seção sobre tools no tutorial
Agentes e próximos passos
- Ainda existe resistência ao termo “agents”, mas no mundo dos LLMs o padrão tem convergido para tools in a loop, e o LLM 0.26 está próximo dessa forma
- Se você quiser criar agentes, o LLM 0.26 pode ser um bom ponto de partida
- Os próximos trabalhos estão organizados em 13 issues no milestone LLM tools v2
- em sua maioria, são melhorias na exibição dos logs de execução de ferramentas e pequenos problemas que não bloquearam este lançamento
- há mais issues com a label tools
- A área de plugins é a mais promissora
- está sendo usado diretamente o template cookiecutter llm-plugin-tools
- há planos de criar um tutorial relacionado
- Também resta adicionar suporte a ferramentas a mais plugins de modelo
- O suporte ao Model Context Protocol também está nos planos
- o MCP está emergindo rapidamente como uma forma padrão de modelos acessarem ferramentas
- duas semanas atrás ele ainda não era suportado diretamente nas principais APIs de fornecedores, mas nos últimos 8 dias foi adicionado por OpenAI, Anthropic e Mistral
- o objetivo é que o LLM atue como cliente MCP, para que servidores MCP escritos por terceiros possam ser usados facilmente como fonte adicional de ferramentas para o LLM
1 comentários
Opiniões no Hacker News
O renderizador de Markdown em streaming criado para esta ferramenta também vale a pena ver: https://github.com/day50-dev/Streamdown
O contexto está em https://github.com/simonw/llm/issues/12, e também uso todos os dias https://github.com/day50-dev/llmehelp, que contém uma ferramenta tmux construída em cima do
llmdo Simonllm: um plugin ZSH que usazlepara transformar inglês em comandos de shell com uma única tecla: https://github.com/day50-dev/ZummonerAinda hoje usei algo como
$ git find out if abcdefg is a descendent of hijklmnop, e ofor i in $(seq 1 6); do printf "%${i}sh${i}\n\n-----\n" | tr " " "#"; done | pv -bqL 30de outro comentário originalmente também era uma entrada muito mais próxima de linguagem naturalAo pressionar
ctrl-x x, o buffer é enviado ao OpenRouter e substituído pela sintaxe correta em menos de 1 segundoAbri uma issue: https://github.com/simonw/llm/issues/1112
Incluí algumas opções de design, mas ainda não parece totalmente certo, então gostaria de receber feedback
llmjunto com o realce de sintaxe dobatIsso aumenta muito o risco de dar um tiro no próprio pé
A documentação https://llm.datasette.io/en/stable/tools.html alerta sobre prompt injection, mas acho que um cenário mais plausível é o dano que a própria pessoa causa a si mesma
Por exemplo, se você der a uma ferramenta acesso à sua conta de corretora para automatizar operações, mesmo sem prompt injection não há nada que impeça o bot de fazer negociações idiotas
Quando você começa a acoplar ferramentas a um LLM, especialmente se essas chamadas de ferramenta são autenticadas e podem agir em seu nome, há caminhos demais para as coisas darem errado
O lado do MCP está passando por isso em altíssima velocidade agora, e o caso do GitHub MCP de ontem é um exemplo: https://news.ycombinator.com/item?id=44097390
Coloquei um grande aviso na documentação e tomei cuidado para que os plugins iniciais de ferramentas fossem apenas coisas que não pudessem causar danos. Por isso o sandbox QuickJS e o plugin SQLite também são somente leitura
llma uma conta de corretora, o idiota não é o bot, é a pessoa que fez a conexãoNo macOS isso não é tão difícil, mas no momento faltam boas ferramentas fáceis de usar. O Claude Code começou a usar o Seatbelt aos poucos para melhorar a experiência do usuário
Você pode se prejudicar, e talvez até o faça, mas não avaliar as possibilidades também é um risco. Pessoas comuns tendem a subestimar a chance de dar um tiro no próprio pé, e pessoas técnicas tendem a subestimar o risco de não aprender novas possibilidades
Há um ano eu já deixava um LLM executar comandos locais no meu notebook e considero isso um tanto arriscado, mas nada prejudicial aconteceu. Mesmo que exista a possibilidade de ele executar
rm -rf /a partir de um prompt comofind out where I am and what weather it is going to be, ela é muito baixaDito isso, deixar o LLM fazer operações com ações sem saber como ele decide é, para mim, arriscado demais
Gosto da ideia de um agente baseado em terminal do terminal Warp, mas não curto muito o modelo tipo Cursor de “confie na gente e pague, que nós cuidamos dos bons prompts e das chamadas ao LLM”
Por isso eu estava procurando um agente de terminal simples, baseado em CLI, que ajudasse a compensar minha falta de habilidade no shell, e a combinação de ferramentas de terminal com
llmparece uma solução leveEstou bem ciente do grande risco de dar um tiro no próprio pé, então fico curioso se é possível pedir permissão a cada chamada de ferramenta, como outros agentes fazem. Por exemplo, algo como “
llmestá tentando chamarrm -rf ./*. Pressione Y para confirmar” poderia impedir até certo ponto que o LLM saísse do controle no terminal--full-autoPara quem usa
llm, Gtk-llm-chat também vale a pena verEle se integra à ferramenta de linha de comando
llme ao desktop, oferecendo um ícone na bandeja e uma janela de chat agradávelRecentemente lançou a versão 3.0.0 e fornece pacotes para os três principais sistemas operacionais de desktop
Vejo este lançamento como um componente fundamental para liberar o potencial dos LLMs sem as limitações dos clientes existentes
Depois que o alfa da 0.26 saiu, tentei criar um plugin que interagisse com servidores MCP, mas foi bem difícil. Até agora consegui conectar, buscar dinamicamente as ferramentas e usá-las, mas ainda não consigo passar parâmetros
A biblioteca Python oficial
mcppressupõe fortemente um fluxo em que você executaasyncio, conecta ao servidor e então inspeciona as ferramentas disponíveisMantenho, quase que por vibe coding, um plugin zsh/omz para autocompletar abas no CLI
llm, mas o ritmo de lançamento de novos recursos está rápido e é difícil acompanharAinda assim, algo como
llm -f README.md -f llm.plugin.zsh -f completions/_llm -f [https://simonwillison.net/2025/May/27/llm-tools/](<https://simonwillison.net/2025/May/27/llm-tools/>) "implement tab completions for the new tool plugins feature"resolve 90% do problemaO repositório é https://github.com/eliyastein/llm-zsh-plugin e, como tentei incluir o máximo possível de opções e flags, ficou um pouco bagunçado, então gostaria de receber feedback
Gerações futuras vão se perguntar como conseguíamos trabalhar, assim como nós olhamos para programadores em assembly e pensamos: “como eles faziam?”
Eu estava curioso sobre como o Claude Code conhece e usa ferramentas
É possível informar ao LLM quais são as ferramentas e como usá-las, e um wrapper de execução pode gerenciar isso, mas achei que o Claude Code tivesse expectativas muito específicas sobre a API de chamada de ferramentas usada pelo wrapper, e que isso provavelmente tivesse sido fortemente reforçado por pós-treinamento ou ajuste fino
Por isso fiquei me perguntando se frameworks de chamada de ferramentas de terceiros que usam Claude ficam em desvantagem em relação ao framework próprio da Anthropic
Separadamente, como mencionado no texto sobre o “ataque” ao GitHub MCP, um LLM pode ser enganado para usar todos os privilégios das credenciais. Como o GitHub oferece credenciais de autenticação granulares, e nossa empresa também, seria bom alguém experimentar um protocolo para que o wrapper gere credenciais granulares a serem passadas ao LLM
Imagino uma estrutura em que a aplicação recebe credenciais mais fortes, e o LLM subordinado é treinado para fazer uma “solicitação de permissão” para tarefas ou recursos específicos. Se o usuário permitir, o framework obtém do serviço credenciais com escopo limitado e as usa na chamada de ferramenta
Seria necessária uma configuração de ferramentas bastante sofisticada que exponha uma ferramenta de “solicitar credenciais adicionais” e, quando ela for chamada, pergunte ao usuário
A ferramenta deve armazenar as credenciais e nunca repassar o token real ao LLM; em vez disso, pode passar um símbolo como
creds1e instruí-lo a chamar usandocreds1em solicitações posterioresFiquei curioso para saber se você viu este artigo. Se ele for tão importante quanto parece, penso que essa métrica deveria estar em todos os system cards
Ao avaliar 12 LLMs populares que afirmam oferecer suporte a contextos de 128K tokens ou mais, eles tiveram bom desempenho em contextos curtos, mas o desempenho caiu muito conforme o comprimento do contexto aumentou. Em 32K, 10 modelos ficaram abaixo de 50% da linha de base de comprimento curto, e até o GPT-4o, que teve desempenho excepcionalmente bom, caiu de 99,3% para 69,7%
https://arxiv.org/abs/2502.05167
Pelo que sei, nos testes needle in a haystack atuais, o Gemini 2.5 Pro e o Gemini 2.5 Flash estão bem à frente dos outros modelos, então seria bom rodar o teste também com esses modelos
Na semana passada, criei uma demo de chatbot para clientes baseado em dados proprietários com a 0.26a0
Os elementos essenciais que precisei escrever foram o prompt de sistema, uma ferramenta para buscar dados externos e uma ferramenta para realizar cálculos; graças a esta biblioteca, foi muito fácil criar a funcionalidade principal
Na demo, a maior parte do esforço foi para o encanamento: criar uma UI web bonita em que a conversa fosse mantida, que se atualizasse naturalmente mesmo se o navegador fosse recarregado por problemas de conexão, e que permitisse iniciar uma nova sessão de chat
Eu não conhecia
after_call=print, então foi bom descobrir lendo o post do blogUso as ferramentas do Simon todos os dias
Graças aos pipes e à alternância fácil entre Ollama local e modelos remotos, é muito confortável trabalhar