Esta página foi traduzida por máquina e ainda não foi revisada por uma pessoa. O inglês é a referência; correções são bem-vindas no GitHub. GitHub

Cookwala / SDK e cenários / 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.

Público: agent builder · Objetivo: Robôs para pessoas · Nível: intermediate

Leia primeiro: /docs/CORE/ /docs/API/

Passos

  1. Fetch the recipe the agent wants cooked. getRecipe

  2. Compute the hash the request must carry. hash

  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. startExecution

  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. startExecution

  5. The hub told the agent which hash it holds.

Resultado

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.

Linha de comando

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}'

Saída gravada

Status: 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"}}

Código

Executar: 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")

scenarios/018-wrong-hash-refuses-an-execution.json

Anterior: 017 Próximo: 019