Keep approval-required and external tools native under `CodeMode(tools='all')`

MP
20d ago
+238-52

CodeMode() previously folded statically deferred tools into run_code, where they could not complete without an inline handler. This implements option 1 from #9364: keep approval-required and external tools native under tools='all'. Handler detection is not used because handlers can resolve only selected calls, as ExaAgent does. Douwe's sign-off on option 1 and a Harness minor release is still required before merge.

[!WARNING]
Compatibility impact: Agents using default CodeMode() with a HandleDeferredToolCalls handler previously could call requires_approval=True and external tools from snippets. Those tools now remain native; the handler still resolves their direct calls.

Why this can ship in a minor release: This changes Harness behavior, not Pydantic AI core. The Harness 0.x version policy permits changed defaults between minor releases, with migration guidance. This is not a claim that the formerly documented inline-handler behavior qualifies for core's undocumented-behavior bug-fix exception.

Migration: To preserve sandbox placement, use an explicit selector, for example CodeMode(tools=lambda ctx, td: True), with the inline handler.

New public surface: None.

User-visible behavior:

Example configurationBeforeAfter
Default CodeMode() with a requires_approval=True or external toolTool is callable through run_code and needs an inline handlerTool is called directly, preserving DeferredToolRequests and inline-handler resolution
  • Explicit name, callable, and metadata selectors can still sandbox these tools.
  • Tool Search discovery follows that same partition. Search descriptions and discovery announcements direct the model to use run_code only for catalog entries and call separately exposed tools directly.
  • Tools raising ApprovalRequired or CallDeferred from their bodies, including through ApprovalRequiredToolset, remain sandboxed as before and still need an inline handler.

Verification:

What changes for existing users: Statically deferred tools become native under default CodeMode(); users without those tools or with explicit selectors retain their tool placement.

No public signatures changed, so no deterministic API-check waiver was needed.

Checklist

  • No breaking changes in accordance with the version policy.
  • Any permitted compatibility impact has a label, warning, migration, release note, and exact API-check waiver.
  • PR title is fit for the release changelog.