How to write a Wield recipe, step by step
A Wield recipe is one JSON file that teaches Wield one task on one website: for example, searching train connections or listing a site's search results. It describes the HTTP requests the site's own pages make, the parameters they take, how to read the responses, and how to check the output. It contains no code. Wield runs it in a tab of the site, in the user's own browser, and sends requests only to the origins the recipe lists.
Anatomy of a recipe
A recipe has these top-level parts:
| Part | What it holds |
|---|---|
site | The site's id, name, origin, the origins a request may use, country and language |
task, description, keywords | What the recipe does, what comes back, and words that help agents find it |
effect and requires_login | read or write, and whether a logged-in session is needed |
params | A JSON Schema for the inputs the agent may pass |
steps | The requests, in order, with how to read each response |
output | The shape of the result, with a JMESPath expression that builds it |
verify | Example parameters and checks the output must pass |
The format is documented in the recipe format reference. Use it as the source of truth.
Declare the site and the params
Set site.origin to the tab the recipe runs in. List every origin a request may use in site.origins. Requests to any other host are blocked, and redirects are not followed.
Write params as a JSON Schema object. Give every property a description with examples, because agents read them. Wield checks the params before anything is sent and fills in defaults. Keep additionalProperties set to false, so unexpected input is rejected.
Write the steps
Each step has an id and a request. Use {{ params.name }} to insert a parameter into a URL, query or body. Keep to these rules:
- Up to 12 steps per recipe, and at most 40 requests per run.
CookieandHostheaders are not allowed. The browser sends the site's cookies itself.- Use
expectto check the status, for example"status": [200]. - Use
extractto read values from the response, for example with a JMESPath expression onjson. - A
GETstep starts as soon as the steps it references are done, so independent lookups run in parallel.
Here is the small example from the recipe format reference:
{
"schema": "https://wield.run/schema/recipe/v1.json",
"id": "example.de/search-items",
"version": 1,
"site": {
"id": "example.de",
"name": "Example",
"origin": "https://www.example.de",
"origins": ["https://www.example.de", "https://api.example.de"],
"country": "DE",
"language": "de"
},
"task": "Search items by keyword and maximum price",
"description": "What comes back, and what is filtered (e.g. sponsored results are dropped).",
"keywords": ["suche", "artikel", "search", "items"],
"effect": "read",
"requires_login": false,
"params": {
"type": "object",
"properties": {
"query": { "type": "string", "minLength": 2, "maxLength": 100 },
"max_price": { "type": "integer", "minimum": 1 },
"limit": { "type": "integer", "default": 20, "maximum": 50 }
},
"required": ["query"],
"additionalProperties": false
},
"steps": [
{
"id": "search",
"request": {
"method": "GET",
"url": "https://api.example.de/v2/search",
"query": { "q": "{{ params.query }}", "price_to": "{{ params.max_price }}", "size": "{{ params.limit }}" }
},
"expect": { "status": [200] },
"extract": { "json": { "total": "meta.total", "items": "results[?!sponsored]" } }
}
],
"output": {
"schema": { "type": "object", "required": ["items"] },
"value": "{total: steps.search.total, items: steps.search.items[].{title: title, price_eur: price.amount, url: join('', ['https://www.example.de', path])}}"
},
"verify": {
"example_params": { "query": "fahrrad", "max_price": 300 },
"checks": ["length(output.items) > `0`", "output.items[0].price_eur <= `300`"]
}
}Describe the output and verify it
output.schema is a JSON Schema for the result. output.value is a JMESPath expression that builds it from the steps. Use typed values: numbers, booleans, ISO dates and absolute links. Drop ads, sponsored and promoted results by default.
verify.checks are JMESPath expressions that must return true on the output of verify.example_params. Write checks that would fail if the site changed its answer, such as a minimum result count or a price limit.
Writes
A recipe that changes data must set effect to write, and mark the write step with write: true. Before the first write request, Wield stops and shows the user an Allow window with every request and body. Deny is the default. Write recipes are not tested automatically, because testing would send real data. Run one under supervision first.
Check it
- Run
wield-build linton the file. Read every warning and fix it, or explain it inprovenance.notes. - Run the recipe live with its example parameters. For public read recipes,
wield-dev runworks from the command line. For anything that needs a login, run it in your own browser through the extension. - Confirm that every check in
verify.checkspasses. - Write down how each request was found, and name every host outside the site's own domain.
- Note what the site's terms say about automated access, in
tos.notes.
Contributions are reviewed by a maintainer before they become public. The contributing guide lists the full checklist.
FAQ
Can a recipe run JavaScript on the page?
No. Recipes are data, not code. They describe requests and how to read responses. They cannot run scripts in the page or read anything outside the responses they asked for.
What are the limits?
A run allows 12 steps, 20 loop iterations, 40 requests, 5 MB per response and 60 seconds in total. These limits protect the site and the user's browser.
Where do I start if I am not sure what the site sends?
Capture the task in your browser's developer tools, then read the JSON request it makes. See how to find a site's internal API in DevTools.