Watch what matters to you.
Take the actions you designated.
On your behalf.

A Monitor watches what's important to you — a price, a queue, a server, a folder, an inbox — and takes the actions you designated when it sees what you told it to look for. Those actions include AI-driven prompts that the assistant executes on your behalf: triage an error, summarize an inbound report, classify a ticket, draft a response, post to Slack with context. This is what agentic AI actually means in production.

Replace the Watchdog Script Graveyard

The cron line that checks disk space. The Python loop that polls a status page. The PowerShell script that watches a stock price. They all look the same: read a value, compare it to a threshold, send an alert. They all live in different places, log in different formats, fail silently, and nobody owns them. Replace the lot with one Monitor each.

Before

  • Bash + cron on one box
  • Python script on another
  • Hand-rolled email send code
  • No audit trail when it didn't fire
  • No RBAC, no central view, no retry policy
  • Credentials in .env files scattered across hosts

After

  • One YAML monitor in InTouch
  • Linked to one or more schedules
  • Notify across 8 outbound channels
  • Full execution log with timestamps
  • RBAC, encrypted credential vault, audit
  • Edit, copy, move, run-now from the UI

Same job

  • "Alert me if disk > 90%"
  • "Notify on stock breakout"
  • "Page on-call if 5xx rate spikes"
  • "Email digest when CRM queue grows"
  • "Slack me when build queue stalls"
  • One pattern, every variant.

One File. Schedule + Check + When.

Monitors are authored in YAML. The body has three blocks: check: says what to read, when: says how to react, and the linked schedule (attached separately, just like jobs) says when to run.

name: avgo-price-watch
description: Watch AVGO and alert on entry/exit signals
category: Finance
version: 1.0.0

check:
  tool: stock-price-tool
  args: { ticker: AVGO }

when:
  - condition: "{{check.price}} <= 350"
    do:
      - notify:
          subscriberNames: [me]
          transport: telegram
          subject: "AVGO BUY signal"
          body: "Price ${{check.price}} crossed below 350"

  - condition: "{{check.price}} >= 420 && {{check.volume}} > 1000000"
    do:
      - notify:
          alertNames: [trading-desk]
          subject: "AVGO breakout"
          body: "AVGO at ${{check.price}} on {{check.volume}} shares"

  - ai: "Is the spread between bid and ask wider than typical for this name?"
    do:
      - notify:
          subscriberNames: [me]
          transport: email
          subject: "AVGO unusual spread"
          body: "Review live quote"

  - else:
    do: []

Save it. Link it to a 1-minute intraday schedule. The Monitor runs, evaluates, and fires — with full audit, RBAC, and notification routing already wired.

What an Arm Can Do

A matched arm fires its do: list of actions, in order. Five verbs cover every "watch + act" pattern. (The job-local if task shares the same grammar and adds two flow-control verbs — skip_remaining and goto — that only make sense inside a job's task list.)

notify

Send a message. Address with subscriberNames, publisherNames, or alertNames. Templatable subject and body. Routes to email, SMS, Slack, Discord, Telegram, WhatsApp, Teams, LINE, or the in-app inbox — whichever each addressee has configured.

run_tool

Run any registered tool inline — SQL query, HTTP call, AWS action, anything. Optional as: <name> captures the tool's outputs so a later action in the same arm can reference {{name.responseCode}} or similar.

run_skill

Run an installed InTouch skill — this is where AI-driven prompts run on your behalf with your credentials and audit. The skill's answer, model, inputTokens, outputTokens, and toolCallCount are captured under the as: key for the next action to reference.

run_jobfile

Fire-and-forget dispatch of a YAML Job File. Pass args the target file references with {{args.X}}. The monitor doesn't wait for the job to finish — runs are independently audited.

nothing

Explicit no-op. Useful for documented "we considered this case but no side effect" arms — usually paired with an else: arm so the audit log records that the Monitor evaluated cleanly and chose to stay quiet.

Three Ways to Match

condition:

Native boolean expression. Operators: == != < <= > >= contains. Combine with && and ||. Interpolate {{check.field}}, {{monitor.firedAt}}, {{env(NAME)}}. Deterministic. Zero LLM cost. Use this when the rule is crisp.

ai:

Free-form yes/no prompt for the AI assistant. Either a bare string (the prompt) or a map with optional context: [server_status, active_jobs, ...] to inject extra grounding. Costs LLM tokens per evaluation. Use when "is this unusual" is the only way to ask.

else:

Catch-all. Must be the last arm. Fires only if no preceding arm matched. Often paired with do: [] (do nothing) or with a quiet "all clear" notification.

Linked to Schedules & Trigger Files

A Monitor doesn't carry a schedule in its body. Just like jobs, you create the Monitor and then attach it to one or more schedules and/or trigger files via the same many-to-many bis_callink wiring.

One schedule, many monitors

A 5-minute schedule can drive a disk-space monitor, a queue-depth monitor, and a SSL-expiry monitor. They all fire on the same tick.

One monitor, many schedules

The same Monitor can run weekday-9am AND weekend-2pm. Two schedules attached, one Monitor body. Edit once.

File change drives a Monitor

When a watched path changes, every linked Monitor fires. Same many-to-many model. A file landing in /incoming can drive a parsing job AND a "did we get all expected files today" Monitor in the same pass.

An orphan Monitor never fires

A Monitor with zero linked schedules or trigger files is dormant by design. No error, no warning — just doesn't run. Lets you author and review before going live.

Three Author Paths

Write the YAML

Open the Monitors view, click New, paste or compose the YAML, save. The validator runs live as you type — errors[] block save, warnings[] let you proceed. Link a schedule from the detail panel and you're done.

Generate with AI

Click Generate, describe the Monitor in one sentence ("alert me when disk goes above 90% on the prod host"), and the AI assistant authors a valid YAML body. Review, tweak, save. The classifier picks up the intent automatically — no special prompt.

Install from the hub

The InTouch hub carries Monitors as a first-class asset type alongside tools, skills, and job files. Browse, preview, click install — the dependency-cascade pulls any tools the Monitor's check: needs.

Run Now. Bulk Enable. Copy. Move.

Everything the Jobs view can do, the Monitors view can do.

Run-now

Test-fire any Monitor end-to-end from the row. Hits the full pipeline including notifications and downstream dispatches — not a dry run. Doesn't advance the scheduler; the next natural fire still happens on time. matchedArm and actionsFired are surfaced in the activity log so you can verify the right arm matched.

Bulk enable / disable

Multi-select with checkboxes; flip a batch of Monitors on or off in one click. Disabled Monitors are skipped at fire time without being deleted — the right way to silence noisy monitors during a maintenance window.

Live YAML validate

POST /monitor/validate takes a YAML body and returns {valid, errors[], warnings[]} without touching the database. The form debounces on every keystroke and lights red/yellow gutter markers as you type.

Copy & move (Dept/Ent)

Copy a Monitor across groups with a new name; move one to a different group. Identical semantics to the Schedule and Trigger File equivalents. Gated to Department / Enterprise — Personal and Team have a single Monitors group.

Monitors vs the if Task

The same arm grammar shows up in two places. Use Monitors when the cadence is external. Use the if task when the decision is local to a job.

Dimension Monitor if task
What it watchesExternal state — APIs, files, queues, prices, server healthOutput of preceding tasks inside the same job
How it firesLinked schedule or trigger fileReaches its slot in the parent job's task sequence
Scope of goto / skip_remainingN/A (monitor isn't a task list)The parent job's task list
Other action verbsnotify, run_tool, run_skill, run_jobfile, nothingSame six, plus goto and skip_remaining
Audit shapeMonitor activity log + matched-arm recordStandard job execution log

See the if task →

Every Monitor Action Is an Endpoint

Everything in the UI is also reachable from REST. The MCP server exposes them to AI clients (Claude Code, Cursor, Claude Desktop). The InTouch AI assistant authors Monitors by calling these.

Endpoint Description
GET /monitor/listList all monitors (lightweight)
GET /monitor/get-by-idFull monitor including YAML body
POST /monitor/insertCreate from CreateMonitorDTO with optional scheduleNames auto-link
PUT /monitor/updateUpdate YAML body, enabled, readme; schedule links preserved
POST /monitor/validateLint a YAML body — no DB write, returns {valid, errors[], warnings[]}
POST /monitor/run-nowTest-fire end-to-end without advancing the scheduler
PUT /monitor/set-statusEnable / disable
DELETE /monitor/deleteDelete; cascades schedule + trigger-file link rows
POST /monitor/copyDuplicate to another group (Dept / Enterprise)
POST /monitor/moveMove to a different group (Dept / Enterprise)
POST /monitor/install-from-hubInstall from an InTouch hub slug
POST /monitor/add-schedule / remove-scheduleLink / unlink a schedule
POST /monitor/add-trigger-file / remove-trigger-fileLink / unlink a trigger file
GET /monitor/get-schedules-by-id / get-trigger-files-by-idInspect what's linked
GET /schedule/list-monitors-by-scheduleidReverse: monitors linked to a schedule
GET /triggerfile/get-monitors-by-idReverse: monitors linked to a trigger file

Replace Your Watchdog Scripts

Personal Edition is free with no time limit. The full Monitor surface ships in every edition.