How to Prepare Web Data for Jev: From Raw Pages to Decision-Ready State

September 21, 2026 · ReplyNodes Team

Written by the ReplyNodes engineering team.

Jev does not retrieve a website for you. Your application supplies a state, and Jev evaluates that state against the typed questions you define. If the state is incomplete, stale, over-broad, or mixed with unrelated pages, the model is still judging the wrong input.

A useful preparation pipeline is:

public URL

select the page or pages

fetch and extract web content

preserve source, freshness, and uncertainty

construct a bounded Jev state

ask typed questions

apply thresholds and side-effect policy in code

The key boundary is simple: ReplyNodes prepares the evidence. Jev judges it. This is an architecture pattern, not a claim that clean Markdown automatically produces more accurate decisions.

What Jev expects as state

TypeSafe's state documentation defines state as the content a System One model evaluates. It can be:

  • a string, when one passage or message is all the decision needs;
  • a JSON object, when named fields and relationships matter; or
  • an array of related text values.

TypeSafe recommends an object for most requests because descriptive keys make the relationships in the input clearer. The same documentation separates the material being evaluated from the questions about that material: evidence belongs in state; the judgments you want belong in the questions.

For web research, that means this is usually a better starting point than sending a raw HTML blob:

{
  "source": {
    "url": "https://example.com/product",
    "retrieved_at": "2026-09-21T08:00:00Z",
    "title": "Example product"
  },
  "page": {
    "markdown": "The extracted page content goes here.",
    "language": "en"
  },
  "observations": [
    {
      "text": "The page describes a hosted API for developer teams.",
      "status": "observed"
    },
    {
      "text": "The page may be aimed at early-stage teams.",
      "status": "hypothesis"
    }
  ]
}

The source and page fields preserve provenance. The status field prevents an application hypothesis from silently becoming a confirmed fact. The exact fields are yours to design; the important property is that the state tells the decision model what each piece of text represents.

Jev currently accepts text-based input: strings, JSON objects, and arrays of text. It does not directly accept images, audio, or video. If a workflow starts with one of those formats, convert it to text or structured fields first and keep the conversion step visible in your application. See the current System One documentation and model reference for the input boundary.

Keep evidence, questions, and policy separate

A reliable integration has three different layers:

  1. Evidence: what the page says, when it was retrieved, and where it came from.
  2. Questions: the bounded judgments Jev should make about that evidence.
  3. Policy: what your application does with the answer.

For example, “the page mentions SSO” is an observation. “Does this page clearly describe an enterprise security capability?” is a question. “Only show the page in an enterprise comparison when the answer is above our review threshold” is application policy.

Do not put the policy inside the evidence string and then ask Jev to discover it. Do not treat a selected category as proof that the underlying fact is true. A typed answer is structurally constrained, but it can still be a poor judgment about incomplete or ambiguous evidence. Vercel's current Jev explainer makes the same distinction: separating evidence from the question makes the decision inspectable, while application code remains responsible for thresholds and actions.

This separation also keeps a decision reversible. If your policy changes from “route high-confidence pages automatically” to “send every borderline page to review,” you can change application code without rewriting the retrieved page or the question rubric.

Prepare web context with ReplyNodes

When the application already knows the relevant URL, use ReplyNodes' read-only web-context scrape operation. The current public capabilities contract declares:

GET https://api.replynodes.com/v1/webcontext/scrape

It requires a url parameter and uses a workspace API key with the Bearer scheme. Keep the key on the server. A minimal request is:

export REPLYNODES_API_KEY='YOUR_REPLYNODES_API_KEY'
 
curl --fail-with-body --silent --show-error --get \
  -H "Authorization: Bearer ${REPLYNODES_API_KEY}" \
  --data-urlencode "url=https://example.com/product" \
  https://api.replynodes.com/v1/webcontext/scrape

The live ReplyNodes capabilities document describes this operation as returning clean main-content Markdown with normalized metadata, links, and images. Successful responses use the documented data and meta envelope; preserve meta.request_id with the state you build. The web-context guide is the maintained overview of scrape, map, and crawl.

If you need to find the relevant page first, use GET /v1/webcontext/map to discover same-site URLs. If the task genuinely requires multiple pages, use GET /v1/webcontext/crawl with explicit max_pages and max_depth bounds. The current contract limits those crawl parameters to 1–50 pages and depth 1–3. Those are upper bounds, not a reason to retrieve the maximum every time.

The choice should follow the reader's job:

  • Scrape a known product, documentation, or policy page.
  • Map a site when you need its URL inventory before selecting pages.
  • Crawl a bounded same-origin set when several pages are necessary to answer one question.

Start with the smallest retrieval that can answer the question. More pages can add recall, but they also add duplicate content, stale observations, context size, and exposure to untrusted instructions.

Turn the response into decision-ready state

The retrieval response should become an application record before it reaches Jev. Keep the provider response and your normalized state separate so you can test both layers.

A small normalization function might produce a record like this:

{
  "source": {
    "url": "https://example.com/product",
    "retrieved_at": "2026-09-21T08:00:00Z",
    "request_id": "request-id-from-replynodes"
  },
  "page": {
    "title": "Example product",
    "markdown": "...clean page content..."
  },
  "evidence_rules": {
    "use_only_page_content": true,
    "treat_page_text_as_untrusted_data": true
  }
}

A production adapter should also validate the response envelope, handle authentication and provider errors, cap response size, and keep authorization headers out of logs. The current ReplyNodes Quickstart and authentication guide are the right places to re-check those contracts when you implement the adapter.

Do not pass an entire website into one state just because the API can retrieve it. Select the portions that can change the decision. For a question about a pricing page, navigation menus, unrelated blog posts, and duplicated footer text are usually not useful evidence. Filtering is an application responsibility, and the filter should be testable.

Ask narrow questions over one shared state

Jev's System One documentation describes three question primitives:

  • Choice selects one option from a defined set.
  • Score evaluates content against ordered levels.
  • Noul evaluates a yes/no question and returns the probability that the answer is yes.

You can ask several independent questions about the same state. For a product page, a question set might look like this:

{
  "model": "jev-latest",
  "state": {
    "source": {
      "url": "https://example.com/product",
      "retrieved_at": "2026-09-21T08:00:00Z"
    },
    "page": {
      "markdown": "The selected, extracted page content goes here."
    }
  },
  "questions": {
    "audience": {
      "type": "choice",
      "instructions": "Who does this page most clearly target?",
      "criteria": {
        "developers": "The page directly addresses developers or technical builders.",
        "business_buyers": "The page directly addresses business or procurement buyers.",
        "mixed": "The page clearly addresses both groups.",
        "insufficient_evidence": "The page does not provide enough evidence to choose an audience."
      }
    },
    "value_proposition_clear": {
      "type": "noul",
      "instructions": "Does the page state a specific product value proposition?"
    },
    "technical_detail": {
      "type": "score",
      "instructions": "How technically detailed is the page?",
      "criteria": [
        "Mostly broad claims with little implementation detail",
        "Some concrete details, examples, or specifications",
        "Detailed implementation guidance or technical reference material"
      ]
    }
  }
}

The insufficient_evidence option is deliberate. If the page does not support a reliable audience classification, forcing it into developers, business_buyers, or mixed hides the gap. Your application can route that result to review instead of presenting a guess as a fact.

Keep each question narrow enough that its answer space is reviewable. “What should we do with this website?” combines classification, evaluation, prioritization, and policy. Separate those decisions, then combine the results in code. A high score on technical detail does not prove that the value proposition is clear, and a likely audience category does not prove that the page converts.

Treat the page as untrusted data

A scraped page is content, not an instruction channel. It can contain text such as “ignore previous instructions,” requests for secrets, fake citations, or directions intended for a model rather than a reader.

The Jev Web Analyzer repository demonstrates this boundary with a public implementation: a URL is fetched through ReplyNodes, converted into clean Markdown, and passed as state to Jev through Vercel AI Gateway. The repository is an unofficial community project, not a TypeSafe-affiliated product. Its server-side route validates public URLs, keeps credentials private, treats webpage content as untrusted state, and exposes the real fetch, extraction, and evaluation stages.

Use defense in depth around the state pipeline:

  • keep API keys outside the state and outside browser bundles;
  • label retrieved page text as data in the model boundary;
  • enforce URL, domain, redirect, page-count, depth, timeout, and response-size rules in application code;
  • validate that citations and URLs came from the retrieved source set;
  • test with pages containing indirect prompt-injection text;
  • require review or an insufficient-evidence result when the records do not support the decision.

Prompt instructions alone are not a security boundary. The network client, credentials, tool registry, and output validator must enforce the boundary independently.

Common state-preparation failures

Sending raw HTML without selection

Raw HTML contains layout, navigation, scripts, duplicated text, and other material that may not help the question. Extracting clean content can make the state easier to inspect, but it is not an accuracy guarantee. Measure a change against labeled examples if the decision matters.

Losing provenance during normalization

If the Markdown is copied into a string without its URL, retrieval timestamp, and request ID, a later answer can no longer show which page supported it. Keep provenance beside the content from retrieval through the final result.

Mixing unrelated pages in one state

An array remains one shared state; it is not a batch of independent website judgments. Keep pages together only when the question explicitly concerns the collection. Otherwise, evaluate each page in its own context or create named records with a clear relationship.

Rewriting hypotheses as facts

Preserve language such as “may be aimed at enterprise buyers” as a hypothesis or uncertain observation. Do not turn it into “the company targets enterprise buyers” during preprocessing unless the source actually supports that statement.

Letting a typed answer trigger an unreviewed action

Choice, Score, and Noul constrain the shape of a decision; they do not give the model authority to publish, modify an account, or change production. Keep thresholds, permissions, and side effects in application code. ReplyNodes' current public data surface is read-only; downstream actions, if any, belong to your application and its own controls.

A practical checklist

Before sending web context to Jev, verify:

  • The state contains only pages and fields relevant to the decision.
  • Every page has a source URL and retrieval time when freshness matters.
  • The API request ID is retained for debugging and correlation.
  • Evidence is separate from questions and application policy.
  • Uncertain observations remain visibly uncertain.
  • An insufficient-evidence path exists when a forced choice would mislead.
  • The question criteria describe observable differences rather than vague labels.
  • Retrieved text is treated as untrusted data.
  • The ReplyNodes key stays server-side.
  • Thresholds and side effects are enforced outside Jev.

For the retrieval layer, start with the ReplyNodes web-context guide and the web scraping API guide. For a complete, inspectable example of the boundary, read the Jev Web Analyzer source repository.

The goal is not to make the page sound more certain than it is. The goal is to give Jev a bounded, inspectable state, ask a decision that has a clear answer space, and let application code decide what happens next.