DSPy 3.5: A Lighter, Faster Foundation
DSPy 3.5 brings a lighter LM layer, graduated core modules, and new History and image capabilities for RLM.
Upgrading from 3.4.1
This release changes prompts, defaults and APIs. Read the upgrade guide for breaking changes, migration steps and compatibility limits, and re-evaluate optimized programs.
Highlights
RLM, Flex and GEPA graduate
dspy.RLM, dspy.Flex and dspy.GEPA are no longer experimental.
ReActV2 now replaces ReAct
ReActV2 is now simply dspy.ReAct, with structured History and a typed submit tool; the old name is deprecated until 3.6.
Rich tool results
Tools can return images, files and other DSPy content parts on supported provider routes.
RLM History — authored by Matt Mannucci (@mannuch)
RLM can save and reload conversation History for later calls; it does not restore live interpreter variables.
A lighter LM foundation — lm15 work by Maxime Rivest (@MaximeRivest), integration by Isaac Miller (@isaacbmiller)
LiteLLM and OpenAI’s Python library are now optional: DSPy calls supported providers through the lightweight lm15 engine.
| Measured default install | 3.3.0 | 3.5 development snapshot |
|---|---|---|
| Installed package files, including bytecode | 206.7 MiB | 30.9 MiB |
| Dependencies, excluding DSPy | 65 | 25 |
| Fresh-process import, best of ten | 1.01 s | 0.49 s |
Automatic API-family routing
model_type="auto" is the default, rather than explicitly selecting chat or responses.
XMLAdapter is now the default Adapter
XMLAdapter now formats and parses predictor calls by default, changing prompts and the output contract even when your Signature stays the same.
Native reasoning and explicit plans
Prefer native reasoning; request an explicit plan when planning before acting helps the task or it needs a human-auditable plan.
Disk caches: secure by default
Restricted loading is now the default, and plain NumPy arrays are stored without pickle.
Image-capable RLM
RLM can crop images with Pillow and send mixed text/image subqueries from its Python REPL.
With DSPy imported, an image-capable LM configured and the default Deno runtime available:
rlm = dspy.RLM("photo: dspy.Image, question: str -> answer: str")
result = rlm(photo=dspy.Image.from_path("photo.png"), question="What is written on the smallest sign?")
print(result.answer)Prewarmed Interpreters
Real DSPy now runs inside RLM and Flex interpreters, with a precompiled standard library, cached startup snapshots and InterpreterPool for prewarming.
| Measured path | 3.4.1 | 3.5 development snapshot |
|---|---|---|
| Cached Deno startup + first execution | 1.59 s | 0.45 s |
| DummyLM Flex forward | 1.61 s | 0.63 s |
| Flex with a ready size-one pool | — | 0.10 s |
Medians of nine fresh processes per path, with prepared runtime caches; pool readiness costs another 0.55 s, excluded from the pooled forward. First-use preparation can be slower.
Full PR List
All 99 PRs in the verified range appear once in the list below. Earlier intermediate bundled-lm15 and metadata updates are included for completeness; the cutoff contains bundled lm15 2.2.0 and metadata sourced from released LiteLLM 1.108.3.
Language Models, Adapters, and Reasoning
- fix(xml): honor positional tuple schemas by @isaacbmiller (#10850).
- fix(adapters): preserve nested XML enum and null guidance by @isaacbmiller (#10859).
- Default LM API-family selection to native lm15 routing by @isaacbmiller (#10856).
- fix: honor reasoning dictionaries in ChainOfThought by @isaacbmiller (#10842).
- fix(xml): parse nested numeric and boolean literals by @isaacbmiller (#10840).
- fix: preserve CoT reasoning in Refine feedback by @isaacbmiller (#10839).
- Update vendored lm15 to 2.2.0 with streaming and reasoning coverage by @isaacbmiller (#10816).
- Deprecate TwoStepAdapter in DSPy 3.5 by @isaacbmiller (#10800).
- Update vendored lm15 to 2.0.0 with canonical token accounting by @isaacbmiller (#10764).
- Make openai an optional dependency by @michaelisaac-dev (#10774).
- Make LiteLLM optional while retaining compatibility execution by @isaacbmiller (#10719).
- Remove deprecated LM entry points and unify canonical execution by @isaacbmiller, with preserved coauthorship by @MaximeRivest (#10652).
- Migrate adapters and candidates to canonical requests and responses by @isaacbmiller, with preserved coauthorship by @MaximeRivest (#10713).
- Build canonical LM requests from generation options by @isaacbmiller, with preserved coauthorship by @MaximeRivest (#10712).
- refactor(lm): define minimal engine protocols by @isaacbmiller (#10709).
- feat(adapters): make XML the default adapter by @isaacbmiller (#10707).
- fix(dspy): parse XMLAdapter outputs as typed tags with literal leaves by @isaacbmiller (#10402).
- Consolidate Jev on dspy.LM via bundled lm15 by @isaacbmiller (#10648).
- Update bundled lm15 to 1.5.0 with reviewed source patches by @isaacbmiller (#10660).
- Treat null / empty-dict tool_calls as 'no calls' in ToolCalls validator by @Virtuoso461 (#10644).
- Update vendored lm15 to 1.4.0 with temporary auth fixes by @isaacbmiller (#10540).
- fix(dspy): use native reasoning with a plan fallback in CoT and RLM by @isaacbmiller (#10643).
Agents, History, Tools, Images, and Interpreters
- Fix tool call IDs in serialized ReAct history by @isaacbmiller (#10844).
- fix(tool): preserve nested refs in ReAct submit declarations by @isaacbmiller (#10845).
- fix(tool): accept date RootModel arguments without weakening numeric validation by @isaacbmiller (#10846).
- Preserve tool error status in native history replay by @isaacbmiller (#10847).
- fix: preserve explicit sandbox output defaults by @isaacbmiller (#10843).
- fix: preserve JSON nulls in Deno tool results by @isaacbmiller (#10852).
- Graduate Flex from experimental by @isaacbmiller (#10836).
- Graduate RLM from experimental by @isaacbmiller (#10835).
- Add image decoding, sandbox Pillow, and multimodal RLM subqueries by @isaacbmiller (#10829).
- Unify custom-value transport into RLM and Flex sandboxes by @isaacbmiller (#10828).
- Add reusable RLM History, persistence, and text-safe replay by @isaacbmiller (#10827).
- fix(rlm): render REPL code and output as plain text in prompts by @isaacbmiller (#10812).
- fix(interpreter): retry transient sandbox download failures by @isaacbmiller (#10817).
- fix(dspy): await async tools under RLM.acall in PythonInterpreter by @isaacbmiller (#10808).
- Add InterpreterPool to start interpreters ahead of need by @michaelisaac-dev (#10777).
- Run the real dspy inside Flex and RLM sandboxes by @michaelisaac-dev (#10776).
- Render custom-type tool results as content blocks by @isaacbmiller (#10737).
- Start Pyodide from a precompiled standard library by @michaelisaac-dev (#10775).
- Promote structured-history ReAct by @isaacbmiller (#10795).
- Remove overdue Image and Audio factory aliases by @isaacbmiller (#10778).
- Remove deprecated CodeAct and ProgramOfThought for DSPy 3.5 by @isaacbmiller (#10780).
- Remove deprecated Image constructor download/verify shim by @isaacbmiller (#10779).
- fix(dspy): support class-based signatures in Flex by @michaelisaac-dev (#10768).
- Add BoundingBox type with automatic Jev image support by @isaacbmiller (#10665).
- feat(dspy): ReActV2 show the agent its remaining turn budget each turn by @dbreunig (#10662).
Optimization, Evaluation, Core APIs, and Caching
- Harden restricted disk-cache handling by @isaacbmiller (#10858).
- Fix bootstrap demo selection for multi-turn agents with callable tools by @isaacbmiller (#10841).
- Graduate GEPA with a compatible upstream dependency bound by @isaacbmiller (#10796).
- fix(dspy): let majority() vote on non-string field values by @SaiMouli3 (#10720).
- fix(dspy): parse negative numbers in string signature Literal types by @Blacksujit (#10678).
- Enable restricted disk-cache deserialization by default by @isaacbmiller (#10726).
- fix(dspy): preserve integer precision when loading pandas data by @emme1t (#10471).
- fix(teleprompt): respect MIPROv2.compile seed=0 by @Zsanz3 (#10322).
- fix(dspy): preserve CoT parse failures in bootstrap traces by @isaacbmiller (#10683).
- fix(BootstrapFewShot): honor metric_threshold=0.0 by @tomron (#10604).
- fix(utils): cache materialized module on lazy-import proxies by @isaacbmiller (#10635).
- fix(evaluate): include all result fields in CSV export by @kausthubhk (#10597).
- fix(dspy): keep fields when copying an Example with no visible fields by @Zhuoxi2000 (#10637).
Documentation
- docs: make the RLM sandbox package example executable by @isaacbmiller (#10860); imports partial and defines the image-task Signature, with no runtime changes.
- docs: repair executable DummyLM examples by @isaacbmiller (#10831).
- docs: pass required tools in ReAct cheatsheet example by @isaacbmiller (#10806).
- docs: install OpenAI SDK for the audio tutorial by @isaacbmiller (#10798).
- docs: fix custom type image example imports by @isaacbmiller (#10743).
- docs(lm): document the DSPy 3.5 Request/Response migration by @isaacbmiller, with preserved coauthorship by @MaximeRivest (#10708).
- docs: serve root redirect and robots.txt from the docs host by @dbreunig (#10730).
- docs: add page dates, homepage metadata, and one DSPy definition by @dbreunig (#10731).
- docs: repair outdated notebook and API examples by @isaacbmiller (#10727).
- docs(dspy): fix cache env var names in FAQ by @tomron (#10610).
- docs: fix stale import paths in the deployment and GEPA guides by @shaikn6 (#10608).
- docs: fix ControlArena tutorial link by @isaacbmiller (#10722).
- docs: remove unavailable community resources and restore moved links by @isaacbmiller (#10702).
- docs: fix async-tool tutorial cross-links by @isaacbmiller (#10699).
- Fix broken company logos on the Use Cases page by @isaacbmiller (#10691).
- docs(dspy): correct precision_score docstring example value by @Blacksujit (#10681).
- docs: fix broken links in faqs, optimizers overview, and built-with-dspy by @shi-felix (#10622).
Dependencies, Metadata, CI, Typing, and Release Engineering
- test: require opt-in for parallel usage tracking by @isaacbmiller (#10857).
- chore: refresh model metadata from LiteLLM 1.108.3 by @isaacbmiller (#10823).
- chore: refresh model metadata from LiteLLM 1.108.1 by @isaacbmiller (#10815).
- chore: refresh model metadata provenance to LiteLLM 1.108.0 by @isaacbmiller (#10799).
- test: make Unbatchify timeout regression deterministic by @isaacbmiller (#10794).
- Preserve saving and loading types with ty by @divakantpandey (#10735).
- perf(utils): avoid stack walks for missing dependencies by @fredheir (#10769).
- fix(typing): preserve types of experimental classes and properties by @fredheir (#10657).
- Refresh LiteLLM metadata to 1.106.6; decouple tests from catalog values by @isaacbmiller (#10744).
- Fix TwoStepAdapter bounding-box test setup after XML default change by @isaacbmiller (#10728).
- test: build the subprocess PYTHONPATH with os.pathsep by @Aditya17-bot (#10589).
- fix(ci): repair publisher container CA trust by @isaacbmiller (#10711).
- Require patched installers and CA bundles by @isaacbmiller (#10703).
- Preserve parallel executor task types with ty by @isaacbmiller (#10688).
- Preserve callback decorator signatures with ty by @isaacbmiller (#10684).
- Add incremental internal typing with ty in CI and pre-commit by @isaacbmiller (#10673).
- Refresh LiteLLM metadata to 1.106.0 and reject router-fee-only estimates by @isaacbmiller (#10670).
- Fix reasoning tests across LiteLLM dependency versions by @isaacbmiller (#10655).
- chore(deps): bump zensical from 0.0.64 to 0.0.69 in /docs by @dependabot (#10651).
- Update versions for 3.4.1 by @github-actions (#10638).
- Refresh model metadata provenance from LiteLLM 1.105.1 by @isaacbmiller (#10646).
- ci: isolate test dependency caches by job by @isaacbmiller (#10640).
Contributors
Thank you to @Aditya17-bot, @Blacksujit, @dbreunig, @divakantpandey, @emme1t, @fredheir, @isaacbmiller, @kausthubhk, @michaelisaac-dev, @SaiMouli3, @shaikn6, @shi-felix, @tomron, @Virtuoso461, @Zhuoxi2000, @Zsanz3, @mannuch and @MaximeRivest. Automation contributions: @dependabot and @github-actions.
Full Changelog: 3.4.1...471b3fb