Esta página fue traducida por una máquina y aún no ha sido revisada por una persona. El inglés es la referencia; las correcciones son bienvenidas en GitHub. GitHub

Cookwala / SDK y escenarios / 045

A run is refused before anything heats when no person is present

The hub dry-runs every request against the device before accepting it. This counter arm has no hob and may not cut unattended, so a request with nobody present is refused at the first node, and the refusal says why.

Audiencia: robot maker · Objetivo: Robots para las personas · Nivel: beginner

Leer primero: /docs/CORE/ /docs/HUB/

Pasos

  1. The device: three operations (cut, crack, transfer), one vision sensor, presence detection and a stop control. capabilities

  2. Send the request with humanPresent false. The answer is an ExecutionStatus in state refused with a reason, the node and a detail; nothing was heated or moved. startExecution

  3. Stop is never refused, even for a run that never started: the hub returns the final status unchanged. stopExecution

Resultado

You have a refusal with reason, node and detail, which is the standard's first promise: check before heat. Next: scenarios 046 to 048 show the other refusal reasons a hub applies before the dry run.

Línea de comandos

cookwala dryrun examples/shakshuka.cookwala.json --device examples/capabilities/robot-arm.json
cookwala dryrun examples/shakshuka.cookwala.json --device examples/capabilities/robot-arm.json --human-present

Salida grabada

Estado: ok

[1] capabilities: {"cookwala": "0.1.0", "actor": {"kind": "robot", "id": "robot:arm-1", "vendor": "Example Robotics", "model": "CounterArm 2"}, "roles": ["executor"], "location": {"zone": "counter-left", "mobile": false}, "capabilities": {"ops": [{"op": "cw.op.cut", "params": {"shape": ["dice", "slice", "mince", "julienne"]}, "ingredientClasses": ["cw.ing.class.vegetable_firm", "cw.ing.class.herb"], "reliability": 0.97}, {"op": "cw.op.crack", "reliability": 0.95}, {"op": "cw.op.transfer", "maxMassG": 3000}], "sensors": [{"sensor": "cw.sense.vision", "visionCues": ["cw.sense.translucent", "cw.sense.egg_whites_se…
[2] startExecution: {"core": "0.2.0", "kind": "ExecutionStatus", "id": "ex-045-absent", "seq": 0, "state": "refused", "request": "ex-045-absent", "updatedAt": "2026-10-07T00:54:31Z", "refusal": {"reason": "needs_human_present", "detail": "cw.op.cut may not run unattended", "node": "n1"}}
[3] stopExecution: {"core": "0.2.0", "kind": "ExecutionStatus", "id": "ex-045-absent", "seq": 0, "state": "refused", "request": "ex-045-absent", "updatedAt": "2026-10-07T00:54:31Z", "refusal": {"reason": "needs_human_present", "detail": "cw.op.cut may not run unattended", "node": "n1"}}

Código

Ejecutar: python scenarios/out/045-refused-before-heat-when-no-person-is-present/python.py

# Scenario 045: A run is refused before anything heats when no person is present
# The hub dry-runs every request against the device before accepting it. This counter arm has no hob and may not cut unattended, so a request with nobody present is refused at the first node, and the refusal says why.
# 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: The device: three operations (cut, crack, transfer), one vision sensor, presence detection and a stop control.
hub = c.capabilities()
assert pick(hub, "capabilities.ops.length") == 3, pick(hub, "capabilities.ops.length")
print("ok", "capabilities.ops.length", "=", 3)
assert pick(hub, "capabilities.sensors.length") == 1, pick(hub, "capabilities.sensors.length")
print("ok", "capabilities.sensors.length", "=", 1)
assert pick(hub, "safety.presenceDetection") == True, pick(hub, "safety.presenceDetection")
print("ok", "safety.presenceDetection", "=", True)

# Step 2: Send the request with humanPresent false. The answer is an ExecutionStatus in state refused with a reason, the node and a detail; nothing was heated or moved.
try:
    refused = c.start_execution({"core": "0.2.0", "kind": "ExecuteRequest", "id": "ex-045-absent", "recipe": "cw:cookwala.ai:example-shakshuka", "recipeHash": "sha256:2ea6fab93cc673fc6784f9bc9fe401d2387bb7779dc537df97286b73807c8841", "servings": 4, "requestedBy": "agent:planner-1", "idempotencyKey": "ex-045-absent-a"}, "ex-045-absent-key", False)
except CookwalaProblem as p:
    refused = p.body  # a refusal is a result, not a crash
    print("refused:", p.refusal)
assert pick(refused, "state") == "refused", pick(refused, "state")
print("ok", "state", "=", "refused")
assert pick(refused, "refusal.reason") == "needs_human_present", pick(refused, "refusal.reason")
print("ok", "refusal.reason", "=", "needs_human_present")
assert pick(refused, "refusal.node") == "n1", pick(refused, "refusal.node")
print("ok", "refusal.node", "=", "n1")
assert pick(refused, "refusal.detail") == "cw.op.cut may not run unattended", pick(refused, "refusal.detail")
print("ok", "refusal.detail", "=", "cw.op.cut may not run unattended")

# Step 3: Stop is never refused, even for a run that never started: the hub returns the final status unchanged.
try:
    stop = c.stop_execution("ex-045-absent")
except CookwalaProblem as p:
    stop = p.body  # a refusal is a result, not a crash
    print("refused:", p.refusal)
assert pick(stop, "state") == "refused", pick(stop, "state")
print("ok", "state", "=", "refused")
assert pick(stop, "seq") == 0, pick(stop, "seq")
print("ok", "seq", "=", 0)

print("scenario complete")

scenarios/045-refused-before-heat-when-no-person-is-present.json

Anterior: 044 Siguiente: 046