llm 0.33 takes the pin out and moves to httpx2
Version 0.32.1 held fresh installs together by pinning the OpenAI Python package below 3.0.0. That was a holding action, and 0.33 does the actual repair: it upgrades to the OpenAI library 3.x and switches its HTTP client from httpx to httpx2. The release also carries changes you will notice in daily use, including a --key option on the embedding commands and server-side tool results that finally show up in llm logs.
Version 0.32.1 shipped on August 21 with a single line of content: a version pin that stopped fresh installs from breaking. The repair it was standing in for arrived a day later. llm 0.33, released on August 22, upgrades to the OpenAI Python library 3.x and moves the HTTP client dependency from httpx to httpx2.
The pin comes out
The break that 0.32.1 patched came from upstream: the OpenAI package stopped depending on httpx, and llm imported httpx without declaring it. Pinning the package below 3.0.0 kept the old dependency arriving, which restored installs without a rewrite. It also froze llm on an old major version of a library it does not control, which is a debt with interest.
0.33 pays it. The dependency is now declared and the client is httpx2, so a fresh install no longer depends on what somebody else happens to pull in.
What else changed
Three of the additions matter if you use llm for more than one-off prompts.
- llm embed and llm embed-multi accept --key, and the Python methods accept key=. The resolved key is passed per call, so a plugin no longer has to mutate shared model state to use a different one. Plugins that read self.key keep working through a compatibility fallback.
- llm logs now shows the output of server-side tool calls in a Tool results section, and marks them with a server_executed key in --json and --short output. Until now that output was simply absent from the log.
- llm prompt -t can be repeated, so the model configuration from one template combines with the prompt from another.
Errors that used to be silent
schema_dsl() now raises a descriptive ValueError for an unknown field type or a duplicate field name. Before this it treated an unknown type as a string and let a repeated name overwrite the earlier field, which is the kind of default that turns a typo into a wrong result rather than a stack trace.
Reasoning stream events that carry provider metadata but no text are kept as ReasoningPart objects, so opaque state such as Anthropic signatures and redacted thinking survives a round trip instead of being dropped.
Sources
Related
A fresh install of llm broke because the OpenAI library stopped using httpx
Version 0.32.1 pins the OpenAI Python package below 3.0.0 so that new installations work again. Nothing in llm changed to cause the break: it imported httpx while relying on the OpenAI package to bring it along, and when that package dropped httpx the dependency simply stopped arriving. It is a small release with a lesson that outlives it.
Simon Willisonverified

Next.js will patch one critical vulnerability on August 26
Vercel published the date before the fix. Versions 16.3.3 and 15.5.24 arrive on August 26 with a full advisory, and the announcement exists so teams can schedule the upgrade instead of discovering it from a CVE feed.
Next.js Blogverified
ChatGPT search switched en masse to the site: operator
On August 20, Simon Willison relayed a measurement from Promptwatch showing that ChatGPT abruptly began narrowing its searches to preselected domains. The share of queries carrying the site: operator held between 0.3% and 0.5% for weeks, then jumped to 16% to 17% on August 8 — two days after OpenAI announced accuracy fixes in GPT-5.6. Willison concludes that the search tool internally has the shape search(query, recency, domains), which means the model picks domains before it even frames the question. If you care about visibility in that search, you are no longer competing only for a place in the result but for your domain to make the list the model assembles on its own.
Simon Willisonverified