[{"url":"https://api.github.com/repos/stanfordnlp/dspy/releases/364378109","assets_url":"https://api.github.com/repos/stanfordnlp/dspy/releases/364378109/assets","upload_url":"https://uploads.github.com/repos/stanfordnlp/dspy/releases/364378109/assets{?name,label}","html_url":"https://github.com/stanfordnlp/dspy/releases/tag/3.3.0","id":364378109,"author":{"login":"isaacbmiller","id":17116851,"node_id":"MDQ6VXNlcjE3MTE2ODUx","avatar_url":"https://avatars.githubusercontent.com/u/17116851?v=4","gravatar_id":"","url":"https://api.github.com/users/isaacbmiller","html_url":"https://github.com/isaacbmiller","followers_url":"https://api.github.com/users/isaacbmiller/followers","following_url":"https://api.github.com/users/isaacbmiller/following{/other_user}","gists_url":"https://api.github.com/users/isaacbmiller/gists{/gist_id}","starred_url":"https://api.github.com/users/isaacbmiller/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/isaacbmiller/subscriptions","organizations_url":"https://api.github.com/users/isaacbmiller/orgs","repos_url":"https://api.github.com/users/isaacbmiller/repos","events_url":"https://api.github.com/users/isaacbmiller/events{/privacy}","received_events_url":"https://api.github.com/users/isaacbmiller/received_events","type":"User","user_view_type":"public","site_admin":false},"node_id":"RE_kwDOIv2ufM4Vt_f9","tag_name":"3.3.0","target_commitish":"main","name":"3.3.0","draft":false,"immutable":true,"prerelease":false,"created_at":"2026-08-03T19:01:57Z","updated_at":"2026-08-03T20:06:03Z","published_at":"2026-08-03T20:06:03Z","assets":[],"tarball_url":"https://api.github.com/repos/stanfordnlp/dspy/tarball/3.3.0","zipball_url":"https://api.github.com/repos/stanfordnlp/dspy/zipball/3.3.0","body":"# DSPy 3.3.0\r\n\r\nDSPy 3.3.0 is a feature release with a new experimental way to optimize programs as code, a native-tool-aware ReAct implementation, and the next stage of DSPy's move toward a typed, provider-neutral language-model system.\r\n\r\nMost existing DSPy programs should keep working without changes. Review the API changes if you construct `Image`, `Audio`, or `File` values from paths or URLs; use NumPy-backed features from the base install; inspect detailed GEPA results; construct code interpreters directly; use `RLM(max_iterations=...)`; consume raw Responses API tool-call outputs; or catch provider-specific LM exceptions.\r\n\r\nWe would especially appreciate feedback on Flex, ReActV2, and the typed LM path. These APIs expand what DSPy can optimize and how it can connect to model providers, and real-world usage will help shape their next iterations.\r\n\r\n## Highlights\r\n\r\n### Flex Optimizes Program Structure, Not Just Prompts — @michaelisaac-dev\r\n\r\nMost DSPy modules fix the shape of a program up front: `Predict` makes one prediction, `ReAct` runs a tool loop, and `RLM` runs a code interpreter in a loop. Optimizers can improve the instructions around that structure, but the structure itself stays fixed. The new experimental `dspy.Flex` moves the implementation into the search space so GEPA can discover the decomposition instead.\r\n\r\nGive Flex the same signature you would give `Predict` and it starts with the simplest working baseline: one `dspy.Predict`, or one `dspy.RLM` when tools are supplied. During compilation, GEPA can rewrite the complete module implementation—changing the predictors, control flow, DSPy primitives, and balance between Python and LM calls—against your metric.\r\n\r\n```python\r\nprogram = dspy.Flex(\"question -> answer\")\r\noptimized = dspy.GEPA(metric=metric, reflection_lm=reflection_lm).compile(\r\n    program,\r\n    trainset=trainset,\r\n    valset=valset,\r\n)\r\n\r\nprint(optimized.module_src)\r\n```\r\n\r\nOptimizer-authored source always runs in a `CodeInterpreter` sandbox, using `dspy.PythonInterpreter` by default. Predictor construction and LM calls bridge back to the host, broken candidates score as failures instead of crashing the search, and `max_predictor_calls` guards against runaway generated programs. Metrics can also accept a `program_trace` to score how a result was produced—for example, penalizing programs that make too many LM calls.\r\n\r\nThe optimized `module_src` is part of the program's serialized state, so saving and loading preserves the implementation GEPA discovered. Flex is experimental, and ordinary GEPA behavior is unchanged when a program does not contain a Flex module.\r\n\r\nPR: #10047\r\n\r\n### ReActV2 and Native Tool-Calling History - @isaacbmiller\r\n\r\n`dspy.ReActV2` is a new version of ReAct built around native tool calling. It is currently marked as experimental.\r\n\r\nThe signature now uses `dspy.History`, `dspy.Tool`, and `dspy.ToolCalls`(which can now optionally store `dspy.ToolCallResults`), rather than the custom next_tool_args and custom trajectory syntax. Using `dspy.History` also means that messages are now broken up into user/assistant/tool groups rather than one long user message with the trajectory.\r\n\r\nThis changes the execution model in a few concrete ways:\r\n\r\n- `parallel_tool_calls` support: DSPy preserves each call/result pair by ID. You can do this in native mode or in non-native mode\r\n- `Multi-turn native tool call` support: Prior tool calls and results can be replayed as assistant and tool messages instead of being flattened into prompt text.\r\n- Each turn lives in `dspy.History` as structured messages rather than one ever-growing `trajectory` string, so providers with prompt caching can reuse stable prefixes more effectively. We have seen up to 50% decreases in cost for some tasks when testing this internally.\r\n\r\n`ReActV2` converts callables to `dspy.Tool`, adds an internal `submit` tool for final outputs, handles unknown tools and tool exceptions, accepts serialized history input, and can force final submission when the model does not call `submit`.\r\n\r\nPRs: #9823, #9824, #9825, #9835\r\n\r\n### Typed, Provider-Neutral LM Boundary - @MaximeRivest\r\n\r\nDSPy is moving from an untyped LM boundary based on `prompt`, `messages`, and provider-shaped `kwargs` toward a typed, provider-neutral contract:\r\n\r\n```python\r\ndef forward(self, request: dspy.LMRequest) -> dspy.LMResponse:\r\n    ...\r\n```\r\n\r\nThe resulting API is a cleaner LM extension point:\r\n\r\n- LiteLLM can become an optional compatibility fallback in the planned 3.5+ path, instead of a required part of the core LM contract.\r\n- Custom LM authors can implement one typed `LMRequest -> LMResponse` path instead of guessing which OpenAI/LiteLLM-shaped inputs will arrive.\r\n- Custom LMs can translate between DSPy's typed objects and their own provider, local runtime, gateway, or inference stack.\r\n- Adapters can start to depend on DSPy's representation of messages, multimodal content, tool calls, reasoning, citations, usage, cache controls, metadata, and stream events.\r\n\r\nMost users do not need to change anything in 3.3. Existing `lm(...)`, modules, and programs keep their current behavior by default.\r\n\r\nTry out the typed return path with `dspy.context(experimental=True)`, and the public migration plan explains the staged transition for custom LM and adapter authors.\r\n\r\n[See the full plan here](https://dspy.ai/community/normalized-lm-api-migration/)\r\n\r\nPRs: #9786, #9802, #9828\r\n\r\n### BaseLM Runtime, Save/Load, Errors, and LiteLLM Decoupling - @MaximeRivest\r\n\r\n`BaseLM` now owns shared runtime state and supports sanitized state serialization through `dump_state()` and `load_state()`. Serialized LM state excludes API keys, preserves legacy saved states, and requires explicit opt-in before importing trusted custom LM classes.\r\n\r\nSaved programs with custom LMs are easier to reason about, LM copies isolate DSPy-owned mutable state, and callers can catch `dspy.LMError` or a narrower DSPy subclass instead of depending on provider-specific exception classes. LiteLLM imports are lazy, which keeps the core LM API less coupled to a specific provider bridge at import time.\r\n\r\nPRs: #9752, #9820, #9821, #9826\r\n\r\n### LM and Responses API Updates Since 3.3.0b1 - @MaximeRivest, @isaacbmiller\r\n\r\nSince the beta, DSPy has added an explicit `BaseLM.forward()` contract, exported the typed LM API, supported typed direct calls through `BaseLM.__call__`, made optional-provider imports thread-safe, and fixed LM state round trips for GPT-5 models.\r\n\r\nThe OpenAI Responses path now emits Responses-native tool and `tool_choice` request shapes. Legacy Responses outputs use the same Chat-style tool-call representation as the Chat Completions path, while typed `LMToolCallPart` objects preserve raw provider fields.\r\n\r\nPRs: #9837, #9840, #9841, #9843, #9877, #9999, #10003, #10014, #10026, #10028\r\n\r\n## API Changes\r\n\r\n### Breaking Changes\r\n\r\n#### Resource Construction and Validation No Longer Perform Implicit I/O\r\n\r\nConstructing or validating `dspy.Image`, `dspy.Audio`, and `dspy.File` values no longer interprets locator-shaped strings as instructions to read a local file or fetch a remote URL. This prevents LM-output parsing, Pydantic validation, and deserialization from silently granting filesystem or network access merely because a value resembles a path or URL.\r\n\r\nResource loading now requires an explicit factory:\r\n\r\n| Before 3.3 | DSPy 3.3 | Behavior |\r\n| --- | --- | --- |\r\n| `Image(path)` or `Image(url=path)` | `Image.from_path(path)` | Read and embed a local image |\r\n| `Image(url, download=True)` | `Image.from_url(url)` | Download and embed a remote image |\r\n| `Image.from_url(url)` or `Image.from_url(url, download=False)` | `Image(url)` or `Image(url=url)` | Keep a non-downloading provider-fetched URL reference |\r\n| `Audio(path)` | `Audio.from_path(path)` | Read and embed local audio |\r\n| `Audio(url)` | `Audio.from_url(url)` | Download and embed remote audio |\r\n| `File(path)` | `File.from_path(path)` | Read and embed a local file |\r\n| `encode_image(path)` | `Image.from_path(path)` | Explicitly read a local image |\r\n| `encode_audio(path_or_url)` | `Audio.from_path(path)` or `Audio.from_url(url)` | Explicitly load audio |\r\n| `encode_file_to_dict(path)` | `File.from_path(path)` | Explicitly read a local file |\r\n\r\nThere are several related compatibility changes:\r\n\r\n- `Image.from_url()` now downloads the resource and returns an embedded data URI. Use `Image(url)` when the model provider should fetch the reference instead.\r\n- `Image.from_url(..., download=...)` and the `download_images` / `verify` options on `encode_image()` were removed. Choose reference construction or an explicit factory instead.\r\n- Pydantic payloads containing `download` or `verify` are rejected without fetching. The deprecated direct developer call `Image(url, download=True)` remains available with a warning through 3.3.\r\n- The deprecated compatibility call requires a positional source: `Image(url, download=True)`. Validation-style calls such as `Image(url=url, download=True)` are rejected.\r\n- `Image.from_file()`, `Image.from_PIL()`, and `Audio.from_file()` remain as deprecated aliases through 3.3 and are scheduled for removal in 3.4. Use `Image.from_path()`, `Image(pil_image)`, and `Audio.from_path()` respectively.\r\n- Safe in-memory inputs—including data URIs, bytes, PIL images, audio arrays, structured dictionaries, and existing resource instances—remain supported.\r\n\r\nThe explicit `Image.from_url(url, verify=...)` and `Audio.from_url(url, verify=...)` factories still accept TLS certificate verification controls. The removed `verify` option applies to `encode_image()`.\r\n\r\n`Image.from_url()` and `Audio.from_url()` make synchronous caller-initiated requests, follow redirects, and do not provide an SSRF allowlist. Applications remain responsible for validating or allowlisting destinations derived from untrusted input.\r\n\r\nPR: #10111 by @isaacbmiller\r\n\r\n#### `numpy` Is Now Optional\r\n\r\n`numpy` is no longer installed with base `dspy`. Features that need NumPy now require the `numpy` extra:\r\n\r\n```bash\r\npip install \"dspy[numpy]\"\r\n```\r\n\r\nAffected areas include embeddings, KNN/KNNFewShot, SIMBA, and other NumPy-backed optimizer or retrieval paths. (#9659 by @isaacbmiller)\r\n\r\n#### GEPA Result Shapes Changed With `gepa[dspy]==0.1.1`\r\n\r\nThe upstream GEPA 0.1.1 API changed several result structures, and `DspyGEPAResult` now mirrors those shapes. Users who inspect `optimized_program.detailed_results` may need to update code:\r\n\r\n- `DspyGEPAResult.candidates` is now a list of compiled DSPy modules, not instruction dictionaries.\r\n- `DspyGEPAResult.best_candidate` now returns a compiled DSPy module.\r\n- `val_subscores` is now `list[dict[Any, float]]`, keyed by validation instance id.\r\n- `per_val_instance_best_candidates` is now `dict[Any, set[int]]`.\r\n- `best_outputs_valset` is now `dict[Any, list[tuple[int, Prediction]]]` when tracked.\r\n- `highest_score_achieved_per_val_task` now returns a dictionary keyed by validation instance id.\r\n\r\nIf you pass custom GEPA reflection templates directly, note that GEPA 0.1.1 renamed default placeholders from `<curr_instructions>` / `<inputs_outputs_feedback>` to `<curr_param>` / `<side_info>`. In `dspy.GEPA`, passing `reflection_prompt_template` through `gepa_kwargs` now raises a clear `ValueError`; use `instruction_proposer` for custom proposal behavior instead. (#9673 by @BenMcH)\r\n\r\n#### `RLM.max_iterations` Is Now `RLM.max_iters`\r\n\r\nThe RLM constructor now uses the same `max_iters` name as other iterative DSPy modules:\r\n\r\n```python\r\n# Before\r\nrlm = dspy.RLM(\"context, query -> answer\", max_iterations=10)\r\n\r\n# DSPy 3.3\r\nrlm = dspy.RLM(\"context, query -> answer\", max_iters=10)\r\n```\r\n\r\nPR: #9920 by @isaacbmiller\r\n\r\n#### RLM Rejects Colliding Names and Unexpected Inputs\r\n\r\nRLM now validates its execution namespace up front. Construction fails for duplicate tool names, Python-keyword tool names, signature inputs that collide with built-in sandbox functions or tools, and output fields named `trajectory` or `final_reasoning`. Invocation also rejects unexpected input fields rather than ignoring them. Rename colliding fields or tools before constructing the module.\r\n\r\nPR: #10020 by @isaacbmiller\r\n\r\n#### RLM Sub-LM and Tool Execution Are Stricter\r\n\r\n`llm_query` and `llm_query_batched` now require the sub-LM to return either a `dspy.LMResponse` containing text or a non-empty legacy output list whose first item is text. Arbitrary response objects are no longer converted with `str()`. Batched queries convert `dspy.LMError` failures to `[ERROR]` entries, but programming and response-contract errors now propagate.\r\n\r\nRLM also invokes user tools through `dspy.Tool`, so tool argument validation and coercion, default handling, and tool callbacks now apply.\r\n\r\nPRs: #10023, #10025 by @isaacbmiller\r\n\r\n#### Code-Executing Modules Use an Interpreter Factory\r\n\r\n`ProgramOfThought`, `CodeAct`, and `RLM` now accept `interpreter_factory=`, a zero-argument callable that creates a fresh `CodeInterpreter` for each invocation. This isolates concurrent calls and makes interpreter ownership explicit.\r\n\r\n```python\r\nprogram = dspy.ProgramOfThought(\r\n    \"question -> answer\",\r\n    interpreter_factory=MyInterpreter,\r\n)\r\n```\r\n\r\nTo use an existing interpreter, pass it as the first positional argument when invoking the module. DSPy does not shut down a caller-owned interpreter, and reuse is supported only for sequential calls to the same module instance.\r\n\r\nThese modules no longer expose a constructor-owned `interpreter` attribute or preserve its sandbox state across calls. Without a caller-owned interpreter, each invocation creates and shuts down a fresh interpreter. Interpreter process and protocol failures are terminal for that interpreter session rather than automatically restarting it, and submitted-code failures now raise `CodeExecutionError`, a subclass of `CodeInterpreterError`.\r\n\r\nPRs: #10018, #10022 by @isaacbmiller\r\n\r\n#### `ToolCalls` Uses DSPy's Native Serialized Shape\r\n\r\n`dspy.ToolCalls.format()` and Pydantic serialization now represent each call as `{\"name\": ..., \"args\": ...}` rather than the prior OpenAI-style `{\"type\": \"function\", \"function\": {\"name\": ..., \"arguments\": ...}}` shape. Code that persists `ToolCalls`, calls `.format()` directly, or forwards the result to an OpenAI-compatible endpoint must update its conversion logic. Provider adapters still produce the wire shape required by their APIs.\r\n\r\nPR: #9823 by @isaacbmiller\r\n\r\n#### Direct `BaseLM` Defaults and Copy Semantics Changed\r\n\r\nThe direct `BaseLM` constructor now defaults `temperature` and `max_tokens` to `None` instead of `0.0` and `1000`. This primarily affects custom LM subclasses that inherit or delegate to `BaseLM.__init__`; ordinary `dspy.LM` already used the provider-default `None` values.\r\n\r\n`BaseLM.copy()` now shallow-copies subclass-owned attributes while separately copying DSPy-owned mutable runtime containers. Custom LM subclasses that relied on arbitrary mutable attributes being deep-copied should override `copy()` or copy that state explicitly.\r\n\r\nPR: #9821 by @MaximeRivest\r\n\r\n#### Responses Tool Calls Use the Chat-Compatible Legacy Shape\r\n\r\nLegacy output from `dspy.LM(..., model_type=\"responses\")` now represents tool calls in the same shape as the Chat Completions path:\r\n\r\n```python\r\n{\r\n    \"type\": \"function\",\r\n    \"id\": call_id,\r\n    \"function\": {\r\n        \"name\": tool_name,\r\n        \"arguments\": arguments,\r\n    },\r\n}\r\n```\r\n\r\nThe `text` key is now always present. Raw Responses item IDs, status, and provider fields remain available through `LMToolCallPart.provider_data` on the typed path.\r\n\r\nPR: #10028 by @isaacbmiller\r\n\r\n#### LM Error Types Are DSPy-Normalized\r\n\r\nLM failures are now mapped into DSPy exception classes. This should make LM error handling more consistent, but code that catches provider-specific or LiteLLM-specific errors directly may need to catch `dspy.LMError` or a narrower DSPy subclass. (#9826 by @MaximeRivest)\r\n\r\n`ChatAdapter` and `JSONAdapter` no longer retry with an alternate output format after an `LMError`; provider and transport failures propagate directly. `TwoStepAdapter` now raises `dspy.AdapterParseError` rather than `ValueError` for local extraction or parsing failures, while extraction-LM failures propagate as `dspy.LMError`.\r\n\r\n### New and Updated APIs\r\n\r\n- Added exported `LMRequest`, `LMResponse`, typed message/content classes, tool specifications, reasoning and cache configuration, usage records, history entries, and streaming types. (#9786, #9841, #9877 by @MaximeRivest)\r\n- Added `forward_contract = \"typed_lm\"` and an explicit `BaseLM.forward(request) -> LMResponse` contract for new custom LM implementations. (#9843, #9877 by @MaximeRivest)\r\n- Added `Signature.append_instructions()` for deriving a signature with additional instructions without mutating the original. (#9923 by @mathurk1)\r\n- Added experimental `dspy.Flex` and trace-aware GEPA metrics through the optional sixth `program_trace` parameter. (#10047 by @michaelisaac-dev)\r\n- Added experimental `dspy.ReActV2`, structured native tool-call history, and tool-result replay. (#9823, #9824, #9825, #9836 by @isaacbmiller)\r\n- Added explicit `from_path()` and `from_url()` resource-loading factories for `Image` and `Audio`, plus `File.from_path()`, while keeping construction and validation free of implicit host I/O. (#10111 by @isaacbmiller)\r\n- Made `BaseLM` own and serialize shared runtime state. `copy()` now makes a shallow object copy, resets history, and separately copies the callbacks list and kwargs dictionary. (#9820, #9821 by @MaximeRivest)\r\n- Excluded defaulted arguments from required tool parameters and stabilized open-ended tool argument schemas. (#9971 by @katherineahn, #10012 by @isaacbmiller)\r\n- Protected RLM-owned namespaces, normalized sub-LM responses, and routed tool execution through `dspy.Tool`. (#10020, #10023, #10025 by @isaacbmiller)\r\n- Made interpreter process and protocol failures terminal for the affected session and isolated interpreters per invocation. (#10018, #10022 by @isaacbmiller)\r\n- Improved interpreter transport for Pydantic objects, scalar values, dataclasses, named tuples, and non-finite floats. (#9753 by @Archelunch, #9991 by @Vinay152003, #10015 and #10049 by @migurski)\r\n- Made module `load_state()` transactional, isolated BootstrapFinetune data by predictor, validated random-search restrictions up front, and preserved callback lineage in parallel workers. (#9741 by @ashishSoni1234, #10005 and #10043 by @isaacbmiller, #10033 by @chuenchen309)\r\n\r\n### Compatibility Notices\r\n\r\n- OpenAI 1.66.2 is now the supported minimum. (#9999 by @isaacbmiller)\r\n- LiteLLM 1.65.8 is required for the reasoning-capability API. (#10003 by @isaacbmiller)\r\n- The LangChain extra now requires LangChain Core 0.3.0 or newer. (#10004 by @isaacbmiller)\r\n- The base install no longer depends directly on `asyncer`, `xxhash`, or `typeguard`; DSPy now uses AnyIO and standard-library equivalents. (#9733, #9734, #9735 by @isaacbmiller)\r\n- `dspy.utils.hasher.Hasher` now uses SHA-256 instead of xxhash64. Hash strings, hash-derived fine-tuning filenames, and deterministic bootstrap trace selection may change; LM response-cache keys are unaffected. (#9734 by @isaacbmiller)\r\n- `Module.set_lm()`, `get_lm()`, and state loading now include module-valued parameter leaves such as `Flex`, rather than only `Predict`. Custom classes that combine `Module` and `Parameter` should expose compatible LM state and accept `allow_unsafe_lm_state=` when overriding `load_state()`. (#10047 by @michaelisaac-dev)\r\n\r\n## Full PR List\r\n\r\n### Language Models and Adapters — 23 PRs\r\n\r\n- #9718 — Handle missing usage from truncated Responses API responses — @isaacbmiller\r\n- #9752 — Make LiteLLM imports lazy — @MaximeRivest\r\n- #9786 — Add core language-model types — @MaximeRivest\r\n- #9791 — Add exact adapter-format message tests — @MaximeRivest\r\n- #9792 — Expand exact adapter-format message coverage — @MaximeRivest\r\n- #9802 — Introduce a normalized LM boundary for adapters — @MaximeRivest\r\n- #9820 — Support `BaseLM` state serialization — @MaximeRivest\r\n- #9821 — Make `BaseLM` own shared LM runtime state — @MaximeRivest\r\n- #9826 — Normalize DSPy LM errors — @MaximeRivest\r\n- #9828 — Add the normalized LM API migration plan — @MaximeRivest\r\n- #9830 — Fix cached-provider Pydantic serializers — @isaacbmiller\r\n- #9834 — Silence missing-input warnings for optional fields — @MaximeRivest\r\n- #9837 — Fix GPT-5 LM state round trips — @isaacbmiller\r\n- #9840 — Make lazy optional imports thread-safe — @MaximeRivest\r\n- #9841 — Export typed LM API symbols — @MaximeRivest\r\n- #9843 — Add an explicit `BaseLM.forward()` contract — @MaximeRivest\r\n- #9877 — Make `BaseLM.__call__` support typed `LMRequest` and `LMResponse` while preserving the legacy default — @MaximeRivest\r\n- #9999 — Declare OpenAI 1.66.2 as the supported floor — @isaacbmiller\r\n- #10003 — Require the LiteLLM reasoning-capability API — @isaacbmiller\r\n- #10014 — Omit absent Responses tool fields — @isaacbmiller\r\n- #10026 — Send Responses-native tool and `tool_choice` shapes — @isaacbmiller\r\n- #10028 — Normalize Responses output parsing and unify the legacy tool-call shape — @isaacbmiller\r\n- #10111 — Prevent implicit resource loading during validation — @isaacbmiller\r\n\r\n### Agents, Tools, and Interpreters — 25 PRs\r\n\r\n- #9411 — Add `SandboxSerializable` for custom RLM types — @kmad\r\n- #9748 — Resolve symlinks for Deno `--allow-read` paths — @npow\r\n- #9753 — Transport Pydantic models as JSON through the interpreter — @Archelunch\r\n- #9754 — Await asynchronous tool functions in `PythonInterpreter` — @Archelunch\r\n- #9823 — Preserve tool-call IDs and add tool results — @isaacbmiller\r\n- #9824 — Replay native tool-call history through adapters — @isaacbmiller\r\n- #9825 — Add ReActV2 — @isaacbmiller\r\n- #9835 — Render tool calls in `inspect_history()` — @isaacbmiller\r\n- #9836 — Mark ReActV2 experimental — @isaacbmiller\r\n- #9873 — Add a Diving Deeper page for `dspy.RLM` — @dbreunig\r\n- #9920 — Rename RLM `max_iterations` to `max_iters` — @isaacbmiller\r\n- #9971 — Exclude defaulted arguments from required function-calling parameters — @katherineahn\r\n- #9989 — Revise Deno installation instructions in the RLM documentation — @migurski\r\n- #9991 — Serialize `inf`, `-inf`, and `nan` as valid Python literals — @Vinay152003\r\n- #10002 — Declare the MCP hello tool's actual return type — @isaacbmiller\r\n- #10007 — Propagate DSPy context to batched RLM subqueries — @isaacbmiller\r\n- #10012 — Stabilize open tool-argument schemas — @isaacbmiller\r\n- #10015 — Preserve scalar tool results in the Python-interpreter sandbox — @migurski\r\n- #10018 — Make interpreter failures terminal — @isaacbmiller\r\n- #10020 — Protect RLM-owned namespaces — @isaacbmiller\r\n- #10022 — Isolate interpreters per invocation — @isaacbmiller\r\n- #10023 — Normalize RLM sub-LM responses — @isaacbmiller\r\n- #10025 — Execute RLM tools through `dspy.Tool` — @isaacbmiller\r\n- #10049 — Serialize dataclass and named-tuple tool results in RLM — @migurski\r\n- #10054 — Prevent `ReAct.truncate_trajectory()` from emptying a single-tool-call trajectory — @chuenchen309\r\n\r\n### Core APIs and Optimizers — 10 PRs\r\n\r\n- #9659 — Make NumPy an optional dependency — @isaacbmiller\r\n- #9673 — Update `DspyGEPAResult` for GEPA 0.1.1 — @BenMcH\r\n- #9705 — Raise `ValueError` when no valid program is found — @Ricardo-M-L\r\n- #9741 — Make `load_state()` transactional — @ashishSoni1234\r\n- #9767 — Remove deprecated prefix arguments from internal Avatar signatures — @nullhack\r\n- #9923 — Add `Signature.append_instructions()` — @mathurk1\r\n- #10005 — Isolate BootstrapFinetune data by predictor — @isaacbmiller\r\n- #10033 — Validate BootstrapFewShotWithRandomSearch restrictions up front — @chuenchen309\r\n- #10043 — Preserve callback call lineage in parallel workers — @isaacbmiller\r\n- #10047 — Add experimental `dspy.Flex` and its GEPA extension — @michaelisaac-dev\r\n\r\n### Documentation and Community — 16 PRs plus one direct commit\r\n\r\n- #9771 — Correct a mismatched closing code fence in the README — @abhicris\r\n- `b16d109` — Fix the FAQ Learn-guide link — @cosmopolitan033\r\n- #9855 — Revamp the home page and restructure learning and reference documentation — @dbreunig\r\n- #9856 — Update homepage release status — @isaacbmiller\r\n- #9875 — Add a link to the example dataset — @dbreunig\r\n- #9886 — Fix the RAGatouille typo and replace deprecated `dspy.OpenAI` references — @FBISiri\r\n- #9889 — Fix the entity-extraction tutorial dataset — @10gyal\r\n- #9893 — Fix a typo in the customer-service agent tutorial — @Maxim-Mazurok\r\n- #9902 — Add API category index pages to prevent directory URL 404s — @migurski\r\n- #9908 — Correct typos in comments and error messages — @arnav-144p\r\n- #9953 — Move class-level docstrings to `ChainOfThought` and `BestOfN` — @katherineahn\r\n- #9970 — Add the Microsoft AI logo, use case, and links to the community page — @dbreunig\r\n- #10080 — Fix article usage in the MIPROv2 documentation — @SpiliosDimakopoulos\r\n- #10081 — Fix article usage in the modules documentation — @SpiliosDimakopoulos\r\n- #10082 — Fix article usage in the BestOfN and Refine documentation — @SpiliosDimakopoulos\r\n- #10083 — Fix article usage in the FAQ — @SpiliosDimakopoulos\r\n- #10084 — Fix a non-standard word in a section heading — @SpiliosDimakopoulos\r\n\r\n### CI, Testing, and Release Infrastructure — 17 PRs\r\n\r\n- #9602 — Update `actions/setup-python` from 3.1.4 to 6.2.0 — @dependabot\r\n- #9742 — Add zizmor and actionlint to CI — @isaacbmiller\r\n- #9743 — Fix zizmor and actionlint findings across workflows — @isaacbmiller\r\n- #9745 — Add `security-events` permission for SARIF uploads — @isaacbmiller\r\n- #9746 — Remove `git-auto-commit-action` from the release workflow — @isaacbmiller\r\n- #9787 — Update `zizmor-action` from 0.5.3 to 0.5.5 — @dependabot\r\n- #9795 — Isolate the DSPy cache in tests — @isaacbmiller\r\n- #9844 — Mark KNN tests as extra-dependent — @isaacbmiller\r\n- #9845 — Update versions for 3.3.0b1 — @github-actions\r\n- #9854 — Update `zizmor-action` from 0.5.5 to 0.5.6 — @dependabot\r\n- #9909 — Update `actions/checkout` from 6.0.2 to 6.0.3 — @dependabot\r\n- #9910 — Update `astral-sh/setup-uv` from 8.1.0 to 8.2.0 — @dependabot\r\n- #10000 — Audit dependency-range boundaries — @isaacbmiller\r\n- #10041 — Pin Ollama to 0.31.2 and add a warm-up health check — @isaacbmiller\r\n- #10078 — Parallelize pytest with xdist and simplify CI jobs — @isaacbmiller\r\n- #10079 — Remove the AMX backend CI variant — @isaacbmiller\r\n- #10089 — Pool Deno/Pyodide interpreters across tests — @isaacbmiller\r\n\r\n### Dependencies — 18 PRs\r\n\r\n- #9624 — Update `mkdocstrings-python` from 1.16.7 to 2.0.3 — @dependabot\r\n- #9729 — Update `typeguard` from 4.4.3 to 4.5.1 — @dependabot\r\n- #9730 — Update `anyio` from 4.9.0 to 4.13.0 — @dependabot\r\n- #9731 — Update `tenacity` from 9.1.2 to 9.1.4 — @dependabot\r\n- #9732 — Update `cachetools` from 6.1.0 to 7.0.6 — @dependabot\r\n- #9733 — Remove `asyncer` and use AnyIO directly — @isaacbmiller\r\n- #9734 — Replace `xxhash` with `hashlib.sha256` — @isaacbmiller\r\n- #9735 — Replace `typeguard` with standard-library type checking — @isaacbmiller\r\n- #9757 — Update `cachetools` from 7.0.6 to 7.1.1 — @dependabot\r\n- #9759 — Update `mistune` from 3.2.0 to 3.2.1 — @dependabot\r\n- #9760 — Update `weaviate-client` from 4.5.7 to 4.21.0 — @dependabot\r\n- #9761 — Update documentation `urllib3` from 1.26.6 to 2.7.0 — @dependabot\r\n- #9762 — Update documentation `mistune` from 3.2.0 to 3.2.1 — @dependabot\r\n- #9789 — Update `anthropic` from 0.89.0 to 0.102.0 — @dependabot\r\n- #9790 — Update `regex` from 2025.11.3 to 2026.5.9 — @dependabot\r\n- #10004 — Declare LangChain Core 0.3.0 as the supported floor — @isaacbmiller\r\n- #10059 — Update documentation `mistune` from 3.2.1 to 3.3.3 — @dependabot\r\n- #10077 — Update `mkdocstrings` from 1.0.4 to 1.0.6 — @dependabot\r\n\r\n## Contributors\r\n\r\nThank you to everyone who contributed to DSPy 3.3.0:\r\n\r\n- @isaacbmiller\r\n- @MaximeRivest\r\n- @kmad\r\n- @BenMcH\r\n- @Ricardo-M-L\r\n- @ashishSoni1234\r\n- @npow\r\n- @Archelunch\r\n- @nullhack\r\n- @abhicris\r\n- @cosmopolitan033\r\n- @dbreunig\r\n- @FBISiri\r\n- @10gyal\r\n- @Maxim-Mazurok\r\n- @migurski\r\n- @arnav-144p\r\n- @mathurk1\r\n- @katherineahn\r\n- @Vinay152003\r\n- @chuenchen309\r\n- @SpiliosDimakopoulos\r\n- @michaelisaac-dev\r\n\r\nAutomation contributions were made by @dependabot and @github-actions.\r\n\r\n## First-Time Contributors\r\n\r\n- @kmad made their first contribution in #9411.\r\n- @ashishSoni1234 made their first contribution in #9741.\r\n- @npow made their first contribution in #9748.\r\n- @Archelunch made their first contributions in #9753 and #9754.\r\n- @nullhack made their first contribution in #9767.\r\n- @cosmopolitan033 made their first contribution in `b16d109`.\r\n- @dbreunig made their first contribution in #9855.\r\n- @FBISiri made their first contribution in #9886.\r\n- @10gyal made their first contribution in #9889.\r\n- @Maxim-Mazurok made their first contribution in #9893.\r\n- @migurski made their first contribution in #9902.\r\n- @arnav-144p made their first contribution in #9908.\r\n- @mathurk1 made their first contribution in #9923.\r\n- @katherineahn made their first contribution in #9953.\r\n- @Vinay152003 made their first contribution in #9991.\r\n- @chuenchen309 made their first contribution in #10033.\r\n- @SpiliosDimakopoulos made their first contribution in #10080.\r\n\r\n**Full Changelog**: https://github.com/stanfordnlp/dspy/compare/3.2.1...3.3.0\r\n","reactions":{"url":"https://api.github.com/repos/stanfordnlp/dspy/releases/364378109/reactions","total_count":2,"+1":1,"-1":0,"laugh":0,"hooray":1,"confused":0,"heart":0,"rocket":0,"eyes":0},"mentions_count":24},{"url":"https://api.github.com/repos/stanfordnlp/dspy/releases/330299458","assets_url":"https://api.github.com/repos/stanfordnlp/dspy/releases/330299458/assets","upload_url":"https://uploads.github.com/repos/stanfordnlp/dspy/releases/330299458/assets{?name,label}","html_url":"https://github.com/stanfordnlp/dspy/releases/tag/3.3.0b1","id":330299458,"author":{"login":"isaacbmiller","id":17116851,"node_id":"MDQ6VXNlcjE3MTE2ODUx","avatar_url":"https://avatars.githubusercontent.com/u/17116851?v=4","gravatar_id":"","url":"https://api.github.com/users/isaacbmiller","html_url":"https://github.com/isaacbmiller","followers_url":"https://api.github.com/users/isaacbmiller/followers","following_url":"https://api.github.com/users/isaacbmiller/following{/other_user}","gists_url":"https://api.github.com/users/isaacbmiller/gists{/gist_id}","starred_url":"https://api.github.com/users/isaacbmiller/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/isaacbmiller/subscriptions","organizations_url":"https://api.github.com/users/isaacbmiller/orgs","repos_url":"https://api.github.com/users/isaacbmiller/repos","events_url":"https://api.github.com/users/isaacbmiller/events{/privacy}","received_events_url":"https://api.github.com/users/isaacbmiller/received_events","type":"User","user_view_type":"public","site_admin":false},"node_id":"RE_kwDOIv2ufM4Tr_hC","tag_name":"3.3.0b1","target_commitish":"main","name":"3.3.0b1","draft":false,"immutable":true,"prerelease":true,"created_at":"2026-05-28T00:15:13Z","updated_at":"2026-05-28T01:11:39Z","published_at":"2026-05-28T01:11:39Z","assets":[],"tarball_url":"https://api.github.com/repos/stanfordnlp/dspy/tarball/3.3.0b1","zipball_url":"https://api.github.com/repos/stanfordnlp/dspy/zipball/3.3.0b1","body":"# DSPy 3.3.0b1 Release Notes\r\n\r\nDSPy 3.3.0b1 is a beta release including a new ReActV2 module, a new BaseLM System, updating to GEPA 0.1.1, and fewer dependencies framework wide.\r\n\r\nMost existing DSPy programs should keep working without changes. Review the breaking changes if you depend on NumPy from the base `dspy` install, inspect GEPA result internals, or catch provider-specific LM exceptions directly.\r\n\r\nWe would really appreciate feedback on ReActV2 and the new LM system! Please try them out and let us know if you run into any issues.\r\n\r\n## Highlights\r\n\r\n### ReActV2 and Native Tool-Calling History - @isaacbmiller\r\n\r\n`dspy.ReActV2` is a new version of ReAct built around native tool calling. It is currently marked as experimental.\r\n\r\nThe signature now uses `dspy.History`, `dspy.Tool`, and `dspy.ToolCalls`(which can now optionally store `dspy.ToolCallResults`), rather than the custom next_tool_args and custom trajectory syntax. Using `dspy.History` also means that messages are now broken up into user/assistant/tool groups rather than one long user message with the trajectory.\r\n\r\nThis changes the execution model in a few concrete ways:\r\n\r\n- `parallel_tool_calls` support: DSPy preserves each call/result pair by ID. You can do this in native mode or in non-native mode\r\n- `Multi-turn native tool call` support: Prior tool calls and results can be replayed as assistant and tool messages instead of being flattened into prompt text.\r\n- Each turn lives in `dspy.History` as structured messages rather than one ever-growing `trajectory` string, so providers with prompt caching can reuse stable prefixes more effectively. We have seen up to 50% decreases in cost for some tasks when testing this internally.\r\n\r\n`ReActV2` converts callables to `dspy.Tool`, adds an internal `submit` tool for final outputs, handles unknown tools and tool exceptions, accepts serialized history input, and can force final submission when the model does not call `submit`.\r\n\r\nPRs: #9823, #9824, #9825, #9835\r\n\r\n### Typed, Provider-Neutral LM Boundary - @MaximeRivest\r\n\r\nDSPy is moving from an untyped LM boundary based on `prompt`, `messages`, and provider-shaped `kwargs` toward a typed, provider-neutral contract:\r\n\r\n```python\r\ndef forward(self, request: dspy.LMRequest) -> dspy.LMResponse:\r\n    ...\r\n```\r\n\r\nThe resulting API is a cleaner LM extension point:\r\n\r\n- LiteLLM can become an optional compatibility fallback in the planned 3.5+ path, instead of a required part of the core LM contract.\r\n- Custom LM authors can implement one typed `LMRequest -> LMResponse` path instead of guessing which OpenAI/LiteLLM-shaped inputs will arrive.\r\n- Custom LMs can translate between DSPy's typed objects and their own provider, local runtime, gateway, or inference stack.\r\n- Adapters can start to depend on DSPy's representation of messages, multimodal content, tool calls, reasoning, citations, usage, cache controls, metadata, and stream events.\r\n\r\nMost users do not need to change anything in 3.3. Existing `lm(...)`, modules, and programs keep their current behavior by default.\r\n\r\nTry out the typed return path with `dspy.context(experimental=True)`, and the public migration plan explains the staged transition for custom LM and adapter authors.\r\n\r\n[See the full plan here](https://dspy.ai/community/normalized-lm-api-migration/)\r\n\r\nPRs: #9786, #9802, #9828\r\n\r\n### Smaller Base Install - @isaacbmiller\r\n\r\nWe have been whittling away at dependencies!\r\n\r\nThe base install is lighter: `numpy` is now optional via `dspy[numpy]`, and direct dependencies on `asyncer`, `xxhash`, and `typeguard` were removed in favor of standard-library paths.\r\n\r\nUsers who do not need NumPy-backed retrieval, embeddings, or optimizers get a smaller default install with fewer transitive dependencies. Users who need NumPy-backed features can install `dspy[numpy]`.\r\n\r\nPRs: #9659, #9733, #9734, #9735\r\n\r\n### BaseLM Runtime, Save/Load, Errors, and LiteLLM Decoupling - @MaximeRivest\r\n\r\n`BaseLM` now owns shared runtime state and supports sanitized state serialization through `dump_state()` and `load_state()`. Serialized LM state excludes API keys, preserves legacy saved states, and requires explicit opt-in before importing trusted custom LM classes.\r\n\r\nSaved programs with custom LMs are easier to reason about, LM copies isolate DSPy-owned mutable state, and callers can catch `dspy.LMError` or a narrower DSPy subclass instead of depending on provider-specific exception classes. LiteLLM imports are lazy, which keeps the core LM API less coupled to a specific provider bridge at import time.\r\n\r\nPRs: #9752, #9820, #9821, #9826\r\n\r\n### Custom Objects for RLM Sandboxes - @kmad\r\n\r\n`dspy.RLM` can now accept custom sandbox-serializable values through `SandboxSerializable`.\r\n\r\nUsers can pass richer objects, such as DataFrames, into the sandbox with explicit setup, serialization, assignment, and preview behavior instead of forcing everything through prompt text.\r\n\r\nPRs: #9411\r\n\r\n### GEPA 0.1.1 Support - @BenMcH\r\n\r\nDSPy now supports `gepa[dspy]==0.1.1`, including updated `DspyGEPAResult` behavior, tests, and docs.\r\n\r\nUsers can move to the current GEPA DSPy integration in this beta. The breaking changes below call out the result-shape changes for code that inspects detailed GEPA outputs.\r\n\r\nPRs: #9673\r\n\r\n## Breaking Changes\r\n\r\n### `numpy` Is Now Optional\r\n\r\n`numpy` is no longer installed with base `dspy`. Features that need NumPy now require the `numpy` extra:\r\n\r\n```bash\r\npip install \"dspy[numpy]\"\r\n```\r\n\r\nAffected areas include embeddings, KNN/KNNFewShot, SIMBA, and other NumPy-backed optimizer or retrieval paths. (#9659 by @isaacbmiller)\r\n\r\n### GEPA Result Shapes Changed With `gepa[dspy]==0.1.1`\r\n\r\nThe upstream GEPA 0.1.1 API changed several result structures, and `DspyGEPAResult` now mirrors those shapes. Users who inspect `optimized_program.detailed_results` may need to update code:\r\n\r\n- `DspyGEPAResult.candidates` is now a list of compiled DSPy modules, not instruction dictionaries.\r\n- `DspyGEPAResult.best_candidate` now returns a compiled DSPy module.\r\n- `val_subscores` is now `list[dict[Any, float]]`, keyed by validation instance id.\r\n- `per_val_instance_best_candidates` is now `dict[Any, set[int]]`.\r\n- `best_outputs_valset` is now `dict[Any, list[tuple[int, Prediction]]]` when tracked.\r\n- `highest_score_achieved_per_val_task` now returns a dictionary keyed by validation instance id.\r\n\r\nIf you pass custom GEPA reflection templates directly, note that GEPA 0.1.1 renamed default placeholders from `<curr_instructions>` / `<inputs_outputs_feedback>` to `<curr_param>` / `<side_info>`. In `dspy.GEPA`, passing `reflection_prompt_template` through `gepa_kwargs` now raises a clear `ValueError`; use `instruction_proposer` for custom proposal behavior instead. (#9673 by @BenMcH)\r\n\r\n### LM Error Types Are Now DSPy-Normalized\r\n\r\nLM failures are now mapped into DSPy exception classes. This should make LM error handling more consistent, but code that catches provider-specific or LiteLLM-specific errors directly may need to catch `dspy.LMError` or a narrower DSPy subclass. (#9826 by @MaximeRivest)\r\n\r\n## LM Runtime Changes\r\n\r\n- Added core typed LM objects for provider-neutral requests, responses, messages, parts, tool specs, reasoning config, cache config, usage, history entries, stream events, and stream assembly. (#9786 by @MaximeRivest)\r\n- Added OpenAI/LiteLLM compatibility conversion helpers so current provider-shaped calls can move through `LMRequest` and `LMResponse` internally. (#9802 by @MaximeRivest)\r\n- Routed adapter `__call__` and `acall` through the normalized LM boundary while converting back to legacy parser inputs for compatibility. (#9802 by @MaximeRivest)\r\n- Current `BaseLM` calls still receive OpenAI/LiteLLM-shaped kwargs. Internally, adapters now move through `adapter messages -> LMRequest -> OpenAI/LiteLLM kwargs -> current BaseLM -> LMResponse -> existing adapter postprocess path`. (#9802 by @MaximeRivest)\r\n- Added exact adapter-format regression coverage before and during the boundary work, including Chat, JSON, XML, BAML, TwoStep, tools, reasoning, citations, multimodal content, custom types, demos, and history. (#9791, #9792 by @MaximeRivest)\r\n- Made `BaseLM` the owner of shared runtime state and changed `BaseLM.copy()` to an explicit shallow runtime copy. (#9821 by @MaximeRivest)\r\n- Added sanitized `BaseLM.dump_state()` and `BaseLM.load_state()` support, including trusted custom LM class loading through `allow_unsafe_lm_state=True`. (#9820 by @MaximeRivest)\r\n- Added structured DSPy LM exceptions and wired them into `dspy.LM` and adapter fallback behavior. (#9826 by @MaximeRivest)\r\n- Made LiteLLM imports lazy so importing DSPy does not eagerly import the LiteLLM bridge. (#9752 by @MaximeRivest)\r\n- Added the public typed LM API migration plan for custom LM and adapter authors. (#9828 by @MaximeRivest)\r\n\r\n## ReActV2 and Tool Calling\r\n\r\n- Added `dspy.ReActV2`, a native-tool-aware ReAct predictor with `dspy.Tool` conversion, an internal `submit` tool, serialized history input support, unknown-tool and tool-exception handling, and forced final submission when needed. (#9825 by @isaacbmiller)\r\n- Enabled ReActV2-style agents to use provider-side parallel tool calls when the adapter is configured with `parallel_tool_calls`, preserving each model-requested call and each observation by call ID. (#9823, #9824, #9825 by @isaacbmiller)\r\n- Moved ReActV2 history from a formatted `trajectory` string into structured `dspy.History`, so native-tool providers can see prior turns as assistant/tool messages and prompt-caching providers can reuse stable prompt prefixes more effectively. (#9824, #9825 by @isaacbmiller)\r\n- Preserved provider tool-call IDs on `ToolCalls.ToolCall` and added `ToolCallResults` for call IDs, tool names, values, and error flags. (#9823 by @isaacbmiller)\r\n- Taught adapters to replay prior native assistant tool calls and matching tool results as native LM messages when native function calling is enabled, without changing non-native history rendering. (#9824 by @isaacbmiller)\r\n- Rendered tool calls in `inspect_history` for assistant messages and LM output records, including provider-style `function` payloads and tool-call outputs without text. (#9835 by @isaacbmiller)\r\n\r\n## Bug Fixes\r\n\r\n- Render tool calls in `inspect_history` and avoid crashing on assistant messages with `content=None` or output records with tool calls but no text. (#9835 by @isaacbmiller)\r\n- Repair cached provider Pydantic serializers when fresh processes read cached OpenAI/LiteLLM response objects with stale `MockValSer` serializers. (#9830 by @isaacbmiller)\r\n- Suppress missing-input warnings for omitted signature inputs whose annotations allow `None`, while preserving warnings for genuinely missing required inputs. (#9834 by @isaacbmiller)\r\n- Handle `usage=None` from the OpenAI Responses API on truncated responses. (#9718 by @isaacbmiller)\r\n- Make module `load_state` transactional by validating before mutating state. (#9741 by @ashishSoni1234)\r\n- Await async tool functions in `PythonInterpreter`. (#9754 by @Archelunch)\r\n- Resolve symlinks correctly for Deno `--allow-read` paths in `PythonInterpreter`. (#9748 by @npow)\r\n- Remove deprecated Avatar prefix arguments from internal signatures. (#9767 by @nullhack)\r\n- Fix a mismatched closing code fence in the README. (#9771 by @abhicris)\r\n- Fix the FAQ learn-guide link. (#9798 by @cosmopolitan033)\r\n\r\n## Docs, Testing, CI, and Dependencies\r\n\r\n- Added and expanded exact adapter-format message coverage. (#9791, #9792 by @MaximeRivest)\r\n- Isolated DSPy cache usage in tests. (#9795 by @isaacbmiller)\r\n- Added the normalized LM API migration plan. (#9828 by @MaximeRivest)\r\n- Hardened workflows with actionlint/zizmor and SARIF permissions updates. (#9742, #9743, #9745 by @isaacbmiller)\r\n- Removed `git-auto-commit-action` from the release workflow. (#9746 by @isaacbmiller)\r\n- Updated `actions/setup-python` from 3.1.4 to 6.2.0. (#9602 by @dependabot[bot])\r\n- Updated runtime/development dependencies including `anyio`, `cachetools`, `tenacity`, `weaviate-client`, `mistune`, and `zizmor-action`. (#9730, #9731, #9732, #9760, #9759, #9787 by @dependabot[bot])\r\n\r\n## Contributors\r\n\r\n- @isaacbmiller\r\n- @MaximeRivest\r\n- @BenMcH\r\n- @abhicris\r\n- @kmad (first contribution, #9411)\r\n- @ashishSoni1234 (first contribution, #9741)\r\n- @Archelunch (first contribution, #9754)\r\n- @npow (first contribution, #9748)\r\n- @nullhack (first contribution, #9767)\r\n- @cosmopolitan033 (first contribution, #9798)\r\n\r\n**Full Changelog**: https://github.com/stanfordnlp/dspy/compare/3.2.1...3.3.0b1\r\n","reactions":{"url":"https://api.github.com/repos/stanfordnlp/dspy/releases/330299458/reactions","total_count":4,"+1":1,"-1":0,"laugh":0,"hooray":2,"confused":0,"heart":1,"rocket":0,"eyes":0},"mentions_count":11},{"url":"https://api.github.com/repos/stanfordnlp/dspy/releases/317491845","assets_url":"https://api.github.com/repos/stanfordnlp/dspy/releases/317491845/assets","upload_url":"https://uploads.github.com/repos/stanfordnlp/dspy/releases/317491845/assets{?name,label}","html_url":"https://github.com/stanfordnlp/dspy/releases/tag/3.2.1","id":317491845,"author":{"login":"isaacbmiller","id":17116851,"node_id":"MDQ6VXNlcjE3MTE2ODUx","avatar_url":"https://avatars.githubusercontent.com/u/17116851?v=4","gravatar_id":"","url":"https://api.github.com/users/isaacbmiller","html_url":"https://github.com/isaacbmiller","followers_url":"https://api.github.com/users/isaacbmiller/followers","following_url":"https://api.github.com/users/isaacbmiller/following{/other_user}","gists_url":"https://api.github.com/users/isaacbmiller/gists{/gist_id}","starred_url":"https://api.github.com/users/isaacbmiller/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/isaacbmiller/subscriptions","organizations_url":"https://api.github.com/users/isaacbmiller/orgs","repos_url":"https://api.github.com/users/isaacbmiller/repos","events_url":"https://api.github.com/users/isaacbmiller/events{/privacy}","received_events_url":"https://api.github.com/users/isaacbmiller/received_events","type":"User","user_view_type":"public","site_admin":false},"node_id":"RE_kwDOIv2ufM4S7IqF","tag_name":"3.2.1","target_commitish":"release-3.2","name":"3.2.1","draft":false,"immutable":true,"prerelease":false,"created_at":"2026-05-05T17:03:37Z","updated_at":"2026-05-05T19:37:48Z","published_at":"2026-05-05T19:37:48Z","assets":[],"tarball_url":"https://api.github.com/repos/stanfordnlp/dspy/tarball/3.2.1","zipball_url":"https://api.github.com/repos/stanfordnlp/dspy/zipball/3.2.1","body":"# DSPy 3.2.1 Changelog\r\n\r\n- Removed the upper bound on `litellm`. (#9687)\r\n- Usecase page has been updated! [https://dspy.ai/community/use-cases/](https://dspy.ai/community/use-cases/). To add your use-case, [open a PR](https://github.com/stanfordnlp/dspy/edit/main/docs/docs/community/use-cases.md)!\r\n\r\n## Bug fixes\r\n\r\n- Fixed async streaming LM calls so custom headers are forwarded to LiteLLM streaming completions. (#9669)\r\n- Fixed `dspy.Embedder` so per-call `caching=False` is honored for both sync and async embedding calls. (#9708)\r\n\r\n## Documentation\r\n\r\n- Moved Deployment into the technical documentation tabs and promoted production use cases under Community. (#9709)\r\n- Updated the production use-cases copy for DSPy.\r\n- Fixed MkDocs admonition rendering in Deployment and Observability docs. (#9690, #9691)\r\n- Fixed duplicate-word typos across docs, source, and tests. (#9695)\r\n\r\n## CI and release\r\n\r\n- Hardened TestPyPI release validation by adding strict `twine check` and reducing unused workflow permissions. (#9648)\r\n- Gave TestPyPI publishing its own GitHub environment. (#9649)\r\n- Removed an unused `setup-node` step from the docs push workflow. (#9702)\r\n- Replaced direct merge-to-main after publishing with a version bump PR. (#9716)\r\n- Refreshed `uv.lock` for the 3.2.0 release state. (#9650)\r\n\r\n## Dependency updates\r\n\r\n- Updated test and development dependencies: `pytest-asyncio`, `ruff`, `pre-commit`, `datamodel-code-generator`, `optuna`, and `urllib3`. (#9665, #9664, #9699, #9701, #9697, #9698)\r\n- Updated documentation dependencies: `mkdocs-llmstxt`, `mkdocstrings`, `mistune`, and `mkdocs-jupyter`. (#9661, #9668, #9666, #9700)\r\n- Updated GitHub Actions dependencies: `actions/cache` and `astral-sh/setup-uv`. (#9662, #9663)\r\n\r\n## Contributors\r\n\r\n- @isaacbmiller\r\n- @GopalGB (first contribution, #9695)\r\n- @spjosyula (first contribution, #9708)\r\n\r\n## Excluded\r\n\r\n- The GEPA 0.1.1 result/documentation update was intentionally excluded from this release. (#9673)","reactions":{"url":"https://api.github.com/repos/stanfordnlp/dspy/releases/317491845/reactions","total_count":5,"+1":0,"-1":0,"laugh":0,"hooray":5,"confused":0,"heart":0,"rocket":0,"eyes":0},"mentions_count":3},{"url":"https://api.github.com/repos/stanfordnlp/dspy/releases/311513499","assets_url":"https://api.github.com/repos/stanfordnlp/dspy/releases/311513499/assets","upload_url":"https://uploads.github.com/repos/stanfordnlp/dspy/releases/311513499/assets{?name,label}","html_url":"https://github.com/stanfordnlp/dspy/releases/tag/3.2.0","id":311513499,"author":{"login":"isaacbmiller","id":17116851,"node_id":"MDQ6VXNlcjE3MTE2ODUx","avatar_url":"https://avatars.githubusercontent.com/u/17116851?v=4","gravatar_id":"","url":"https://api.github.com/users/isaacbmiller","html_url":"https://github.com/isaacbmiller","followers_url":"https://api.github.com/users/isaacbmiller/followers","following_url":"https://api.github.com/users/isaacbmiller/following{/other_user}","gists_url":"https://api.github.com/users/isaacbmiller/gists{/gist_id}","starred_url":"https://api.github.com/users/isaacbmiller/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/isaacbmiller/subscriptions","organizations_url":"https://api.github.com/users/isaacbmiller/orgs","repos_url":"https://api.github.com/users/isaacbmiller/repos","events_url":"https://api.github.com/users/isaacbmiller/events{/privacy}","received_events_url":"https://api.github.com/users/isaacbmiller/received_events","type":"User","user_view_type":"public","site_admin":false},"node_id":"RE_kwDOIv2ufM4SkVGb","tag_name":"3.2.0","target_commitish":"release-3.2.0","name":"3.2.0","draft":false,"immutable":true,"prerelease":false,"created_at":"2026-04-21T16:02:56Z","updated_at":"2026-04-21T17:17:12Z","published_at":"2026-04-21T17:17:03Z","assets":[],"tarball_url":"https://api.github.com/repos/stanfordnlp/dspy/tarball/3.2.0","zipball_url":"https://api.github.com/repos/stanfordnlp/dspy/zipball/3.2.0","body":"## Highlights\r\n\r\n### BetterTogether Allows Chaining Optimizers — @dilarasoylu\r\n`BetterTogether` now accepts arbitrary optimizers as keyword arguments and chains them via strategy strings. For example, `BetterTogether(metric=m, p=GEPA(...), w=BootstrapFinetune(...))` with `strategy=\"p -> w -> p\"` will prompt-optimize, fine-tune, then prompt-optimize again -- evaluating each step on a valset and returning the best program. (#9149)\r\n\r\nThere are many promising strategies that may come from running multiple GEPA steps in sequence, or combining prompt and weight optimization steps in sequence, and we are excited to see what the community comes up with.\r\n\r\n### Beginning of decoupling DSPy from LiteLLM — @MaximeRivest\r\n@MaximeRivest has an ongoing effort to decouple DSPy from LiteLLM, making it much easier to use custom LMs with DSPy. In this release, adapters no longer import `litellm` at all -- `BaseLM` now exposes capability properties (`supports_function_calling`, `supports_reasoning`, `supports_response_schema`, `supported_params`) and a new `dspy.ContextWindowExceededError` replaces the `litellm` error throughout. Custom `BaseLM` backends can now integrate with DSPy's retry/truncation logic without any `litellm` dependency. (#9516, #9521, #9522)\r\n\r\n### Warning on Input field type mismatch — @michaelisaac-dev\r\nPassing a value that doesn't match a signature's declared type now logs a warning (using `typeguard`). Extra fields not in the signature also warn. Disable with `dspy.configure(warn_on_type_mismatch=False)`. (#9313)\r\n\r\n### Hardened RLM and PythonInterpreter — @isaacbmiller\r\nTool calls now use kwargs-only dispatch, the JS tool bridge returns structured errors instead of throwing (preventing Deno crashes), and stdout parsing skips non-JSON lines instead of crashing. Subprocess restarts now correctly replay tool/mount registration. (#9341, #9351)\r\n\r\n## Notices\r\n\r\n### Restricted pickle for disk cache\r\nWe have added an opt-in `dspy.configure_cache(restrict_pickle=True)` that swaps `pickle.load` with a restricted unpickler that only allows litellm/openai types, numpy reconstruction helpers, and user-registered `safe_types`. Prevents arbitrary code execution from corrupted or malicious cache files. (#9629)\r\n\r\nIn a future release, we will make this restriction the default behavior.\r\n\r\n### optuna is now optional\r\nMoved from a required dependency to `pip install dspy[optuna]`. Saves ~12.7 MB. Only `MIPROv2` and `BootstrapFewShotWithOptuna` use it. (#9397)\r\n\r\n---\r\n\r\n## All Changes\r\n\r\n### Features\r\n* Make BetterTogether compatible with all optimizers by @dilarasoylu (#9149)\r\n* feat: add verify parameter to Image for SSL bypass by @adityasingh2400 (#9279)\r\n* feat(signature): add type validation for input fields by @michaelisaac-dev (#9313)\r\n* feat: add file output support to inspect_history and fix return type by @bledden (#9321)\r\n* feat: make optuna optional by @isaacbmiller (#9397)\r\n* feat(retrievers): add EmbeddingsWithScores for similarity score access by @SerjSmor (#9478)\r\n* Add XMLAdapter to dspy.ai by @MaximeRivest (#9504)\r\n\r\n### Bug Fixes\r\n* fix(adapters): skip JSON schema for DSPy custom types in prompt by @darinkishore (#9257)\r\n* fix: ColBERTv2RetrieverLocal forward method variable scoping bug by @veeceey (#9272)\r\n* fix(predict): remove code corruption in ProgramOfThought._parse_code by @adityasingh2400 (#9276)\r\n* fix(RLM): show head and tail for RLM outputs by @isaacbmiller (#9282)\r\n* fix(rlm): change repl_variable preview to 1000 chars by @isaacbmiller (#9296)\r\n* fix(dspy): SemanticF1 and CompleteAndGrounded now return dspy.Prediction by @Copilot (#9302)\r\n* refactor(rlm): enhance code fence parsing and REPL entry formatting by @isaacbmiller (#9309)\r\n* Fix false rollout_id warning when LM temperature is unset by @okhat (#9316)\r\n* fix: pass metric_threshold to BootstrapFewShot for unshuffled case by @kvr06-ai (#9317)\r\n* fix: only suggest reducing valset in GEPA when it is large by @bledden (#9320)\r\n* fix: make DummyLM delegate to forward() instead of overriding __call__ by @bledden (#9322)\r\n* fix: run evaluation on main thread when num_threads=1 by @zamal-db (#9328)\r\n* fix(saving): block unsafe LM loading keys by @isaacbmiller (#9334)\r\n* fix(settings): add allow_pickle flag to settings loading by @isaacbmiller (#9339)\r\n* fix(interpreter): Harden JSONRPC communication and tool bridge by @isaacbmiller (#9341)\r\n* fix(interpreter): reset tools/mounts when Deno subprocess restarts by @isaacbmiller (#9351)\r\n* fix(adapters): pass use_native_function_calling in JSONAdapter.acall by @isaacbmiller (#9374)\r\n* fix(adapters): raise AdapterParseError on empty LM response instead of silent None by @isaacbmiller (#9389)\r\n* Deprecation warning for prefix, format, and parser kwargs in InputField/OutputField by @MaximeRivest (#9394)\r\n* fix(signature): reject duplicate input and output field names by @MaximeRivest (#9432)\r\n* fix(adapter): guard annotation subclass checks for ReAct tool args by @isaacbmiller (#9433)\r\n* fix(JSONAdapter): Ensure JSON serialization handles diacritics correctly for Pydantic BaseModel by @matrn (#9493)\r\n* Restrict litellm version to <=1.82.6 by @isaacbmiller (#9498)\r\n* fix(deps): pin typeguard==4.4.3 to prevent supply chain attacks by @isaacbmiller (#9551)\r\n* fix(lm): preserve per-message structure in Responses API conversion by @lawrence3699 (#9580)\r\n* fix: cloudpickle serialization of Signature on Python 3.14 by @isaacbmiller (#9616)\r\n* fix: correct demo index assignment in MIPROv2 raw_chosen_params by @Ricardo-M-L (#9627)\r\n* Fix cache bugs: os.fspath(None) crash, double disk lookups, lazy logging by @isaacbmiller (#9628)\r\n* Add restrict_pickle option for safe disk cache deserialization by @isaacbmiller (#9629)\r\n* Revert \"fix: set LITELLM_LOCAL_MODEL_COST_MAP before litellm import to avoid HTTP fetch\" by @isaacbmiller (#9637)\r\n* fix(base_lm): guard response.usage access to handle missing usage field by @isaacbmiller (#9638)\r\n\r\n### Refactors\r\n* Refactor: Make DummyLM and callbacks depend on BaseLM instead of LM by @MaximeRivest (#9515)\r\n* Refactor: Move model capability checks to BaseLM to remove litellm from adapters by @MaximeRivest (#9516)\r\n* Refactor: Introduce DSPy-owned ContextWindowExceededError to decouple error handling by @MaximeRivest (#9521)\r\n* refactor: type-hint adapters with BaseLM instead of LM by @MaximeRivest (#9522)\r\n\r\n### Security\r\n* fix(saving): block unsafe LM loading keys by @isaacbmiller (#9334)\r\n* Pin CI actions to SHA and replace curl-pipe-bash Deno install by @TomeHirata (#9509)\r\n* Create SECURITY.md by @isaacbmiller (#9529)\r\n* docs: add ai generated code policy by @isaacbmiller (#9586)\r\n\r\n### Testing\r\n* fix(deno): Add pytest.mark.deno by @isaacbmiller (#9269)\r\n\r\n### Docs\r\n* docs(RLMS): add initial rlm docs by @isaacbmiller (#9264)\r\n* fix(docs): Fix tool description on RLM docs by @isaacbmiller (#9270)\r\n* fix: correct typo 'occured' to 'occurred' by @thecaptain789 (#9268)\r\n* Add R port to community ports documentation by @JamesHWade (#9278)\r\n* fix: typo 'itinery_database' to 'itinerary_database' by @TheOnlyWayUp (#9274)\r\n* docs(rlm): fix RLM docs consistency and typos by @shirvani-jr (#9280)\r\n* Add missing docstrings in dspy/utils/hasher.py by @immerSIR (#9293)\r\n* [docs] add Google-style docstrings to Module class by @Tanmay-24 (#9175)\r\n* docs: complete llmstxt plugin with full nav sections by @ahmeshaf (#9307)\r\n* docs: Add 'Copy page' button to fetch and copy raw Markdown by @zamal-db (#9327)\r\n* docs: add Vertex AI (GCP) tab to Language Models guide by @zamal-db (#9329)\r\n* docs: clarify max_rounds behavior in BootstrapFewShot by @bledden (#9319)\r\n* docs: Update read_output_stream to return final value by @gauravkumar37 (#8977)\r\n* Add docstrings to dspy/clients/provider.py by @dev-josias (#9140)\r\n* docs: remove n=5 assumption from modules tutorial example by @MaximeRivest (#9380)\r\n* docs(evaluate): add docstrings to auto_evaluation.py by @stbiadmin (#9399)\r\n* docs: add docstrings to utility functions in utils.py by @Jah-yee (#9371)\r\n* Fix/docstring examples section header by @MaximeRivest (#9418)\r\n* Enhance docstring for Parallel class by @juntaoyou (#9390)\r\n* docs: fix module_end_status_message description in tutorial docs by @paul-tharun (#9144)\r\n* Update optimizer import documentation to use modern pattern by @0xRaduan (#8980)\r\n* Add API reference pages for dspy.configure and dspy.context by @MaximeRivest (#9445)\r\n* Improve dspy.Example docstrings and examples by @MaximeRivest (#9444)\r\n* fix(docs): remove broken BetterTogether tutorial links by @isaacbmiller (#9480)\r\n* [docs] Remove misleading confidence field from Classification example by @xieyj17 (#9495)\r\n* docs: fix duplicate 'the the' typos across docs, source, and tests by @abhicris (#9641)\r\n\r\n### CI / Infrastructure\r\n* chore: bump uv.lock by @isaacbmiller (#9263)\r\n* fix(precommit): remove hardcoded python version by @isaacbmiller (#9346)\r\n* chore: Add greenlet s390x wheel entries to uv.lock by @isaacbmiller (#9455)\r\n* ci: drop unused write permissions from ruff lint job by @isaacbmiller (#9505)\r\n* fix(ci): correct setup-node SHA typo in docs-push workflow by @isaacbmiller (#9528)\r\n* chore: add dependabot configuration for automated dependency updates by @isaacbmiller (#9592)\r\n* chore(dspy): bump gepa from 0.0.26 to 0.0.27 by @isaacbmiller (#9416)\r\n* feat(ci): Create PRs with ruff fixes automatically by @isaacbmiller (#9336) -- reverted (#9345)\r\n\r\n### Dependency updates (Dependabot)\r\n* orjson 3.11.2 -> 3.11.8 (#9597)\r\n* requests 2.32.4 -> 2.33.1 (#9603)\r\n* anthropic 0.54.0 -> 0.89.0 (#9599)\r\n* tqdm 4.67.1 -> 4.67.3 (#9623)\r\n* pre-commit 4.2.0 -> 4.5.1 (#9622)\r\n* denoland/setup-deno 2.0.3 -> 2.0.4 (#9596)\r\n* actions/checkout 3.6.0 -> 6.0.2 (#9595)\r\n* actions/setup-node 3.9.1 -> 6.3.0 (#9600)\r\n* stefanzweifel/git-auto-commit-action 5.2.0 -> 7.1.0 (#9598)\r\n* pypa/gh-action-pypi-publish 1.13.0 -> 1.14.0 (#9618)\r\n* mkdocs-jupyter 0.25.1 -> 0.26.1 (#9605)\r\n* mkdocstrings 0.29.0 -> 1.0.3 (#9609)\r\n* mkdocs-material 9.6.9 -> 9.7.6 (#9608)\r\n* mkdocs-redirects 1.2.2 -> 1.2.3 (#9607)\r\n* mistune 3.0.2 -> 3.2.0 (#9625)\r\n\r\n### New Contributors\r\n* @thecaptain789 made their first contribution in #9268\r\n* @TheOnlyWayUp made their first contribution in #9274\r\n* @shirvani-jr made their first contribution in #9280\r\n* @adityasingh2400 made their first contribution in #9279\r\n* @immerSIR made their first contribution in #9293\r\n* @Tanmay-24 made their first contribution in #9175\r\n* @ahmeshaf made their first contribution in #9307\r\n* @kvr06-ai made their first contribution in #9317\r\n* @zamal-db made their first contribution in #9327\r\n* @bledden made their first contribution in #9319\r\n* @gauravkumar37 made their first contribution in #8977\r\n* @dev-josias made their first contribution in #9140\r\n* @veeceey made their first contribution in #9272\r\n* @stbiadmin made their first contribution in #9399\r\n* @Jah-yee made their first contribution in #9371\r\n* @michaelisaac-dev made their first contribution in #9313\r\n* @juntaoyou made their first contribution in #9390\r\n* @paul-tharun made their first contribution in #9144\r\n* @matrn made their first contribution in #9493\r\n* @SerjSmor made their first contribution in #9478\r\n* @xieyj17 made their first contribution in #9495\r\n* @Ricardo-M-L made their first contribution in #9627\r\n* @lawrence3699 made their first contribution in #9580\r\n* @abhicris made their first contribution in #9641\r\n\r\n**Full Changelog**: https://github.com/stanfordnlp/dspy/compare/3.1.3...3.2.0\r\n","mentions_count":32},{"url":"https://api.github.com/repos/stanfordnlp/dspy/releases/283424902","assets_url":"https://api.github.com/repos/stanfordnlp/dspy/releases/283424902/assets","upload_url":"https://uploads.github.com/repos/stanfordnlp/dspy/releases/283424902/assets{?name,label}","html_url":"https://github.com/stanfordnlp/dspy/releases/tag/3.1.3","id":283424902,"author":{"login":"okhat","id":963532,"node_id":"MDQ6VXNlcjk2MzUzMg==","avatar_url":"https://avatars.githubusercontent.com/u/963532?v=4","gravatar_id":"","url":"https://api.github.com/users/okhat","html_url":"https://github.com/okhat","followers_url":"https://api.github.com/users/okhat/followers","following_url":"https://api.github.com/users/okhat/following{/other_user}","gists_url":"https://api.github.com/users/okhat/gists{/gist_id}","starred_url":"https://api.github.com/users/okhat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/okhat/subscriptions","organizations_url":"https://api.github.com/users/okhat/orgs","repos_url":"https://api.github.com/users/okhat/repos","events_url":"https://api.github.com/users/okhat/events{/privacy}","received_events_url":"https://api.github.com/users/okhat/received_events","type":"User","user_view_type":"public","site_admin":false},"node_id":"RE_kwDOIv2ufM4Q5LiG","tag_name":"3.1.3","target_commitish":"main","name":"3.1.3","draft":false,"immutable":false,"prerelease":false,"created_at":"2026-02-05T16:01:35Z","updated_at":"2026-02-05T16:18:52Z","published_at":"2026-02-05T16:18:52Z","assets":[],"tarball_url":"https://api.github.com/repos/stanfordnlp/dspy/tarball/3.1.3","zipball_url":"https://api.github.com/repos/stanfordnlp/dspy/zipball/3.1.3","body":"## What's Changed\r\n\r\nRLMs\r\n* fix(interpreter): Fix enable_read_paths with multiple files by @missing-piece in https://github.com/stanfordnlp/dspy/pull/9256\r\n* fix: handle dict response in RLM for reasoning models by @darinkishore in https://github.com/stanfordnlp/dspy/pull/9219\r\n* feat(CodeInterpreter): Convert messaging format to JSONRPC by @isaacbmiller in https://github.com/stanfordnlp/dspy/pull/9226\r\n* feat(RLMs): Fix code fence parsing by @isaacbmiller in https://github.com/stanfordnlp/dspy/pull/9231\r\n* fix(RLM): large variable injection by @isaacbmiller in https://github.com/stanfordnlp/dspy/pull/9233\r\n* fix(RLM): no longer get stuck on imports by @isaacbmiller in https://github.com/stanfordnlp/dspy/pull/9234\r\n* fix(RLM): Refactor tools to take list instead of dict and properly serialize None/null values by @isaacbmiller in https://github.com/stanfordnlp/dspy/pull/9247\r\n\r\nGEPA\r\n* Update gepa[dspy] dependency to version 0.0.26 adding support for cached evals in GEPA expected to reduce metric calls, fix MLFlow logging, and bug fixes by @LakshyAAAgrawal in https://github.com/stanfordnlp/dspy/pull/9238\r\n* Update gepa[dspy] version to 0.0.25 adding python==3.14 support by @LakshyAAAgrawal in https://github.com/stanfordnlp/dspy/pull/9224\r\n* Temporarily remove the GEPA tool optimization doc by @chenmoneygithub in https://github.com/stanfordnlp/dspy/pull/9220\r\n* fix(gepa): Remove enable_tool_optimization feature by @Ju-usc in https://github.com/stanfordnlp/dspy/pull/9223\r\n\r\n\r\n\r\nMaintenance\r\n* Stabilize real LM tests with deterministic temperature by @okhat in https://github.com/stanfordnlp/dspy/pull/9218\r\n* fix: handle error responses from ColBERTv2 server by @emmanuel-ferdman in https://github.com/stanfordnlp/dspy/pull/9227\r\n* Fix format  by @chenmoneygithub in https://github.com/stanfordnlp/dspy/pull/9249\r\n* Fix the request header in streaming mode by @chenmoneygithub in https://github.com/stanfordnlp/dspy/pull/9248\r\n* feat(docs): add community ports page by @isaacbmiller in https://github.com/stanfordnlp/dspy/pull/9222\r\n\r\n\r\nDeferred to a later release (added then reverted before cutting this release):\r\n* Allow DSPy to use the native reasoning from models by @chenmoneygithub in https://github.com/stanfordnlp/dspy/pull/8822\r\n* Revert ChainOfThought to pre-dspy.Reasoning (#8822) behavior by @okhat in https://github.com/stanfordnlp/dspy/pull/9258\r\n\r\n## New Contributors\r\n* @missing-piece made their first contribution in https://github.com/stanfordnlp/dspy/pull/9256\r\n\r\n**Full Changelog**: https://github.com/stanfordnlp/dspy/compare/3.1.2...3.1.3","reactions":{"url":"https://api.github.com/repos/stanfordnlp/dspy/releases/283424902/reactions","total_count":4,"+1":0,"-1":0,"laugh":0,"hooray":4,"confused":0,"heart":0,"rocket":0,"eyes":0},"mentions_count":8},{"url":"https://api.github.com/repos/stanfordnlp/dspy/releases/277943662","assets_url":"https://api.github.com/repos/stanfordnlp/dspy/releases/277943662/assets","upload_url":"https://uploads.github.com/repos/stanfordnlp/dspy/releases/277943662/assets{?name,label}","html_url":"https://github.com/stanfordnlp/dspy/releases/tag/3.1.2","id":277943662,"author":{"login":"okhat","id":963532,"node_id":"MDQ6VXNlcjk2MzUzMg==","avatar_url":"https://avatars.githubusercontent.com/u/963532?v=4","gravatar_id":"","url":"https://api.github.com/users/okhat","html_url":"https://github.com/okhat","followers_url":"https://api.github.com/users/okhat/followers","following_url":"https://api.github.com/users/okhat/following{/other_user}","gists_url":"https://api.github.com/users/okhat/gists{/gist_id}","starred_url":"https://api.github.com/users/okhat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/okhat/subscriptions","organizations_url":"https://api.github.com/users/okhat/orgs","repos_url":"https://api.github.com/users/okhat/repos","events_url":"https://api.github.com/users/okhat/events{/privacy}","received_events_url":"https://api.github.com/users/okhat/received_events","type":"User","user_view_type":"public","site_admin":false},"node_id":"RE_kwDOIv2ufM4QkRVu","tag_name":"3.1.2","target_commitish":"main","name":"3.1.2","draft":false,"immutable":false,"prerelease":false,"created_at":"2026-01-19T14:08:19Z","updated_at":"2026-01-19T14:16:35Z","published_at":"2026-01-19T14:16:35Z","assets":[],"tarball_url":"https://api.github.com/repos/stanfordnlp/dspy/tarball/3.1.2","zipball_url":"https://api.github.com/repos/stanfordnlp/dspy/zipball/3.1.2","body":"## What's Changed\r\n\r\nMaintenance\r\n* ci: install Deno in release workflow by @okhat in https://github.com/stanfordnlp/dspy/pull/9217\r\n* Fix download bug in RAG tutorial by @togimoto in https://github.com/stanfordnlp/dspy/pull/9156\r\n* Update DSpy settings save / load methods by @WeichenXu123 in https://github.com/stanfordnlp/dspy/pull/9215\r\n* Expose timeout and straggler_limit params in Parallel by @halfprice06 in https://github.com/stanfordnlp/dspy/pull/9199\r\n* Fix JSON parsing: Removing initial regex extraction. by @blightzero in https://github.com/stanfordnlp/dspy/pull/9182\r\n\r\n## New Contributors\r\n* @halfprice06 made their first contribution in https://github.com/stanfordnlp/dspy/pull/9199\r\n* @blightzero made their first contribution in https://github.com/stanfordnlp/dspy/pull/9182\r\n\r\n**Full Changelog**: https://github.com/stanfordnlp/dspy/compare/3.1.1...3.1.2","reactions":{"url":"https://api.github.com/repos/stanfordnlp/dspy/releases/277943662/reactions","total_count":4,"+1":4,"-1":0,"laugh":0,"hooray":0,"confused":0,"heart":0,"rocket":0,"eyes":0},"mentions_count":5},{"url":"https://api.github.com/repos/stanfordnlp/dspy/releases/277783876","assets_url":"https://api.github.com/repos/stanfordnlp/dspy/releases/277783876/assets","upload_url":"https://uploads.github.com/repos/stanfordnlp/dspy/releases/277783876/assets{?name,label}","html_url":"https://github.com/stanfordnlp/dspy/releases/tag/3.1.1","id":277783876,"author":{"login":"okhat","id":963532,"node_id":"MDQ6VXNlcjk2MzUzMg==","avatar_url":"https://avatars.githubusercontent.com/u/963532?v=4","gravatar_id":"","url":"https://api.github.com/users/okhat","html_url":"https://github.com/okhat","followers_url":"https://api.github.com/users/okhat/followers","following_url":"https://api.github.com/users/okhat/following{/other_user}","gists_url":"https://api.github.com/users/okhat/gists{/gist_id}","starred_url":"https://api.github.com/users/okhat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/okhat/subscriptions","organizations_url":"https://api.github.com/users/okhat/orgs","repos_url":"https://api.github.com/users/okhat/repos","events_url":"https://api.github.com/users/okhat/events{/privacy}","received_events_url":"https://api.github.com/users/okhat/received_events","type":"User","user_view_type":"public","site_admin":false},"node_id":"RE_kwDOIv2ufM4QjqVE","tag_name":"3.1.1","target_commitish":"main","name":"3.1.1","draft":false,"immutable":false,"prerelease":false,"created_at":"2026-01-19T02:23:56Z","updated_at":"2026-01-19T02:30:49Z","published_at":"2026-01-19T02:30:49Z","assets":[],"tarball_url":"https://api.github.com/repos/stanfordnlp/dspy/tarball/3.1.1","zipball_url":"https://api.github.com/repos/stanfordnlp/dspy/zipball/3.1.1","body":"## What's Changed\r\n\r\nRLMs\r\n* feat(rlm): Add RLM Module and improve PythonInterpreter by @isaacbmiller in https://github.com/stanfordnlp/dspy/pull/9193\r\n* Use `language` in system instructions for `dspy.Code` fields by @mariusarvinte in https://github.com/stanfordnlp/dspy/pull/9106\r\n* Update dspy.RLM to improve reliability and avoid pydantic warnings by @okhat in https://github.com/stanfordnlp/dspy/pull/9210\r\n* fix(RLM): Change FinalAnswerResult to FinalOutput and remove RLM __call__ by @isaacbmiller in https://github.com/stanfordnlp/dspy/pull/9212\r\n\r\n\r\nGEPA\r\n* Fix GEPAFeedbackMetric Protocol missing 'self' parameter by @Copilot in https://github.com/stanfordnlp/dspy/pull/9111\r\n* feat(gepa): add tool description optimization for multi-agent systems by @Ju-usc in https://github.com/stanfordnlp/dspy/pull/8928\r\n* Update pyproject.toml to update gepa from 0.0.22 -> 0.0.24 by @LakshyAAAgrawal in https://github.com/stanfordnlp/dspy/pull/9161\r\n* Patch `dspy.gepa` to handle `list[dict]` output from a `dspy.LM` by @mariusarvinte in https://github.com/stanfordnlp/dspy/pull/9169\r\n\r\n\r\n\r\nAdapters\r\n* Upgrade json_repair to fix parsing issue of underscore-style float number by @chenmoneygithub in https://github.com/stanfordnlp/dspy/pull/9088\r\n* Properly yield the last chunk in streaming by @chenmoneygithub in https://github.com/stanfordnlp/dspy/pull/9089\r\n* Avoid unwanted exception chaining when running async tool in sync context by @stevapple in https://github.com/stanfordnlp/dspy/pull/9092\r\n* Enhance StreamListener to support generic type annotations for output by @TomeHirata in https://github.com/stanfordnlp/dspy/pull/9112\r\n* FIX: streamify was appending StatusStreamingCallback directly to the shared settings.callbacks list by @glesperance in https://github.com/stanfordnlp/dspy/pull/9073\r\n* fix(BAMLAdapter): Use docstrings to describe BaseModels by @BenMcH in https://github.com/stanfordnlp/dspy/pull/9125\r\n* Fix Responses API structured outputs by @Olocool17 in https://github.com/stanfordnlp/dspy/pull/9130\r\n\r\n\r\nMaintenance\r\n* Fix UsageTracker AttributeError when using ParallelExecutor with dspy.context by @Copilot in https://github.com/stanfordnlp/dspy/pull/9095\r\n* Update uv.lock dspy version to match the latest release by @chenmoneygithub in https://github.com/stanfordnlp/dspy/pull/9067\r\n* [docs] Add Google-style docstrings for dspy/adapters/chat_adapter.py ChatAdapter class #9063 by @azai91 in https://github.com/stanfordnlp/dspy/pull/9072\r\n* Fix ContextWindowExceededError after 3 retries in react loop by @Copilot in https://github.com/stanfordnlp/dspy/pull/9110\r\n* fix: skip merging when both usage entry values are None by @chizukicn in https://github.com/stanfordnlp/dspy/pull/9121\r\n* Fix: enforce positive `memory_max_entries` for in-memory cache by @mshr-h in https://github.com/stanfordnlp/dspy/pull/9128\r\n* Add typing to `dspy.datasets.dataset` by @max-muoto in https://github.com/stanfordnlp/dspy/pull/9143\r\n* Increase max_iters for dspy.ReAct by @chenmoneygithub in https://github.com/stanfordnlp/dspy/pull/9162\r\n* fix(dspy): prevent argument injection in LocalProvider subprocess calls by @Copilot in https://github.com/stanfordnlp/dspy/pull/9160\r\n* fix(dspy): populate InputField default values in Predict by @ritsuki1227 in https://github.com/stanfordnlp/dspy/pull/9167\r\n* fix(PythonInterpreter): Remove overly permissive read permissions and add strict allow by @isaacbmiller in https://github.com/stanfordnlp/dspy/pull/9081\r\n* Add save / load methods for DSpy settings by @WeichenXu123 in https://github.com/stanfordnlp/dspy/pull/9165\r\n\r\n\r\nDocs\r\n* [doc] Correct conversation history tutorial example by @zhiyanliu in https://github.com/stanfordnlp/dspy/pull/9071\r\n* fix: Resolve broken hover-nlp/hover dataset by @vincentkoc in https://github.com/stanfordnlp/dspy/pull/9069\r\n* Fix missing Real-World Examples and Experimental RL Optimization sections on tutorials page by @0xRaduan in https://github.com/stanfordnlp/dspy/pull/8982\r\n* Refactor ReflectiveExample TypedDict documentation by @LakshyAAAgrawal in https://github.com/stanfordnlp/dspy/pull/9133\r\n* [Automatic] Update api reference by @chenmoneygithub in https://github.com/stanfordnlp/dspy/pull/9135\r\n* Replace ujson with orjson in docs by @togimoto in https://github.com/stanfordnlp/dspy/pull/9148\r\n\r\n\r\n\r\n## New Contributors\r\n* @zhiyanliu made their first contribution in https://github.com/stanfordnlp/dspy/pull/9071\r\n* @azai91 made their first contribution in https://github.com/stanfordnlp/dspy/pull/9072\r\n* @0xRaduan made their first contribution in https://github.com/stanfordnlp/dspy/pull/8982\r\n* @Ju-usc made their first contribution in https://github.com/stanfordnlp/dspy/pull/8928\r\n* @mariusarvinte made their first contribution in https://github.com/stanfordnlp/dspy/pull/9106\r\n* @Olocool17 made their first contribution in https://github.com/stanfordnlp/dspy/pull/9130\r\n* @chizukicn made their first contribution in https://github.com/stanfordnlp/dspy/pull/9121\r\n* @mshr-h made their first contribution in https://github.com/stanfordnlp/dspy/pull/9128\r\n* @max-muoto made their first contribution in https://github.com/stanfordnlp/dspy/pull/9143\r\n* @togimoto made their first contribution in https://github.com/stanfordnlp/dspy/pull/9148\r\n* @ritsuki1227 made their first contribution in https://github.com/stanfordnlp/dspy/pull/9167\r\n* @WeichenXu123 made their first contribution in https://github.com/stanfordnlp/dspy/pull/9165\r\n\r\n**Full Changelog**: https://github.com/stanfordnlp/dspy/compare/3.1.0...3.1.1","reactions":{"url":"https://api.github.com/repos/stanfordnlp/dspy/releases/277783876/reactions","total_count":1,"+1":0,"-1":0,"laugh":0,"hooray":0,"confused":0,"heart":0,"rocket":1,"eyes":0},"mentions_count":21},{"url":"https://api.github.com/repos/stanfordnlp/dspy/releases/274610657","assets_url":"https://api.github.com/repos/stanfordnlp/dspy/releases/274610657/assets","upload_url":"https://uploads.github.com/repos/stanfordnlp/dspy/releases/274610657/assets{?name,label}","html_url":"https://github.com/stanfordnlp/dspy/releases/tag/3.1.0","id":274610657,"author":{"login":"chenmoneygithub","id":22925031,"node_id":"MDQ6VXNlcjIyOTI1MDMx","avatar_url":"https://avatars.githubusercontent.com/u/22925031?v=4","gravatar_id":"","url":"https://api.github.com/users/chenmoneygithub","html_url":"https://github.com/chenmoneygithub","followers_url":"https://api.github.com/users/chenmoneygithub/followers","following_url":"https://api.github.com/users/chenmoneygithub/following{/other_user}","gists_url":"https://api.github.com/users/chenmoneygithub/gists{/gist_id}","starred_url":"https://api.github.com/users/chenmoneygithub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chenmoneygithub/subscriptions","organizations_url":"https://api.github.com/users/chenmoneygithub/orgs","repos_url":"https://api.github.com/users/chenmoneygithub/repos","events_url":"https://api.github.com/users/chenmoneygithub/events{/privacy}","received_events_url":"https://api.github.com/users/chenmoneygithub/received_events","type":"User","user_view_type":"public","site_admin":false},"node_id":"RE_kwDOIv2ufM4QXjnh","tag_name":"3.1.0","target_commitish":"release-3.1.0b1","name":"3.1.0","draft":false,"immutable":false,"prerelease":false,"created_at":"2025-11-18T00:29:24Z","updated_at":"2026-01-06T18:48:05Z","published_at":"2026-01-06T18:48:05Z","assets":[],"tarball_url":"https://api.github.com/repos/stanfordnlp/dspy/tarball/3.1.0","zipball_url":"https://api.github.com/repos/stanfordnlp/dspy/zipball/3.1.0","body":"## What's Changed\r\n\r\nThis is a 3.1.0 official release. We are making the beta release 3.1.0beta1 official.\r\n\r\n### Optimizers & Evaluation\r\n\r\n* Add tutorial for dspy-trusted-monitor using GEPA by @ZachParent in https://github.com/stanfordnlp/dspy/pull/8938\r\n* Update gepa[dspy] dependency version to 0.0.18 by @LakshyAAAgrawal in https://github.com/stanfordnlp/dspy/pull/8969\r\n* fix(MIPROv2): zero shot not taking .compile parameters into account before determining if the program was zero shot by @isaacbmiller in https://github.com/stanfordnlp/dspy/pull/8909\r\n* Update gepa[dspy] dependency version to 0.0.22 by @LakshyAAAgrawal in https://github.com/stanfordnlp/dspy/pull/9042\r\n* [docs] Add GEPA gepa_kwargs documentation by @GabrielLoiseau in https://github.com/stanfordnlp/dspy/pull/8998\r\n* Update optimizer overview to include the description of SIMBA by @TomeHirata in https://github.com/stanfordnlp/dspy/pull/9026\r\n* Enable callback logging only for full eval on GEPA by @TomeHirata in https://github.com/stanfordnlp/dspy/pull/9050\r\n* Update Arbor Tutorials by @Ziems in https://github.com/stanfordnlp/dspy/pull/9007\r\n* Update RL Tutorial by @Ziems in https://github.com/stanfordnlp/dspy/pull/9008\r\n\r\n### Features & Enhancements\r\n\r\n* Add Disable Fallback Option in ChatAdapter by @Ziems in https://github.com/stanfordnlp/dspy/pull/8984\r\n* Add a method to extract system message based on adapter and signature by @chenmoneygithub in https://github.com/stanfordnlp/dspy/pull/9006\r\n* feat(File): add File type for handling file data by @TomeHirata in https://github.com/stanfordnlp/dspy/pull/9014\r\n* Allow stream listener to work on any type by @chenmoneygithub in https://github.com/stanfordnlp/dspy/pull/8833\r\n* fix(audio): Normalize 'x-wav' audio format to 'wav' by @akshatvishu in https://github.com/stanfordnlp/dspy/pull/9017\r\n* Support Python 3.14 by @TomeHirata in https://github.com/stanfordnlp/dspy/pull/9041\r\n* Introduce dspy.Reasoning to capture native reasoning from reasoning models by @chenmoneygithub in https://github.com/stanfordnlp/dspy/pull/8986\r\n\r\n### Security & Serialization\r\n\r\n* Add guards against loading pkl files by @isaacbmiller in https://github.com/stanfordnlp/dspy/pull/9048\r\n* Add param to load_memory_cache to stop pkl files without explicit loading by @isaacbmiller in https://github.com/stanfordnlp/dspy/pull/9055\r\n\r\n### Bug Fixes & Type Handling\r\n\r\n* Fix TypeError when tracking usage with Anthropic models returning Pydantic objects by @Copilot in https://github.com/stanfordnlp/dspy/pull/8978\r\n* Update old Anthropic model names by @TomeHirata in https://github.com/stanfordnlp/dspy/pull/8992\r\n* fix(XMLAdapter): Implement user message formatting by @BenMcH in https://github.com/stanfordnlp/dspy/pull/9003\r\n* Fix content input conversion for OpenAI Responses API by @Copilot in https://github.com/stanfordnlp/dspy/pull/8993\r\n* Refactor: update type hints for adapter and LM methods by @TomeHirata in https://github.com/stanfordnlp/dspy/pull/9025\r\n* fix(dspy): exclude gpt-5-chat from reasoning model classification by @mindful-time in https://github.com/stanfordnlp/dspy/pull/9033\r\n* fix(dspy): Example.toDict() fails to serialize dspy.History objects by @Copilot in https://github.com/stanfordnlp/dspy/pull/9047\r\n* Some continuous format fix by @chenmoneygithub in https://github.com/stanfordnlp/dspy/pull/8987\r\n\r\n### Documentation & Tutorials\r\n\r\n* Add documentation for provider-side prompt caching with Anthropic and OpenAI by @Copilot in https://github.com/stanfordnlp/dspy/pull/8970\r\n* [docs] Add Google-style docstrings for dspy/evaluate/metrics.py by @eramis73 in https://github.com/stanfordnlp/dspy/pull/8954\r\n* fix: broken PyPI downloads badge from pepy.tech in README and docs home page by @dushmanta05 in https://github.com/stanfordnlp/dspy/pull/8995\r\n* Document ToolCall.execute() availability from dspy 3.0.4b2 by @Copilot in https://github.com/stanfordnlp/dspy/pull/9004\r\n* fix(docs): add python language id to code block by @Ahmad8864 in https://github.com/stanfordnlp/dspy/pull/9023\r\n* docs: add note on Python version for pre-commit by @akshatvishu in https://github.com/stanfordnlp/dspy/pull/9028\r\n* chore(docs): update dspy.settings.configure and dspy.settings.context to dspy.configure and dspy.context by @isaacbmiller in https://github.com/stanfordnlp/dspy/pull/9060\r\n* docs: add documentation for async tool usage and error handling by @TomeHirata in https://github.com/stanfordnlp/dspy/pull/9054\r\n\r\n### Minor Fixes, Maintenance & CI\r\n\r\n* Remove unused notebook python file by @TomeHirata in https://github.com/stanfordnlp/dspy/pull/8971\r\n* Cache Ollama to speed up CI by @TomeHirata in https://github.com/stanfordnlp/dspy/pull/8972\r\n* Clean out unused deps by @isaacbmiller in https://github.com/stanfordnlp/dspy/pull/8968\r\n* docs: add note on Python version for pre-commit by @akshatvishu in https://github.com/stanfordnlp/dspy/pull/9028\r\n* Bump DSPy version by @chenmoneygithub in https://github.com/stanfordnlp/dspy/pull/9061\r\n\r\n## New Contributors\r\n\r\n* @ZachParent made their first contribution in https://github.com/stanfordnlp/dspy/pull/8938\r\n* @eramis73 made their first contribution in https://github.com/stanfordnlp/dspy/pull/8954\r\n* @dushmanta05 made their first contribution in https://github.com/stanfordnlp/dspy/pull/8995\r\n* @akshatvishu made their first contribution in https://github.com/stanfordnlp/dspy/pull/9017\r\n* @mindful-time made their first contribution in https://github.com/stanfordnlp/dspy/pull/9033\r\n* @GabrielLoiseau made their first contribution in https://github.com/stanfordnlp/dspy/pull/8998\r\n* @Ahmad8864 made their first contribution in https://github.com/stanfordnlp/dspy/pull/9023\r\n\r\n**Full Changelog**: https://github.com/stanfordnlp/dspy/compare/3.0.4...3.1.0b1","reactions":{"url":"https://api.github.com/repos/stanfordnlp/dspy/releases/274610657/reactions","total_count":1,"+1":0,"-1":0,"laugh":0,"hooray":0,"confused":0,"heart":1,"rocket":0,"eyes":0},"mentions_count":13},{"url":"https://api.github.com/repos/stanfordnlp/dspy/releases/263136283","assets_url":"https://api.github.com/repos/stanfordnlp/dspy/releases/263136283/assets","upload_url":"https://uploads.github.com/repos/stanfordnlp/dspy/releases/263136283/assets{?name,label}","html_url":"https://github.com/stanfordnlp/dspy/releases/tag/3.1.0b1","id":263136283,"author":{"login":"chenmoneygithub","id":22925031,"node_id":"MDQ6VXNlcjIyOTI1MDMx","avatar_url":"https://avatars.githubusercontent.com/u/22925031?v=4","gravatar_id":"","url":"https://api.github.com/users/chenmoneygithub","html_url":"https://github.com/chenmoneygithub","followers_url":"https://api.github.com/users/chenmoneygithub/followers","following_url":"https://api.github.com/users/chenmoneygithub/following{/other_user}","gists_url":"https://api.github.com/users/chenmoneygithub/gists{/gist_id}","starred_url":"https://api.github.com/users/chenmoneygithub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chenmoneygithub/subscriptions","organizations_url":"https://api.github.com/users/chenmoneygithub/orgs","repos_url":"https://api.github.com/users/chenmoneygithub/repos","events_url":"https://api.github.com/users/chenmoneygithub/events{/privacy}","received_events_url":"https://api.github.com/users/chenmoneygithub/received_events","type":"User","user_view_type":"public","site_admin":false},"node_id":"RE_kwDOIv2ufM4PryQb","tag_name":"3.1.0b1","target_commitish":"main","name":"3.1.0b1","draft":false,"immutable":false,"prerelease":true,"created_at":"2025-11-17T07:37:47Z","updated_at":"2025-11-18T00:26:51Z","published_at":"2025-11-18T00:26:51Z","assets":[],"tarball_url":"https://api.github.com/repos/stanfordnlp/dspy/tarball/3.1.0b1","zipball_url":"https://api.github.com/repos/stanfordnlp/dspy/zipball/3.1.0b1","body":"## What's Changed\r\n\r\nThis is a pre-release for 3.1.0. \r\n\r\n### Optimizers & Evaluation\r\n\r\n* Add tutorial for dspy-trusted-monitor using GEPA by @ZachParent in https://github.com/stanfordnlp/dspy/pull/8938\r\n* Update gepa[dspy] dependency version to 0.0.18 by @LakshyAAAgrawal in https://github.com/stanfordnlp/dspy/pull/8969\r\n* fix(MIPROv2): zero shot not taking .compile parameters into account before determining if the program was zero shot by @isaacbmiller in https://github.com/stanfordnlp/dspy/pull/8909\r\n* Update gepa[dspy] dependency version to 0.0.22 by @LakshyAAAgrawal in https://github.com/stanfordnlp/dspy/pull/9042\r\n* [docs] Add GEPA gepa_kwargs documentation by @GabrielLoiseau in https://github.com/stanfordnlp/dspy/pull/8998\r\n* Update optimizer overview to include the description of SIMBA by @TomeHirata in https://github.com/stanfordnlp/dspy/pull/9026\r\n* Enable callback logging only for full eval on GEPA by @TomeHirata in https://github.com/stanfordnlp/dspy/pull/9050\r\n* Update Arbor Tutorials by @Ziems in https://github.com/stanfordnlp/dspy/pull/9007\r\n* Update RL Tutorial by @Ziems in https://github.com/stanfordnlp/dspy/pull/9008\r\n\r\n### Features & Enhancements\r\n\r\n* Add Disable Fallback Option in ChatAdapter by @Ziems in https://github.com/stanfordnlp/dspy/pull/8984\r\n* Add a method to extract system message based on adapter and signature by @chenmoneygithub in https://github.com/stanfordnlp/dspy/pull/9006\r\n* feat(File): add File type for handling file data by @TomeHirata in https://github.com/stanfordnlp/dspy/pull/9014\r\n* Allow stream listener to work on any type by @chenmoneygithub in https://github.com/stanfordnlp/dspy/pull/8833\r\n* fix(audio): Normalize 'x-wav' audio format to 'wav' by @akshatvishu in https://github.com/stanfordnlp/dspy/pull/9017\r\n* Support Python 3.14 by @TomeHirata in https://github.com/stanfordnlp/dspy/pull/9041\r\n* Introduce dspy.Reasoning to capture native reasoning from reasoning models by @chenmoneygithub in https://github.com/stanfordnlp/dspy/pull/8986\r\n\r\n### Security & Serialization\r\n\r\n* Add guards against loading pkl files by @isaacbmiller in https://github.com/stanfordnlp/dspy/pull/9048\r\n* Add param to load_memory_cache to stop pkl files without explicit loading by @isaacbmiller in https://github.com/stanfordnlp/dspy/pull/9055\r\n\r\n### Bug Fixes & Type Handling\r\n\r\n* Fix TypeError when tracking usage with Anthropic models returning Pydantic objects by @Copilot in https://github.com/stanfordnlp/dspy/pull/8978\r\n* Update old Anthropic model names by @TomeHirata in https://github.com/stanfordnlp/dspy/pull/8992\r\n* fix(XMLAdapter): Implement user message formatting by @BenMcH in https://github.com/stanfordnlp/dspy/pull/9003\r\n* Fix content input conversion for OpenAI Responses API by @Copilot in https://github.com/stanfordnlp/dspy/pull/8993\r\n* Refactor: update type hints for adapter and LM methods by @TomeHirata in https://github.com/stanfordnlp/dspy/pull/9025\r\n* fix(dspy): exclude gpt-5-chat from reasoning model classification by @mindful-time in https://github.com/stanfordnlp/dspy/pull/9033\r\n* fix(dspy): Example.toDict() fails to serialize dspy.History objects by @Copilot in https://github.com/stanfordnlp/dspy/pull/9047\r\n* Some continuous format fix by @chenmoneygithub in https://github.com/stanfordnlp/dspy/pull/8987\r\n\r\n### Documentation & Tutorials\r\n\r\n* Add documentation for provider-side prompt caching with Anthropic and OpenAI by @Copilot in https://github.com/stanfordnlp/dspy/pull/8970\r\n* [docs] Add Google-style docstrings for dspy/evaluate/metrics.py by @eramis73 in https://github.com/stanfordnlp/dspy/pull/8954\r\n* fix: broken PyPI downloads badge from pepy.tech in README and docs home page by @dushmanta05 in https://github.com/stanfordnlp/dspy/pull/8995\r\n* Document ToolCall.execute() availability from dspy 3.0.4b2 by @Copilot in https://github.com/stanfordnlp/dspy/pull/9004\r\n* fix(docs): add python language id to code block by @Ahmad8864 in https://github.com/stanfordnlp/dspy/pull/9023\r\n* docs: add note on Python version for pre-commit by @akshatvishu in https://github.com/stanfordnlp/dspy/pull/9028\r\n* chore(docs): update dspy.settings.configure and dspy.settings.context to dspy.configure and dspy.context by @isaacbmiller in https://github.com/stanfordnlp/dspy/pull/9060\r\n* docs: add documentation for async tool usage and error handling by @TomeHirata in https://github.com/stanfordnlp/dspy/pull/9054\r\n\r\n### Minor Fixes, Maintenance & CI\r\n\r\n* Remove unused notebook python file by @TomeHirata in https://github.com/stanfordnlp/dspy/pull/8971\r\n* Cache Ollama to speed up CI by @TomeHirata in https://github.com/stanfordnlp/dspy/pull/8972\r\n* Clean out unused deps by @isaacbmiller in https://github.com/stanfordnlp/dspy/pull/8968\r\n* docs: add note on Python version for pre-commit by @akshatvishu in https://github.com/stanfordnlp/dspy/pull/9028\r\n* Bump DSPy version by @chenmoneygithub in https://github.com/stanfordnlp/dspy/pull/9061\r\n\r\n## New Contributors\r\n\r\n* @ZachParent made their first contribution in https://github.com/stanfordnlp/dspy/pull/8938\r\n* @eramis73 made their first contribution in https://github.com/stanfordnlp/dspy/pull/8954\r\n* @dushmanta05 made their first contribution in https://github.com/stanfordnlp/dspy/pull/8995\r\n* @akshatvishu made their first contribution in https://github.com/stanfordnlp/dspy/pull/9017\r\n* @mindful-time made their first contribution in https://github.com/stanfordnlp/dspy/pull/9033\r\n* @GabrielLoiseau made their first contribution in https://github.com/stanfordnlp/dspy/pull/8998\r\n* @Ahmad8864 made their first contribution in https://github.com/stanfordnlp/dspy/pull/9023\r\n\r\n**Full Changelog**: https://github.com/stanfordnlp/dspy/compare/3.0.4...3.1.0b1","mentions_count":13},{"url":"https://api.github.com/repos/stanfordnlp/dspy/releases/261187451","assets_url":"https://api.github.com/repos/stanfordnlp/dspy/releases/261187451/assets","upload_url":"https://uploads.github.com/repos/stanfordnlp/dspy/releases/261187451/assets{?name,label}","html_url":"https://github.com/stanfordnlp/dspy/releases/tag/3.0.4","id":261187451,"author":{"login":"chenmoneygithub","id":22925031,"node_id":"MDQ6VXNlcjIyOTI1MDMx","avatar_url":"https://avatars.githubusercontent.com/u/22925031?v=4","gravatar_id":"","url":"https://api.github.com/users/chenmoneygithub","html_url":"https://github.com/chenmoneygithub","followers_url":"https://api.github.com/users/chenmoneygithub/followers","following_url":"https://api.github.com/users/chenmoneygithub/following{/other_user}","gists_url":"https://api.github.com/users/chenmoneygithub/gists{/gist_id}","starred_url":"https://api.github.com/users/chenmoneygithub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chenmoneygithub/subscriptions","organizations_url":"https://api.github.com/users/chenmoneygithub/orgs","repos_url":"https://api.github.com/users/chenmoneygithub/repos","events_url":"https://api.github.com/users/chenmoneygithub/events{/privacy}","received_events_url":"https://api.github.com/users/chenmoneygithub/received_events","type":"User","user_view_type":"public","site_admin":false},"node_id":"RE_kwDOIv2ufM4PkWd7","tag_name":"3.0.4","target_commitish":"release-3.0.4b2","name":"3.0.4","draft":false,"immutable":false,"prerelease":false,"created_at":"2025-10-21T23:33:37Z","updated_at":"2025-11-10T17:41:17Z","published_at":"2025-11-10T17:41:17Z","assets":[],"tarball_url":"https://api.github.com/repos/stanfordnlp/dspy/tarball/3.0.4","zipball_url":"https://api.github.com/repos/stanfordnlp/dspy/zipball/3.0.4","body":"3.0.4b2 has been running for a while without seeing issue, so we are making it an official 3.0.4 release.\r\n\r\nThe release note is the combination of 3.0.4b1 and 3.0.4b2.\r\n\r\n\r\n## What's Changed\r\n\r\n### Optimizers\r\n\r\n- Fix GEPA usage tracking with tuple outputs by @smec-cgint in #8739\r\n- Add custom instruction_proposer support to GEPA with multimodal (dspy.Image) handling by @andressrg in #8737\r\n- Enhance logging for valset usage in GEPA by @LakshyAAAgrawal in #8770\r\n- [Feature] GEPA: Add custom component selection logic support by @andressrg in #8765\r\n- Add MLFLow <> GEPA support by @TomeHirata in #8763\r\n- Update optimization overview with data split guidance by @LakshyAAAgrawal in #8792\r\n- docs: Add comprehensive instruction_proposer documentation and examples for GEPA by @andressrg in #8775\r\n- Introduce gepa_kwargs for passing custom kwargs to gepa.optimize by @LakshyAAAgrawal in #8850\r\n- Propagate callback metadata during GEPA minibatch eval by @TomeHirata in #8835\r\n- Fix typo in GEPA warning by @TomeHirata in #8840\r\n- Update gepa[dspy] dependency version to 0.0.17; Potential fix for load from state not working in GEPA by @LakshyAAAgrawal in #8859\r\n- SIMBA Improvements by @klopsahlong in #8766\r\n\r\n### Features & Enhancements\r\n\r\n- Add Anthropic Citation API support by @TomeHirata in #8721\r\n- Add api reference for citations and document by @TomeHirata in #8801\r\n- Allow custom type to be streamed and use native response by @TomeHirata in #8778\r\n- Fix example code for Citations by @TomeHirata in #8868\r\n- Add `ToolCall.execute` for smoother tool execution (#8825, @TomeHirata)\r\n- Add DSPy User-Agent header (#8887, @TomeHirata)\r\n- Update headers when specified (#8893, @TomeHirata)\r\n- Arbor GRPO Sync Update (#8939, @Ziems)\r\n- Deprecate Image from_* helpers in favor of flexible constructor by @isaacbmiller in #8771\r\n- Cache Image.format for better throughput by @TomeHirata in #8842\r\n- test(dspy.Image): Adds a test with ReAct that has an Image tool by @isaacbmiller in #8855\r\n\r\n### Bug Fixes & Type Handling\r\n\r\n- Fix #8703 - fixing module and feedback mismatch by @Lucas-Fernandes-Martins in #8777\r\n- Fix value parsing and add tests by @chenmoneygithub in #8774\r\n- Parse doubly-encoded base type in json.parse by @TomeHirata in #8814\r\n- Fix unexpected parsing of Optional[str] fields when string has brackets or braces by @sontanon in #8805\r\n- Use mcp.ClientSession for type hint by @TomeHirata in #8826\r\n- Fix type hint for callpreprocess by @TomeHirata in #8827\r\n- fix: Allow DummyLM answers dict values to be of any type to work with a wider range of signatures by @BenMcH in #8803\r\n- Fix the crash when usage tracker is enabled with non-prediction output by @TomeHirata in #8831\r\n- Fallback to memory cache when disk is not available by @TomeHirata in #8718\r\n- bug(lm): Avoid unnecessary cache key computation by @isaacbmiller in #8862\r\n- Display metric=0 in eval table by @TomeHirata in #8817\r\n- Add save/load to Embeddings by @TomeHirata in #8818\r\n- Fix chunk loss in long streaming with native response field (#8881, @TomeHirata)\r\n- Make the buffer condition more precise (#8907, @TomeHirata)\r\n- fix: add fallback on missing end marker during streaming (#8890, @enitrat)\r\n- fix(JSONAdapter): escape logic when JSON mode but no structured outputs (#8871, @isaacbmiller)\r\n- fix: XML adapter markers (#8876, @enitrat)\r\n- Fix `test_xml_adapter_full_prompt` (#8904, @TomeHirata)\r\n- Fix responses API (#8880, @chenmoneygithub)\r\n- Fix response_format handling for responses API (#8911, @TomeHirata)\r\n- Fix error handling in dspy parallel (#8860, @TomeHirata)\r\n- fix(LM): default `temperature` and `max_tokens` to `None` (#8908, @isaacbmiller)\r\n- fix(MIPROv2): select between `task_model` and `prompt_model` (#8877, @isaacbmiller)\r\n- Exclude API keys from saved programs (#8941, @Copilot)\r\n\r\n### Documentation & Tutorials\r\n\r\n- Minor document changes by @Navanit-git in #8722\r\n- Add doc page to learn tool usage in DSPy by @TomeHirata in #8709\r\n- Style fix for tool page by @TomeHirata in #8781\r\n- Add tracing banner in new tutorials by @B-Step62 in #8772\r\n- docs: fix link to the sglang installation/getting started page by @tomsanbear in #8776\r\n- Guide on using native tool calling by @chenmoneygithub in #8788\r\n- fix: removed duplicate cell from GEPA information extraction tutorial by @vacmar01 in #8806\r\n- Remove EmailInsight class from email extraction tutorial by @TomeHirata in #8790\r\n- Update documentation to include responses api by @chenmoneygithub in #8780\r\n- [Feature] Add automatic llms.txt generation via mkdocs-llmstxt plugin by @aberoham in #8562\r\n- Guide on using native tool calling by @chenmoneygithub in #8788\r\n- Update HotPotQA in light of #8591 by @okhat in #8751\r\n- Add Learn MCP page (#8903, @TomeHirata)\r\n- Fix MIPRO paper link in RAG tutorial (#8937, @TomeHirata)\r\n- [Docstring] Add docstring for Adapter (#8915, @chenmoneygithub)\r\n- [Docs] Google-style docstrings for `dspy/primitives/example` Example class (#8949, @Davshiv20)\r\n- [Docs] Google-style docstrings for `Signature.prepend/append/insert/delete` (#8945, @gnetsanet)\r\n- Better tutorial sidebar—do not auto-expand all tutorials (#8912, @chenmoneygithub)\r\n\r\n### Minor Fixes & Maintenance\r\n\r\n- Use developer role in response API by @TomeHirata in #8727\r\n- 8688 csv output by @crawftv in #8725\r\n- Add header link by @TomeHirata in #8773\r\n- Add experimental annotation by @TomeHirata in #8712\r\n- Update LICENSE error by @TomeHirata in #8783\r\n- Fixed Spelling error in DatasetDescriptor Prompt by @PoeAudits in #8812\r\n- Update API reference by @TomeHirata in #8844\r\n- Expose EvaluationResult as dspy.evaluate.EvaluationResult by @TomeHirata in #8843\r\n- Include built-in types in DSPy api references by @chenmoneygithub in #8810\r\n- Change DummyLM to take an adapter at init by @isaacbmiller in #8802\r\n- Infinitus AI agents by @suman-subash-infinitusai in #8708\r\n- [WIP] Arbor Interface Update by @Ziems in #8837\r\n- Refactor URL construction in `ArborReinforceJob` to use `urljoin` (#8951, @Ziems)\r\n- Update type hint of `ClientSession` (#8894, @TomeHirata)\r\n- Long line in function signature (style) (#8914, @chenmoneygithub)\r\n- Fix lint of LM (#8884, @chenmoneygithub)\r\n- Deflake the real LM test (#8924, @chenmoneygithub)\r\n\r\n## New Contributors\r\n* @crawftv made their first contribution in https://github.com/stanfordnlp/dspy/pull/8725\r\n* @Navanit-git made their first contribution in https://github.com/stanfordnlp/dspy/pull/8722\r\n* @smec-cgint made their first contribution in https://github.com/stanfordnlp/dspy/pull/8739\r\n* @suman-subash-infinitusai made their first contribution in https://github.com/stanfordnlp/dspy/pull/8708\r\n* @andressrg made their first contribution in https://github.com/stanfordnlp/dspy/pull/8737\r\n* @tomsanbear made their first contribution in https://github.com/stanfordnlp/dspy/pull/8776\r\n* @Lucas-Fernandes-Martins made their first contribution in https://github.com/stanfordnlp/dspy/pull/8777\r\n* @aberoham made their first contribution in https://github.com/stanfordnlp/dspy/pull/8562\r\n* @PoeAudits made their first contribution in https://github.com/stanfordnlp/dspy/pull/8812\r\n* @sontanon made their first contribution in https://github.com/stanfordnlp/dspy/pull/8805\r\n* @enitrat made their first contribution in https://github.com/stanfordnlp/dspy/pull/8890\r\n* @Davshiv20 made their first contribution in https://github.com/stanfordnlp/dspy/pull/8949\r\n* @gnetsanet made their first contribution in https://github.com/stanfordnlp/dspy/pull/8945\r\n\r\n**Full Changelog**: https://github.com/stanfordnlp/dspy/compare/3.0.3...3.0.4","reactions":{"url":"https://api.github.com/repos/stanfordnlp/dspy/releases/261187451/reactions","total_count":6,"+1":0,"-1":0,"laugh":0,"hooray":0,"confused":0,"heart":0,"rocket":6,"eyes":0},"mentions_count":23}]