manifest: qloops.loop/v1

# Surface relevant price updates without repeatedly checking the source manually.
# OpenRouter example: configure the model explicitly. CLI acceptance uses the caller interface.

id: price-watch
name: "Price watch: machine filters, human authorises"
version: 1.1.0
description: >
  Checks a rate, lets an agent-gate decide whether it is worth anyone's
  attention, then holds for a human before the outgoing request.
owner: oleg
enabled: true

triggers:
  - kind: schedule
    cron: "0 8 * * *"
  - kind: manual

settings:
  budgetUsd: 0.10

steps:
  - id: pw-fetch
    kind: fetch
    config:
      name: "Fetch rate"
      url: "https://open.er-api.com/v6/latest/USD"
      format: json
      timeoutSec: "30"

  - id: pw-judge
    kind: approval-gate
    config:
      name: "Worth waking anyone?"
      reviewer: agent
      anchor: "rate"
      rubric: >
        The payload holds `json.rates`, a map of currency code to rate against
        USD. PASS only if `json.rates.UAH` is above 42.0.
        Otherwise FAIL — an ordinary day is not news.
      escalateOn: objection

  - id: pw-confirm
    kind: approval-gate
    config:
      name: "Send it?"
      reviewer: human
      anchor: "rate"

  - id: pw-send
    kind: api-request
    config:
      name: "Send the alert"
      method: POST
      url: "{{env.QLOOP_WEBHOOK_URL}}"
      expect: "2xx"
      timeoutSec: "30"
      body: '{"text":"Rate alert — USD/UAH is {{steps.Fetch rate.output.json.rates.UAH}}"}'
