Cette page a été traduite par une machine et n'a pas encore été révisée par une personne. L'anglais est la référence ; les corrections sont les bienvenues sur GitHub. GitHub
Cookwala / SDK et scénarios / 018
An execution request with the wrong recipe hash is refused; the right hash still needs a person
An agent sends an ExecuteRequest naming a recipe and its hash. The executor compares the hash with the revision it holds and refuses a mismatch; with the right hash, the device's own dry run still applies. Nothing heats up in this scenario.
Lire d'abord: /docs/CORE/ /docs/API/
Étapes
Fetch the recipe the agent wants cooked.
getRecipeCompute the hash the request must carry.
hashSend a request with a zero hash: HTTP 202 with state refused, reason recipe_hash_mismatch. A refusal is a result, not an error.
startExecutionSend the right hash with nobody present: the hub's device is the example arm, and cutting needs a person. Refused before any motion.
startExecutionThe hub told the agent which hash it holds.
Résultat
You have seen two refusals an agent must handle before cooking starts, and that both arrive as a status, not a crash. Scenarios 040 onwards start, watch, stop and log an accepted execution.
Ligne de commande
cookwala hash examples/shakshuka.cookwala.json
curl -s -X POST http://localhost:7878/v1/executions -H 'Content-Type: application/json' -H 'Idempotency-Key: sc018-wrong-hash' -d '{"core": "0.2.0", "kind": "ExecuteRequest", "id": "sc018-wrong-hash", "recipe": "cw:cookwala.ai:example-shakshuka", "recipeHash": "sha256:0000000000000000000000000000000000000000000000000000000000000000", "requestedBy": "agent:scenario-018", "idempotencyKey": "sc018-wrong-hash", "x-hub-human-present": true}'Sortie enregistrée
Statut: ok
[1] getRecipe: {"$schema": "https://cookwala.ai/v1/schemas/recipe.schema.json", "cookwala": "0.1.0", "id": "example-shakshuka", "revision": 2, "updated": "2026-10-03", "hash": "sha256:2ea6fab93cc673fc6784f9bc9fe401d2387bb7779dc537df97286b73807c8841", "verification": {"level": "V2", "evidence": {"simulatorRuns": 1, "humanReviews": 1, "fieldReports": 0}, "reviewedBy": "fifi.cooking editorial", "notes": "Illustrative example for the spec; values are realistic but not field-verified."}, "dish": {"names": {"en": "Shakshuka", "ar": "شكشوكة", "fr": "Chakchouka"}, "cuisine": ["TN", "MA", "DZ", "LY"], "course": "main…
[2] hash: {"hash": "sha256:2ea6fab93cc673fc6784f9bc9fe401d2387bb7779dc537df97286b73807c8841"}
[3] startExecution: {"core": "0.2.0", "kind": "ExecutionStatus", "id": "sc018-wrong-hash", "seq": 0, "state": "refused", "request": "sc018-wrong-hash", "updatedAt": "2026-10-07T00:54:07Z", "refusal": {"reason": "recipe_hash_mismatch", "detail": "this hub holds sha256:2ea6fab93cc673fc6784f9bc9fe401d2387bb7779dc537df97286b73807c8841"}}
[4] startExecution: {"core": "0.2.0", "kind": "ExecutionStatus", "id": "sc018-right-hash", "seq": 0, "state": "refused", "request": "sc018-right-hash", "updatedAt": "2026-10-07T00:54:07Z", "refusal": {"reason": "needs_human_present", "detail": "cw.op.cut may not run unattended", "node": "n1"}}Code
Exécuter: python scenarios/out/018-wrong-hash-refuses-an-execution/python.py
# Scenario 018: An execution request with the wrong recipe hash is refused; the right hash still needs a person
# An agent sends an ExecuteRequest naming a recipe and its hash. The executor compares the hash with the revision it holds and refuses a mismatch; with the right hash, the device's own dry run still applies. Nothing heats up in this scenario.
# Run a hub first: python hub/cookwala_hub.py --recipes examples
import json, os
from cookwala.client import CookwalaClient, CookwalaProblem
def load(path):
with open(path, encoding="utf-8") as f:
return json.load(f)
def pick(obj, path):
for part in path.replace("]", "").replace("[", ".").split("."):
obj = obj[int(part)] if part.isdigit() else (len(obj) if part == "length" else obj.get(part))
return obj
c = CookwalaClient(os.environ.get("COOKWALA_HUB", "http://localhost:7878"))
# Step 1: Fetch the recipe the agent wants cooked.
recipe = c.get_recipe("shakshuka")
assert pick(recipe, "id") == "example-shakshuka", pick(recipe, "id")
print("ok", "id", "=", "example-shakshuka")
# Step 2: Compute the hash the request must carry.
h = c.hash(recipe)
assert pick(h, "hash") == "sha256:2ea6fab93cc673fc6784f9bc9fe401d2387bb7779dc537df97286b73807c8841", pick(h, "hash")
print("ok", "hash", "=", "sha256:2ea6fab93cc673fc6784f9bc9fe401d2387bb7779dc537df97286b73807c8841")
# Step 3: Send a request with a zero hash: HTTP 202 with state refused, reason recipe_hash_mismatch. A refusal is a result, not an error.
try:
wrong = c.start_execution({"core": "0.2.0", "kind": "ExecuteRequest", "id": "sc018-wrong-hash", "recipe": "cw:cookwala.ai:example-shakshuka", "recipeHash": "sha256:0000000000000000000000000000000000000000000000000000000000000000", "requestedBy": "agent:scenario-018", "idempotencyKey": "sc018-wrong-hash"}, "sc018-wrong-hash", True)
except CookwalaProblem as p:
wrong = p.body # a refusal is a result, not a crash
print("refused:", p.refusal)
assert pick(wrong, "state") == "refused", pick(wrong, "state")
print("ok", "state", "=", "refused")
assert pick(wrong, "refusal.reason") == "recipe_hash_mismatch", pick(wrong, "refusal.reason")
print("ok", "refusal.reason", "=", "recipe_hash_mismatch")
# Step 4: Send the right hash with nobody present: the hub's device is the example arm, and cutting needs a person. Refused before any motion.
try:
right = c.start_execution({"core": "0.2.0", "kind": "ExecuteRequest", "id": "sc018-right-hash", "recipe": "cw:cookwala.ai:example-shakshuka", "recipeHash": "sha256:2ea6fab93cc673fc6784f9bc9fe401d2387bb7779dc537df97286b73807c8841", "requestedBy": "agent:scenario-018", "idempotencyKey": "sc018-right-hash"}, "sc018-right-hash", False)
except CookwalaProblem as p:
right = p.body # a refusal is a result, not a crash
print("refused:", p.refusal)
assert pick(right, "state") == "refused", pick(right, "state")
print("ok", "state", "=", "refused")
assert pick(right, "refusal.reason") == "needs_human_present", pick(right, "refusal.reason")
print("ok", "refusal.reason", "=", "needs_human_present")
assert pick(right, "refusal.node") == "n1", pick(right, "refusal.node")
print("ok", "refusal.node", "=", "n1")
# Step 5: The hub told the agent which hash it holds.
assert pick(wrong, "refusal.detail") == "this hub holds sha256:2ea6fab93cc673fc6784f9bc9fe401d2387bb7779dc537df97286b73807c8841", pick(wrong, "refusal.detail")
print("ok", "refusal.detail", "=", "this hub holds sha256:2ea6fab93cc673fc6784f9bc9fe401d2387bb7779dc537df97286b73807c8841")
print("scenario complete")