How to Implement Web Requests with gl.nondet.web.render in GenLayer Smart Contracts
You can implement web requests in GenLayer smart contracts by calling gl.nondet.web.render to fetch external page content, then processing that content through an LLM prompt wrapped in an equivalence-principle verification to maintain deterministic consensus.
The genlayer-project-boilerplate repository demonstrates this exact pattern in production contract code. Learning how to implement web requests with gl.nondet.web.render in GenLayer allows your smart contracts to ingest real-world data while preserving the blockchain's deterministic guarantees.
How to Implement Web Requests with gl.nondet.web.render
GenLayer contracts call external web resources through the non-deterministic API gl.nondet.web. The architectural flow follows five concrete steps to keep the contract deterministic while still allowing dynamic web data:
- Call
gl.nondet.web.renderto fetch raw page content. - Compose an LLM prompt that instructs the model to output only JSON.
- Execute the prompt with
gl.nondet.exec_prompt(..., response_format="json"). - Validate the LLM output using an equivalence-principle function such as
gl.eq_principle.strict_eq. - Parse the verified JSON and use the data inside the contract logic.
Fetch Page Content Using gl.nondet.web.render
The render method retrieves a page's content in either text or HTML form. In contracts/football_bets.py, the private _check_match helper uses mode="text" to strip markup and obtain plain text suitable for LLM consumption.
from genlayer import *
def fetch_match_text(url: str) -> str:
# Retrieve the page as plain text (no HTML tags)
return gl.nondet.web.render(url, mode="text")
Compose an LLM Prompt for Structured Extraction
After fetching raw page content, build an LLM prompt that instructs the model to output only JSON. The prompt should embed the web data alongside explicit schema requirements.
def extract_match_info(url: str, team1: str, team2: str) -> dict:
# 1️⃣ Get raw page content
page = fetch_match_text(url)
# 2️⃣ Build an LLM prompt that forces JSON output
prompt = f"""
Extract the match result for:
Team 1: {team1}
Team 2: {team2}
Web content:
{page}
Respond in JSON:
{{
"score": str, // e.g. "1:2" or "-" if unresolved
"winner": int // 0 for draw, -1 if unresolved
}}
It is mandatory that you respond only using the JSON format above,
nothing else.
"""
# 3️⃣ Execute the prompt (JSON response format)
llm_result = gl.nondet.exec_prompt(prompt, response_format="json")
# 4️⃣ Verify output with strict equivalence principle
verified = json.loads(gl.eq_principle.strict_eq(lambda: json.dumps(llm_result, sort_keys=True)))
return verified
Validate Output with the Equivalence Principle
Because web fetches and LLM calls are non-deterministic, GenLayer requires an equivalence-principle function to ensure validators agree on the result. The boilerplate uses gl.eq_principle.strict_eq to verify that repeated executions produce identical JSON output before the contract accepts the data.
Parse Verified Data Inside the Contract
Once sanitized, parse the JSON and use the fields directly in your contract logic. The FootballBets contract demonstrates this inside its _check_match method, located in contracts/football_bets.py (lines 30-33).
class FootballBets(gl.Contract):
# ...
def _check_match(self, resolution_url: str, team1: str, team2: str) -> dict:
# The core web-render + LLM extraction logic
def get_match_result() -> str:
web_data = gl.nondet.web.render(resolution_url, mode="text")
task = f'''
Extract the match result for:
Team 1: {team1}
Team 2: {team2}
Web content:
{web_data}
Respond in JSON:
{{
"score": str,
"winner": int
}}
Only output the JSON.
'''
result = gl.nondet.exec_prompt(task, response_format="json")
return json.dumps(result, sort_keys=True)
# Verify and parse
result_json = json.loads(gl.eq_principle.strict_eq(get_match_result))
return result_json
Key Files in the genlayer-project-boilerplate
The repository contains several files that illustrate non-deterministic web requests and their surrounding infrastructure:
contracts/football_bets.py— Shows a real-world use ofgl.nondet.web.render(lines 30-33) and the surrounding equivalence-principle flow.contracts/PatternTest.py— Contains additional examples of non-deterministic calls and pattern matching.config/genlayer_config.py— Loads environment variables required for RPC connectivity (used by the test harness).
Summary
gl.nondet.web.renderfetches external page content intextorHTMLmode for use inside smart contracts.- The equivalence principle (
gl.eq_principle.strict_eq) is mandatory to sanitize non-deterministic web and LLM output so validators can reach consensus. - The
FootballBetscontract incontracts/football_bets.pydemonstrates the complete fetch-prompt-verify-parse pattern. - Always force a structured response format such as
response_format="json"when callinggl.nondet.exec_promptto simplify downstream parsing.
Frequently Asked Questions
What does gl.nondet.web.render return?
The method returns raw page content for a given URL in either text or HTML form based on the mode parameter. When mode="text" is supplied, HTML tags are stripped so the output can be fed directly into an LLM prompt.
Why is the equivalence principle required for web requests?
Web pages and LLM responses are non-deterministic and may vary across validators. GenLayer uses equivalence-principle functions such as gl.eq_principle.strict_eq to ensure all validators agree on the exact same output before it is recorded on-chain.
Can gl.nondet.web.render fetch HTML instead of text?
Yes. According to the GenLayer API as implemented in the boilerplate, gl.nondet.web.render supports both text and HTML retrieval modes. The FootballBets contract uses mode="text" because plain text is easier to parse inside LLM prompts.
Where is the FootballBets contract located?
The complete implementation is located in contracts/football_bets.py within the genlayer-project-boilerplate repository. This file demonstrates the _check_match method combining gl.nondet.web.render, gl.nondet.exec_prompt, and gl.eq_principle.strict_eq to resolve match results.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →