Skip to content

Web pipeline: retrieval rides with discovery; hallucinated fetch calls get steered - #2625

Merged
jjang-ai merged 2 commits into
mainfrom
feat/search-comfort
Sep 4, 2026
Merged

Web pipeline: retrieval rides with discovery; hallucinated fetch calls get steered#2625
jjang-ai merged 2 commits into
mainfrom
feat/search-comfort

Conversation

@jjang-ai

@jjang-ai jjang-ai commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Why

A model with web search enabled saw only web_search (discovery) in its schema; retrieval (search_and_extract) sat behind a capabilities_load round-trip. Observed live: models loop-rephrased web_search or hallucinated web_fetch — a tool that has never existed in osaurus — and produced zero page reads (the Raptor research-run failure).

What

  1. search_and_extract is composed into the schema whenever web search is enabled (was: Charts+Web combo or orchestrator only). The web-off strip still removes both halves; manual mode untouched. Cost: ~350–420 tokens on web-enabled prompts — the same spec the Charts+Web path already paid.
  2. web_search's description names the direct transition ("search_and_extract IS the fetch tool") and drops the capabilities_load detour — on the Default agent that loader is gated to configure writes, so the old text steered into a rejected load. Same fix in the web_search anti-loop nudge.
  3. Hallucinated fetch names get steered, not dead-ended: web_fetch/fetch_url/read_webpage/… return a retryable envelope pointing at search_and_extract — only when the name has no real registration (a plugin/MCP tool claiming it always wins), the request's scope already exposes search_and_extract (nothing withheld is leaked; nil-scope HTTP/MCP surfaces keep the generic refusal), and no plugin group shares the name (group-load rescue keeps precedence). Browser-intent (browse, open_url) and shell-intent (curl) names are deliberately excluded.

Verification

  • Adversarial audit of the diff (leak/shadowing/precedence/envelope-keys): steering can never name a tool outside the request's own scope; toolsByName guard keeps real registrations winning; group rescue precedence guarded; envelope keys verified against ToolEnvelope.failure.
  • Tests: composer exposure both ways (web on → both halves; web off → neither), steering + opacity contracts in ToolScopeGateRecoveryTests, superseded lean-baseline pin updated, description contract test updated.
  • Release build clean.

Eric added 2 commits September 3, 2026 19:49
…s get steered

A model with web search enabled used to see only web_search (discovery) in
its schema; retrieval (search_and_extract) sat behind a capabilities_load
round-trip. Observed live: models loop-rephrased web_search or hallucinated
web_fetch — a tool that has never existed here — and produced zero page
reads.

- search_and_extract is now composed into the schema whenever web search is
  enabled (was: Charts+Web combo or orchestrator only). The web-off strip
  still removes both halves.
- web_search's description names the direct transition and says plainly
  that search_and_extract IS the fetch tool; the capabilities_load detour
  is gone (on the Default agent that loader is gated to configure writes,
  so following the old text produced a rejected load). Same fix in the
  web_search anti-loop nudge.
- Calls to fetch-tool names imported from other harnesses (web_fetch,
  fetch_url, read_webpage, ...) return a retryable envelope steering to
  search_and_extract — only when the name has no real registration (a
  plugin/MCP tool claiming it always wins), the request's scope already
  exposes search_and_extract (nothing withheld is leaked; HTTP/MCP
  surfaces with nil scope keep the generic refusal), and no plugin group
  shares the name (the group-load rescue keeps precedence). Browser-intent
  (browse, open_url) and shell-intent (curl) names are deliberately not
  steered.
- Tests: composer exposure both ways, steering + opacity contracts, and
  the superseded lean-baseline pin updated.
@jjang-ai
jjang-ai merged commit 9d7d071 into main Sep 4, 2026
8 checks passed
@jjang-ai
jjang-ai deleted the feat/search-comfort branch September 4, 2026 05:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant