Tools · · 2 min read

LLM 0.33 Ships OpenAI Python 3, httpx2 and Better Tool Logs

Simon Willison's LLM 0.33 moves to OpenAI Python 3 and httpx2, records server-side tool output, adds per-call embedding keys, and lets builders compose prompt templates.


Simon Willison released LLM 0.33 on August 22, 2026. The headline dependency change is an upgrade to the OpenAI Python library 3.x and a switch from httpx to httpx2. The more useful changes for agent builders are improved server-side tool logs, composable templates, per-call embedding keys, and safer handling of reasoning metadata.

This is the full fix for a fresh-install problem that surfaced a day earlier. LLM 0.32.1 temporarily pinned openai<3; version 0.33 adopts OpenAI Python 3 and moves the HTTP dependency explicitly.

Upgrade with the command that matches your installation:

pip install -U llm
# or
pipx upgrade llm
# or
uv tool upgrade llm

Then confirm the installed version:

llm --version

The four changes that matter

1. Server-side tool calls are easier to audit. llm logs now shows the output of tools executed by the model provider. The JSON and short formats include a new server_executed field, so a log consumer can distinguish hosted tools from functions executed by your own process. If you use WebSearch, Code Interpreter, or provider-hosted tools, this closes an important observability gap.

llm logs --json

Do not assume this creates a complete security audit by itself: your application still needs to retain approvals, tool arguments, identities, and external side effects where those matter.

2. Templates can be composed instead of copied. The -t / --template option is now repeatable and applies templates in order. That lets you keep model configuration in one reusable template and task prompts in another:

llm -m gpt-5.6-luna -o reasoning_effort high --save lhigh
llm "Generate an SVG of a pelican riding a bicycle" --save pelican
llm -t lhigh -t pelican

For teams, this makes it easier to version model and reasoning defaults separately from prompt content. Test the order explicitly when two templates set the same option, because later composition can change the effective request.

3. Embedding keys can be supplied per call. llm embed and llm embed-multi now accept --key. The equivalent Python embedding and collection APIs accept key= without mutating shared model state. That is useful for multi-tenant services and key rotation, where storing a credential on a long-lived model object is undesirable. Existing plugins that read self.key retain a compatibility fallback.

4. Reasoning and structured-output failures are less lossy. Metadata-only reasoning events are preserved as ReasoningPart objects, including opaque provider state such as Anthropic signatures and redacted thinking data. OpenAI Responses-compatible models also gain reasoning_summary values of auto, concise, or detailed. Separately, the schema DSL now raises descriptive errors for unknown field types and duplicate fields instead of silently accepting them.

What to test before upgrading production

Plugin maintainers should test against OpenAI Python 3 and the new httpx2 dependency, especially if a plugin imports transport types directly. Agent applications should compare old and new log JSON before changing parsers, then add an explicit branch for server_executed. Embedding services should verify both stored-key and per-request-key paths.

For a quick working example of Simon Willison’s CLI with a provider plugin, see our Gemini 3.5 Flash setup guide.

Sources

Source: LLM 0.33 release notes