Skip to content

fix(dspy): reject duplicate tool names in FlexContext.context_names - #96

Open
detail-app[bot] wants to merge 1 commit into
mainfrom
detail/bug-fix/fix-dspy-reject-duplicate-tool-names-in-flexcontex-bc29ea
Open

fix(dspy): reject duplicate tool names in FlexContext.context_names#96
detail-app[bot] wants to merge 1 commit into
mainfrom
detail/bug-fix/fix-dspy-reject-duplicate-tool-names-in-flexcontex-bc29ea

Conversation

@detail-app

@detail-app detail-app Bot commented Sep 6, 2026

Copy link
Copy Markdown

Warning

GitHub issue creation failed

Detail attempted to publish this bug to GitHub, but the issue could not be created. This fix PR was created without that issue, and missing tracker references are shown as Unknown issue.

You can review and merge this PR normally. Please review your tracker integration settings before the next publish run.

Detail bug report: View on Detail

📝 Changes Description

This MR/PR contains the following changes:

  • Bug: dspy.Flex(..., tools=[...]) silently overwrote duplicate tool names (last-wins) instead of rejecting them. FlexContext.context_names (dspy/predict/flex/ctx.py) built the sandbox globals dict with a plain out[name] = tool assignment and no uniqueness check, so two dspy.Tool instances sharing a name (e.g. two Tool(f, name="lookup"), or two functions sharing __name__) caused the earlier tool to be silently dropped — both from the sandbox namespace and from the dspy.RLM(...) baseline emitted into module_src — with no error. The same input is already rejected by dspy.RLM._normalize_tools with ValueError("Duplicate tool name '...'"), so Flex's baseline contract and RLM's diverged silently.

  • Fix: Added a duplicate-name check in FlexContext.context_names, the single chokepoint used both during baseline-source emission (Flex._baseline_src) and runtime tool registration (BridgeRuntime._tool_callables/_resolve_tool). Since _baseline_src calls context_names() during Flex.__init__, the ValueError now fires at construction time — before any interpreter is created or forward runs. The message matches RLM's exactly: Duplicate tool name '<name>'. This mirrors the existing guard in dspy/predict/rlm.py:214-216.

  • Tests: Added two regression tests in tests/flex/test_tools.py: test_duplicate_tool_names_rejected (mirrors test_rlm.py::test_duplicate_tool_names_rejected at the Flex constructor) and test_unique_tool_names_are_accepted (guards against over-rejection of valid multi-tool input).

Closes Unknown issue

✅ Contributor Checklist

  • Pre-Commit checks are passing (locally and remotely)
  • Title of your PR / MR corresponds to the required format
  • Commit message follows required format {label}(dspy): {message}

⚠️ Warnings

  • Authored by Detail: Automatic Fixes.
  • dspy.Flex is an @experimental module; this hardens its constructor validation to match dspy.RLM's existing contract. The change is additive (a new raise) and affects only the duplicate-name path; existing single-tool and multi-unique-tool usage is unchanged.

Testing summary

  • Unit/lint/format/build all pass: uv run ruff check --fix and uv run ruff format leave both files unchanged; uv build succeeds and import dspy works.
  • tests/flex/test_tools.py passes (9 passed, 8 @deno_required skipped without Deno; 17 passed with Deno installed via uv sync --extra deno).
  • Full tests/flex/ suite passes (75 passed / 39 skipped without Deno; 114 passed with Deno).
  • RLM regression suite (tests/predict/test_rlm.py -k "tool or duplicate or reserved") passes (21 without --deno; 28 with --deno), confirming no cross-module regression.
  • Verified end-to-end through the real Deno-backed BridgeRuntime.forward path: the duplicate input raises at construction (before any forward), and the positive single-tool path dispatches correctly ("abc""ABC").

Automatic Fixes PRs can be configured here.

@greptile-apps

greptile-apps Bot commented Sep 6, 2026

Copy link
Copy Markdown

Greptile Summary

Adds fail-fast validation for duplicate Flex tool names, aligning Flex with RLM behavior.

  • Rejects duplicate effective tool names before the context map can silently overwrite an earlier tool.
  • Adds regression coverage for duplicate rejection and acceptance of uniquely named tools.

Confidence Score: 5/5

The PR appears safe to merge; the validation is applied at the shared tool-context chokepoint and is covered by focused regression tests.

No actionable correctness, security, or repository-rule issues remain; duplicate names now fail before overwrite while unique names continue through baseline generation.

Important Files Changed

Filename Overview
dspy/predict/flex/ctx.py Adds a correctly placed duplicate-name guard before tool registration.
tests/flex/test_tools.py Covers duplicate-name rejection at construction and preserves valid multi-tool behavior.

Reviews (1): Last reviewed commit: "fix(dspy): reject duplicate tool names i..." | Re-trigger Greptile

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant