Skip to content

fix(http-executor): inputs_schema fallback, http.body alias, safe redirects, HTML/non-JSON guard - #9

Draft
man4ish wants to merge 7 commits into
mainfrom
fix/http-executor-schema-fallback
Draft

man4ish wants to merge 7 commits into
mainfrom
fix/http-executor-schema-fallback

Conversation

@man4ish

@man4ish man4ish commented Nov 1, 2026 •

Copy link
Copy Markdown
Collaborator

Why

A static and live audit of all 1,716 HTTP tools that TES registers here found that most fail inside this executor before the upstream API sees a valid request:

  • 1,004 tools declare inputs only in inputs_schema, with no inputs list. Their {placeholders} were never substituted, so the URL went out literally, e.g. /vep/human/region/%7Bregion%7D/%7Ballele%7D. Their required fields were never validated either.
  • 24 tools put their POST body under http.body. Only http.body_map was read, so they POSTed an empty body.
  • 40 tools get a 3xx from upstream. httpx doesn't follow redirects by default, so every such run failed.

What

  1. _input_fields() falls back to inputs_schema.properties for any name the inputs list doesn't declare. Where both exist, the inputs entry wins. Schema secret: true is honoured for log masking.

  2. http.body is accepted as an alias for http.body_map. Nested JSON values, such as GraphQL variables, keep their structure instead of being sent as a Python repr.

  3. Header values are templated, so API keys can go in a header rather than the query string.

  4. Redirects:

    • Followed only when they stay on the same host or are an http→https upgrade.
    • Never downgraded to http; at most 5 hops.
    • When an allowed redirect changes host, credential headers (Authorization, Cookie, *api-key*, *token*, …) and secret-valued query params are stripped first.
    • Refused redirects fail the run with a message that names hosts only.
  5. Response-kind guard on every response, not only redirects. Many upstreams return 200 with a landing page, login wall or error page, and the run used to finish COMPLETED with {"text": "<html>…"}. Now:

    • JSON tool (Accept mentions json, or a response_map that reads anything other than the {"text": …} wrapper): the body must parse as JSON. The body is parsed rather than trusting the content type, so mislabelled JSON still passes.
    • Text tool (response_map reads only text, e.g. KEGG, efetch, Cactus): the body must not be HTML. Without this exception, 16 working text tools would have broken.
    • No expectation: unchanged.

    From the live probe: this fails 19 redirect-to-HTML runs, plus 11 tools that previously "succeeded" with HTML or XML (DisGeNET, UniChem, DepMap, Orphanet, …).

Tests

428 passed (26 new: schema fallback, body alias and nesting, header templating and masking, 8 redirect-policy cases, 9 response-kind cases). The ruff error count is unchanged from main (25, all pre-existing).

Merge order

Merge and deploy this before the TES PR (OmniBioAI/omnibioai-tes, branch fix/http-tool-definitions). TES's new CI gate assumes this executor behaviour.

🤖 Generated with Claude Code

Manish Kumar and others added 3 commits November 1, 2026 17:20
….body

Most YAML HTTP tools declare only inputs_schema (no `inputs` list), so
their {placeholders} were never substituted (sent literally, e.g.
/region/%7Bregion%7D) and their required fields were never validated.
_input_fields() now falls back to inputs_schema.properties for any name
the `inputs` list doesn't declare (the list still wins on conflicts),
including `secret: true` for log masking.

Also:
- accept `http.body` as an alias for `http.body_map` (24 tools sent an
  empty body); nested JSON values keep their structure instead of being
  sent as a Python repr
- resolve {placeholders} in headers, so API keys can travel in a header
  instead of the query string

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ax 5)

httpx does not follow redirects by default, so every upstream that
answers with a 3xx (40 tools in the live probe) failed the run.

Redirects are now followed only when they stay on the same host or
upgrade http->https, never downgrade to http, and at most 5 hops. When an
allowed redirect changes host, credential headers (Authorization,
Cookie, *api-key*, *token*, ...) and secret-valued query params are
stripped first. Disallowed redirects fail the run with a message that
names hosts only, so secrets in URLs never reach run logs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s expected

Many upstreams answer 200 with a landing page, login wall or error page;
the run then COMPLETED with {"text": "<html>..."}. Following redirects
made this more common (19 of 40 redirecting tools end on HTML).

Every response is now checked after raise_for_status():
- JSON tool (Accept mentions json, or a response_map reading anything
  other than the {"text": ...} wrapper): the body must parse as JSON
- text tool (response_map reads only `text`, e.g. KEGG/efetch): the
  body must not be HTML
- no expectation: unchanged

Failure messages name the content type and host only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@man4ish man4ish changed the title fix(http-executor): resolve inputs from inputs_schema, accept http.body, follow safe redirects fix(http-executor): inputs_schema fallback, http.body alias, safe redirects, HTML/non-JSON guard Nov 1, 2026
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