Skip to content

superforcaster-polymarket-v4: free-text prompts (the advertised contract) silently disable retrieval, yielding prior-only forecasts #455

Description

@bennyjo

Summary

superforcaster-polymarket-v4 (and its ancestors) advertises a free-text input contract but silently depends on the valory trader's internal prompt template. Any other agent that calls the tool through the Mech Marketplace - the intended audience includes any agent paying for a prediction via Pearl Connect, not only traders - gets a degraded prior-only forecast: the web-retrieval step returns zero results and the LLM answers from its pretraining priors.

Observed in production: a mech request for a market trading at 0.875 returned p_yes = 0.60 with organic: [] in the captured Serper response. The requesting agent had stated the resolution question precisely (criteria, resolution source, deadline), exactly as the advertised contract suggests.

Root cause

  1. The advertised contract says free text. The published tool metadata (scripts/tool_schemas.yaml, prediction kind) describes the input in its entirety as:

    input:
      type: text
      description: The text to make a prediction on

    Nothing tells a requester that a specific prompt format is expected.

  2. The tool assumes an undocumented template. extract_question in packages/valory/customs/superforcaster_polymarket_v4/superforcaster_polymarket_v4.py extracts the question with the regex question\s+"(.+?)"\s+and\s+the\s+yes``, which matches only the valory trader's internal prompt template. On a mismatch it falls back to using the entire prompt as the Serper search query.

  3. Prompt-shaped queries degrade retrieval, in the worst case to zero organic results. Verified empirically against the live Serper API (2026-08-28), running the tool's own extract_question where applicable:

    Query shape Regex matched Query sent Status organic results
    Real trader-template prompt (317 chars) yes bare 59-char question 200 10
    Detailed free-text resolution question (347 chars: criteria + source + deadline) no full prompt 200 6
    Prompt with instruction boilerplate and JSON-format text (580 chars) no full prompt 200 0
    Question wrapped in exact-match quotes n/a quoted phrase 200 0

    The trader path is healthy because extraction succeeds. For non-template prompts, degradation depends on content: a pure natural-language question usually still retrieves (fewer results); instruction boilerplate, backticks/JSON-format text, or exact-match quoting can drive results to zero. The production organic: [] case likely involved such content in the prompt; the captured searchParameters.q in the mech response is the definitive evidence for any specific incident.

  4. Empty retrieval passes silently. The tool guards the HTTP-error path (raise_for_status()), but a 200 with organic: [] flows straight through: format_sources_data returns an empty string, the LLM receives an empty <background></background> block, and it forecasts from priors. The failure is invisible on-chain except as a poorly calibrated number.

Net effect: only the one caller whose internal template the tool happens to parse gets the intended retrieval path. Every other requester's prompt is passed raw to Serper - retrieval quality then depends on incidental prompt content, ranging from mildly degraded to silently empty, and the tool neither detects nor reports the empty case.

Why this matters

Mech Marketplace tools are meant to be callable by any agent willing to pay for a good prediction, not only the valory trader. That requires two things, and this tool currently provides neither:

  • The published metadata must give a requester clear, sufficient instructions to call the tool successfully.
  • The tool must honor those instructions - a prompt that satisfies the advertised contract must take the full-quality path, including retrieval.

Suggested fix direction

Tool-side, as a new variant (superforcaster-polymarket-v5) per the housekeeping rules, since any of this shifts the output distribution:

  1. Honor the advertised free-text contract: when the trader-template regex does not match, treat the whole prompt as the question for the LLM but derive a proper search query from it (extract/compress the leading question, rather than passing the full prompt to Serper).
  2. Add an explicit empty-retrieval guard: on organic: [], either retry with a simplified query, or force low confidence/info_utility (or return the null prediction) so the requester can detect and discount the answer.

Secondary, independent of the variant: make the published input description in scripts/tool_schemas.yaml state what a good prompt looks like (a single self-contained resolution question with criteria, source, and deadline), so requesters have explicit instructions to adhere to.

References

  • Tool source: packages/valory/customs/superforcaster_polymarket_v4/superforcaster_polymarket_v4.py (extract_question, fetch_additional_sources, format_sources_data)
  • Published metadata: scripts/tool_schemas.yaml (defaults.prediction.input), scripts/generate_metadata.py
  • Related precedent: fix(customs): align component.yaml descriptions with published manifests #284 (tool description vs. trader is_prediction_tool predicate - same class of implicit-contract problem, on the discovery side rather than the input side)

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    tool-improvementTool-quality regression flagged by daily benchmark; routes to tool-improvement-agent

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions