pypi / dspy
dspy
What changed in dspy 3, from its official release notes, upgrade guides and advisories. Sources checked 2026-10-21.
7 breaking1 security2 new APIs and options5 behavior and defaults5 fixes and other
See which of these apply to your code, ranked, in your agent:
npx @unstale/cli initdspy 320 changes
Breaking changes 7
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.
The private shim file moved to dspy/primitives/_facade_shim.py, so the old module no longer imports.
Flex bridge shim constants and helpers moved here; imports from dspy.predict.flex.bridge now raise ImportError.
Signatures can no longer declare input fields named history or tools; the constructor raises ValueError because ReActV2 supplies both itself.
History replay now passes main_request= to format_user_message_content; custom adapter overrides must accept main_request: bool = False.
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.
Null Score level descriptions are rejected when defining signatures or setting criteria, and saved programs containing them no longer load or run successfully.
Security 1
LM calls made for sandboxed code accept generation parameters only; sandboxed code cannot set model, api_base, api_key, or headers.
New APIs and options 2
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.
Configure GEPA's instruction proposer with skills, additional_instructions, base_instructions, max_chars, truncate_history_outputs, and adapter.
Behavior and default changes 5
When instruction_proposer is omitted, GEPA now uses InstructionProposer(), which sends structured reflective examples through dspy.Predict with a JSONAdapter.
Replayed turns keep output-format reminders, making each turn's prompt a prefix of the next one for prompt caching.
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.
The RLM call budget now includes llm_query, llm_query_batched, and every sub-agent LM call; each requested completion uses one slot.
On Python 3.10–3.13, adapters now render PEP 604 union annotations like typing.Union; parsing is unchanged, but prompts differ.
Fixes and other changes 5
Raises a ValueError naming student predictors without an LM instead of failing later with AttributeError; set the LM on each student predictor.
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.
Fixes a 3.4.0 import crash that could occur when DSPy lazily imported LiteLLM.
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.
Streamed chunks no longer include whitespace around field markers, so joined chunks equal the parsed field value.