How GenLayer Smart Contracts Access the Internet: The `gl.nondet.web` API Explained

GenLayer contracts access the internet through the gl.nondet.web API, a non-deterministic primitive that fetches live web content (HTML, text, screenshots) and requires equivalence-principle validation before results can be used on-chain.

GenLayer enables intelligent contracts to retrieve real-world data directly from the web—a capability that distinguishes its architecture from traditional blockchain platforms. This functionality is implemented in the genlayerlabs/genlayer-project-boilerplate repository and centers on a family of nondeterministic web-access methods that must be paired with consensus mechanisms.

Understanding Non-Deterministic Web Access

Traditional smart contracts are deterministic: given the same inputs, all validators must produce identical outputs. Web access breaks this assumption because network latency, content changes, or server responses may vary across validator nodes.

GenLayer solves this through two-stage execution:

  1. Fetch external data using gl.nondet.web methods
  2. Validate results using equivalence-principle functions like gl.eq_principle.strict_eq

This pattern ensures validators reach consensus on the same interpretation of web content before state changes are finalized.

The gl.nondet.web API Methods

The gl.nondet.web module provides four primary methods for internet access:

  • gl.nondet.web.get(url, headers={}) — Performs an HTTP GET request and returns a Response object
  • gl.nondet.web.post(url, body, headers={}) — Performs an HTTP POST request with a request body
  • gl.nondet.web.render(url, mode="text") — Retrieves rendered page content as plain text
  • gl.nondet.web.render(url, mode="html") — Retrieves raw HTML source
  • gl.nondet.web.render(url, mode="screenshot") — Captures a screenshot image of the page

All methods return data that must be processed through an equivalence principle before on-chain use.

Complete Web Access Pattern: Fetch, Prompt, Validate

The contracts/football_bets.py file demonstrates the full implementation pattern for how GenLayer contracts access the internet. This contract resolves football bets by scraping live match results from BBC Sport.

Step 1: Compose the Target URL

match_resolution_url = (
    "https://www.bbc.com/sport/football/scores-fixtures/" + game_date
)  # → line 62

Step 2: Fetch Page Content with gl.nondet.web.render

web_data = gl.nondet.web.render(resolution_url, mode="text")  # → line 31

The mode="text" parameter returns a clean, parseable text representation of the page rather than raw HTML.

Step 3: Extract Structured Data via LLM

task = f"""
Extract the match result for:
Team 1: {team1}
Team 2: {team2}

Web content:
{web_data}

Respond in JSON:
{{
    "score": str,
    "winner": int
}}
"""
result = gl.nondet.exec_prompt(task, response_format="json")  # → line 51

Step 4: Validate with Equivalence Principle

result_json = json.loads(gl.eq_principle.strict_eq(get_match_result))  # → line 54

The strict_eq wrapper ensures all validators agree on the identical JSON string before the result is accepted.

Full Working Example: FootballBets Contract

def _check_match(self, resolution_url: str, team1: str, team2: str) -> dict:
    # 1️⃣ Pull the page content

    web_data = gl.nondet.web.render(resolution_url, mode="text")   # line 31

    # 2️⃣ Build a prompt that asks the LLM to parse the score/winner

    task = f"""
    Extract the match result for:
    Team 1: {team1}
    Team 2: {team2}

    Web content:
    {web_data}

    Respond in JSON:
    {{
        "score": str,
        "winner": int
    }}
    """
    # 3️⃣ Ask the LLM and enforce a JSON response

    result = gl.nondet.exec_prompt(task, response_format="json")   # line 51

    # 4️⃣ Verify the nondeterministic output

    result_json = json.loads(gl.eq_principle.strict_eq(lambda: json.dumps(result, sort_keys=True)))  # line 54

    return result_json

Alternative Patterns for Internet Access

Direct GET Request for API Data

@gl.public.view
def fetch_price(self, ticker: str) -> str:
    url = f"https://api.example.com/price?ticker={ticker}"
    resp = gl.nondet.web.get(url)                     # ← HTTP GET

    # Validate response content

    price = gl.eq_principle.strict_eq(lambda: resp.body)
    return price

Screenshot Verification

@gl.public.view
def get_page_snapshot(self, url: str) -> bytes:
    img = gl.nondet.web.render(url, mode="screenshot")
    # Validators confirm the image hash matches

    img_hash = gl.eq_principle.strict_eq(lambda: hashlib.sha256(img).hexdigest())
    return img

Key Source Files in the Repository

File Purpose Key Lines
contracts/football_bets.py Web rendering, LLM prompting, equivalence-principle validation 31-34 (web fetch), 51-54 (LLM & validation)
contracts/__init__.py Contract module registration —
tests/direct/test_views.py Mock web calls in direct-mode tests —
config/genlayer_config.py Network endpoint configuration —

Summary

  • GenLayer smart contracts access the internet through gl.nondet.web, a non-deterministic API that supports GET, POST, and rendered content retrieval
  • All web calls require equivalence-principle validation (gl.eq_principle.strict_eq or similar) to achieve validator consensus
  • Three render modes are available: "text" for clean extraction, "html" for raw markup, and "screenshot" for visual verification
  • The FootballBets contract in contracts/football_bets.py demonstrates the complete pattern: URL construction, gl.nondet.web.render, LLM processing with gl.nondet.exec_prompt, and strict equality validation

Frequently Asked Questions

What makes gl.nondet.web "non-deterministic"?

The gl.nondet.web methods are non-deterministic because web servers may return different responses to different validators—due to timing, caching, geo-location, or dynamic content. Unlike deterministic operations that produce identical outputs on every node, these calls require equivalence-principle validation so validators can agree on a single canonical result before updating on-chain state.

Can GenLayer contracts access any website?

Yes, gl.nondet.web.get and gl.nondet.web.render can target any public URL. However, the equivalence principle may fail for highly dynamic or personalized content. For reliable consensus, contracts should target stable, public sources or use mode="text" to reduce noise from JavaScript-rendered variations.

What happens if validators disagree on web content?

If validators produce different outputs from a gl.nondet.web call, the equivalence-principle function (e.g., gl.eq_principle.strict_eq) detects the mismatch and halts execution. The transaction does not finalize until a sufficient majority agrees on the same result, preserving network consensus.

How do you test contracts that use internet access?

The tests/direct/test_views.py file demonstrates mocking web calls in direct-mode tests. Developers can simulate gl.nondet.web responses without making actual network requests, enabling deterministic test behavior while preserving the production code structure.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →