llm 0.33 arrives with chainable templates and per-call keys
Simon Willison's CLI for talking to models straight from the terminal gained template chaining, --key in embedding commands, and reasoning summaries in the Responses API.

If you work with LLMs in the terminal, you've probably already run into llm, the command-line tool created by Simon Willison. It does one simple thing and does it well: sends prompts to dozens of models (OpenAI, Anthropic, local models via plugin) straight from the shell, stores history in SQLite, and works both for quick experiments and for dropping into scripts and pipelines. Version 0.33, released on August 22, 2026, isn't an overhaul, it's the kind of incremental release that fixes real friction points for people who use the tool every day.
Templates that chain together
The most practical highlight is that llm prompt -t/--template can now be repeated, combining templates in the order you pass them. This changes how you can organize model configuration.
The pattern this unlocks is separating configuration from prompt. You create a template that packages a model with its default options and another template with just the prompt text, then combine the two when you run:
# Template with model + reasoning options
llm -m gpt-5.6-luna -o reasoning_effort high --save lhigh
# Template with just the prompt
llm "Generate an SVG of a pelican riding a bicycle" --save pelican
# Combine and run both
llm -t lhigh -t pelicanIn practice, this means you keep a handful of "model profile" templates (one for heavy reasoning, one for fast and cheap responses, one for a local model) and reuse them with any saved prompt. Before, each template was a closed block; now you can build combinations without duplicating model configuration in every prompt file. For anyone who writes a lot of recurring prompts, that's less repetition and less chance of forgetting to set the right reasoning_effort.
Per-call keys in embeddings
The llm embed and llm embed-multi commands now accept --key. On the Python side, the EmbeddingModel.embed(), EmbeddingModel.embed_multi(), Collection.embed(), and Collection.embed_multi() methods now accept key=, passing the resolved key per call to the embedding plugin without altering the model's shared state.
The important detail here is without altering the shared state. Before, embedding models read self.key, which tied the key to the model globally. Now they follow the same pattern that regular LLM models already used: the key travels with the call. Anyone maintaining embedding plugins doesn't need to rewrite anything, because there's a compatibility fallback, plugins that still read self.key keep working. The contribution came from ChrisJr404 (issues #757 and #1620).
Anyone building RAG will recognize the value: if you index collections for different clients or switch between accounts, being able to pass the right key per call avoids the hack of swapping a global environment variable mid-process.
Reasoning summaries in the Responses API
Reasoning-capable models that use the Responses API now support the reasoning_summary option, with three values: auto, concise, and detailed. It can be used together with llm openai endpoint --responses (issue #1600).
Willison notes that this is especially useful for exercising models that provide their own imitation of OpenAI's Responses API. As more and more providers expose endpoints compatible with this format, having a standardized way to request the reasoning summary (short or detailed) helps compare how different models justify their answers without needing model-specific code.
The dependency swap under the hood
The release also updated the OpenAI Python library to the 3.x line and switched the HTTP client from httpx to httpx2 (issues #1608 and #1631). Willison had already shipped a quick patch, 0.32.1, the day before, but describes 0.33 as the more complete fix.
This kind of change usually goes unnoticed until it breaks something. If you have plugins or scripts that pin the httpx version, it's worth checking compatibility before updating in production. For regular use via the CLI, the swap should be transparent.
Is it worth updating?
None of the 0.33 items is a game-changer, but together they reduce friction for anyone who already lives in the tool. Chainable templates are the most visible day-to-day gain: they separate configuration from content in a way that fits well with automation flows. The --key in embeddings fixes a long-standing API inconsistency. And reasoning_summary is one of those features that only makes sense once you're seriously comparing reasoning models.
To install or update:
pip install -U llm
# or, if you use uv/pipx
uv tool upgrade llmIf you don't use llm yet and work with models in the terminal, it remains one of the most direct ways to test prompts, version experiments in SQLite, and integrate LLMs into scripts without writing an HTTP client by hand. The full release notes, with all contributor credits, are in Willison's annotated post at simonwillison.net.
Translated from the Brazilian Portuguese original · Read the original
Convex Agent Component: how native memory and RAG work for AI agents
Convex's official component bundles threads, persistent memory, and hybrid vector/text search for those building AI agents, without setting up a parallel vector DB stack.
