showcase · tier 1 · business
Price watch
Pulls one field from the shop API, compares it in CEL, pings your webhook. No model call anywhere.
- 2tasksthe plan falls out of the bindings
- 2wavesparallel by construction
- 1verbs exercisedinvoke
- T1the tierbusiness
The whole file
2 tasks · 2 wavesThe plan falls out of the bindings, nothing is scheduled by hand.
price-watch.nika.yamlsource
nika: v1workflow: id: price-watch description: "Watch a product price, ping me when it drops below my target"const: product_api: "https://api.shop.example.com/v1/products/macbook-air" alert_below: 899secrets: alerts_webhook: source: env key: ALERTS_WEBHOOK_URL egress: # sanction the one send · the secret IS the URL - to: "nika:notify" host_from_self: truepermits: tools: ["nika:fetch", "nika:notify"] net: # TWO hosts, for two different reasons. # # `api.shop.example.com` is what `const.product_api` names — a literal # `check` can read, so a mismatch here is caught before the run. # # `hooks.slack.com` is the ALERT host, and it is the entry people leave # out. `host_from_self:` above sanctions the FLOW (this secret may be the # URL) — it does not grant the capability. The host stays unknown at # check, so it is judged at RUN against this bound: name the escalation # host here or the send is refused mid-run, the first time the price # actually drops. Swap it for wherever YOUR webhook lives. http: ["api.shop.example.com", "hooks.slack.com"]tasks: check: invoke: tool: "nika:fetch" args: url: "${{ const.product_api }}" mode: jq jq: "." output: # named jq bindings over the raw response price: ".price" name: ".name" on_error: # Offline rehearsal · a sample ABOVE the target, so the gate below stays # closed and the dry run ends green with the alert skipped. The alert # path is therefore NOT exercised offline — which is exactly why the # `net:` bound above has to be right by reading, not by running. recover: { price: 949, name: "MacBook Air (offline sample)" } alert: with: price: ${{ tasks.check.price }} # value edges · the named bindings cross the boundary here name: ${{ tasks.check.name }} when: ${{ with.price < const.alert_below }} invoke: tool: "nika:notify" args: channel: webhook target: "${{ secrets.alerts_webhook }}" message: "Price drop · ${{ with.name }} is now ${{ with.price }} (target ${{ const.alert_below }})" severity: infooutputs: price: ${{ tasks.check.price }}audited · 3 tasks · 3 waves · permits declarednika 0.106.1
nika inspect · engine 0.106.1 · vendored graph, never re-derived
2 declared edges · 2 waves · the plan falls out of the bindings