Skip to content

feat(tools/web): attach actionable hints to web_search / web_fetch er…#671

Closed
MyPrototypeWhat wants to merge 1 commit into
esengine:mainfrom
MyPrototypeWhat:web-tool-error-hints
Closed

feat(tools/web): attach actionable hints to web_search / web_fetch er…#671
MyPrototypeWhat wants to merge 1 commit into
esengine:mainfrom
MyPrototypeWhat:web-tool-error-hints

Conversation

@MyPrototypeWhat

Copy link
Copy Markdown

Closes #16.

Tool errors round-trip to the model verbatim, so a bare 'web_search 429' prompts the model to retry the same call with the same args. Pick a status-specific i18n key with a hint clause for the four cases the model most commonly hits:

  • 429 — wait 10s, or rephrase the query
  • 403 — confirm public access / network reachability / User-Agent
  • 5xx — try a browser; if it loads, retry in 30s
  • other — confirm reachability and parseability (existing message, reused as the default)

Also surface the AbortController timeout as 'web_fetch timed out after {ms}ms' with a 'use a lighter URL' hint, instead of letting the raw AbortError bubble up. Caller-driven aborts still propagate as-is.

Both EN and zh-CN translations updated; the existing /web_search 429/ regex assertion is preserved as a prefix.

What

Pick a status-code-specific i18n key with an actionable hint when web_search or web_fetch hits a non-2xx response, instead of returning the bare status. Four buckets: 429, 403, 5xx, and a generic catch-all that's still actionable. Also surface AbortController timeouts in web_fetch as "web_fetch timed out after {ms}ms" instead of letting the raw AbortError bubble up; caller-driven aborts (Esc) still propagate unchanged. EN + zh-CN translations and TranslationSchema updated in step. Closes #16.

Why

Tool errors go back to the model verbatim — they're how the agent decides what to do next. A bare web_search 429 reads as a transient failure, so the model retries with identical args and burns tokens. web_search 429 — try: wait 10s before retrying, or rephrase the query tells the model both that a same-args retry won't help and what to do instead. Same shape for 403 (check public access / UA), 5xx (open in a browser, retry in 30s), timeout (lighter URL).

How to verify

npm run verify
npx vitest run tests/web-tools.test.ts

The new actionable error hints describe block adds four cases: search 429, search 503, fetch 403, fetch timeout — each asserts on the hint substring, not just the status. Existing assertions on /web_search 429/ and /web_fetch 404/ still match (the new messages start with the same prefix).

Checklist

  • npm run verify passes locally (lint + typecheck + tests + comment-policy gate)
  • No Co-Authored-By: Claude trailer in commits
  • Comments follow CONTRIBUTING.md (no module-essay headers, no incident history)
  • No edits to CHANGELOG.md — release notes are maintainer-written at release time

…rors

Closes esengine#16.

Tool errors round-trip to the model verbatim, so a bare 'web_search 429'
prompts the model to retry the same call with the same args. Pick a
status-specific i18n key with a hint clause for the four cases the model
most commonly hits:

- 429 — wait 10s, or rephrase the query
- 403 — confirm public access / network reachability / User-Agent
- 5xx — try a browser; if it loads, retry in 30s
- other — confirm reachability and parseability (existing message,
  reused as the default)

Also surface the AbortController timeout as 'web_fetch timed out after
{ms}ms' with a 'use a lighter URL' hint, instead of letting the raw
AbortError bubble up. Caller-driven aborts still propagate as-is.

Both EN and zh-CN translations updated; the existing /web_search 429/
regex assertion is preserved as a prefix.
@esengine

Copy link
Copy Markdown
Owner

Hey, thanks for putting this together — the four-bucket strategy, the helper-function shape, and the timeout-vs-abort distinction are all the right calls.

Unfortunately #632 landed first and overlaps heavily with this PR — rateLimit429 / forbidden403 / fetchRateLimit429 / fetchForbidden403 / fetchTimeout are already on main, all closing the same #16, with the same general approach. Re-landing those under the searchStatusNNN naming would only churn the schema with no behavioral gain, so I'm going to close this one as superseded.

But the 5xx bucket is a real gap — #632 stopped at 429/403, and surfacing transient 5xx with a "try again in 30s / check in a browser" hint is genuinely valuable. I'll open a small follow-up that adds just serverError5xx + fetchServerError5xx (sticking to #632's naming convention since that's what's on main), with credit to you in the PR body. Your 503 test case will land alongside.

Sorry for the timing — both PRs were in flight on the same evening and #632 happened to hit main first. The contribution isn't wasted; the part that was new sticks.

@esengine esengine closed this May 11, 2026
@MyPrototypeWhat MyPrototypeWhat deleted the web-tool-error-hints branch May 11, 2026 12:08
esengine added a commit that referenced this pull request May 11, 2026
)

#632 actionable-error work stopped at 429 + 403 — generic 5xx still
fell through to the catch-all "rephrase the query / switch engine"
message, which is the wrong advice for a transient server-side
failure. Add serverError5xx + fetchServerError5xx pointing the model
at a browser sanity-check and a 30s retry instead.

Existing webSearch 503 test tightened from `/web_search 503.*try:/`
to assert on the new `retry in 30s` substring; a parallel webFetch
502 test added in the same shape.

Credit to @MyPrototypeWhat#671 surfaced the gap and the 503 test
case lands with this PR.
ChasLui pushed a commit to ChasLui/DeepSeek-Reasonix that referenced this pull request May 23, 2026
…sengine#676)

esengine#632 actionable-error work stopped at 429 + 403 — generic 5xx still
fell through to the catch-all "rephrase the query / switch engine"
message, which is the wrong advice for a transient server-side
failure. Add serverError5xx + fetchServerError5xx pointing the model
at a browser sanity-check and a 30s retry instead.

Existing webSearch 503 test tightened from `/web_search 503.*try:/`
to assert on the new `retry in 30s` substring; a parallel webFetch
502 test added in the same shape.

Credit to @MyPrototypeWhatesengine#671 surfaced the gap and the 503 test
case lands with this PR.
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.

Make web_search / web_fetch errors actionable

2 participants