# What changed in dspy

> 20 changes in dspy 3 from its official release notes, upgrade guides and advisories: 7 breaking, 1 security, 2 new APIs and options. Each one cited. Sources checked 2026-10-21. HTML: https://unstale.sh/pypi/dspy/

To see which of these apply to a repository, run `npx @unstale/cli init` in it.

## dspy 3

### Breaking changes

- The bundled metadata snapshot now follows LiteLLM 1.105.0; offline setups may lose capability flags for still-routable models, changing structured-output, native-tool, and reasoning behavior. (3.4.1) — [release notes](https://github.com/stanfordnlp/dspy/releases/tag/3.4.1)
- The private shim file moved to dspy/primitives/_facade_shim.py, so the old module no longer imports. (3.4.1) — [release notes](https://github.com/stanfordnlp/dspy/releases/tag/3.4.1)
- Flex bridge shim constants and helpers moved here; imports from dspy.predict.flex.bridge now raise ImportError. (3.4.1) — [release notes](https://github.com/stanfordnlp/dspy/releases/tag/3.4.1)
- Signatures can no longer declare input fields named history or tools; the constructor raises ValueError because ReActV2 supplies both itself. (3.4.1) — [release notes](https://github.com/stanfordnlp/dspy/releases/tag/3.4.1)
- History replay now passes main_request= to format_user_message_content; custom adapter overrides must accept main_request: bool = False. (3.4.1) — [release notes](https://github.com/stanfordnlp/dspy/releases/tag/3.4.1)
- GEPA now requires reflection_lm to be a dspy.LM or another dspy.BaseLM that can return parseable JSON; plain functions fail and leave the program unoptimized. (3.4.1) — [release notes](https://github.com/stanfordnlp/dspy/releases/tag/3.4.1)
- Null Score level descriptions are rejected when defining signatures or setting criteria, and saved programs containing them no longer load or run successfully. (3.4.1) — [release notes](https://github.com/stanfordnlp/dspy/releases/tag/3.4.1)

### Security

- LM calls made for sandboxed code accept generation parameters only; sandboxed code cannot set model, api_base, api_key, or headers. (3.4.1) — [release notes](https://github.com/stanfordnlp/dspy/releases/tag/3.4.1)

### New APIs and options

- RLM code can import dspy and build Predict, ChainOfThought, ReActV2, and nested RLM sub-agents; sub-agents run on the host and only JSON crosses the interpreter boundary. (3.4.1) — [release notes](https://github.com/stanfordnlp/dspy/releases/tag/3.4.1)
- Configure GEPA's instruction proposer with skills, additional_instructions, base_instructions, max_chars, truncate_history_outputs, and adapter. (3.4.1) — [release notes](https://github.com/stanfordnlp/dspy/releases/tag/3.4.1)

### Behavior and default changes

- When instruction_proposer is omitted, GEPA now uses InstructionProposer(), which sends structured reflective examples through dspy.Predict with a JSONAdapter. (3.4.1) — [release notes](https://github.com/stanfordnlp/dspy/releases/tag/3.4.1)
- Replayed turns keep output-format reminders, making each turn's prompt a prefix of the next one for prompt caching. (3.4.1) — [release notes](https://github.com/stanfordnlp/dspy/releases/tag/3.4.1)
- Tool argument defaults are stored in JSON form for types such as Enum, Decimal, dates, Path, tuples, sets, pydantic models, and dataclasses, while omitted arguments retain their original Python defaults. (3.4.1) — [release notes](https://github.com/stanfordnlp/dspy/releases/tag/3.4.1)
- The RLM call budget now includes llm_query, llm_query_batched, and every sub-agent LM call; each requested completion uses one slot. (3.4.1) — [release notes](https://github.com/stanfordnlp/dspy/releases/tag/3.4.1)
- On Python 3.10–3.13, adapters now render PEP 604 union annotations like typing.Union; parsing is unchanged, but prompts differ. (3.4.1) — [release notes](https://github.com/stanfordnlp/dspy/releases/tag/3.4.1)

### Fixes and other changes

- Raises a ValueError naming student predictors without an LM instead of failing later with AttributeError; set the LM on each student predictor. (3.4.1) — [release notes](https://github.com/stanfordnlp/dspy/releases/tag/3.4.1)
- When a JSON value contains an item pydantic cannot serialize, that item renders as str(item) instead of converting the whole value to a Python repr. (3.4.1) — [release notes](https://github.com/stanfordnlp/dspy/releases/tag/3.4.1)
- Fixes a 3.4.0 import crash that could occur when DSPy lazily imported LiteLLM. (3.4.1) — [release notes](https://github.com/stanfordnlp/dspy/releases/tag/3.4.1)
- DSPy now supports Python 3.15; on that version, LiteLLM and GEPA are not installed, LiteLLM fallback routes are unavailable, and dspy.GEPA raises ImportError. (3.4.1) — [release notes](https://github.com/stanfordnlp/dspy/releases/tag/3.4.1)
- Streamed chunks no longer include whitespace around field markers, so joined chunks equal the parsed field value. (3.4.1) — [release notes](https://github.com/stanfordnlp/dspy/releases/tag/3.4.1)
