> ## Documentation Index
> Fetch the complete documentation index at: https://docs.simplefunctions.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Research monitors

> Natural-language research monitors — keep an LLM-driven loop watching a topic, with results delivered to dashboard, webhook, or Telegram.

A **research monitor** is a long-running, natural-language research loop. You describe what you want watched (e.g. *"semiconductor sanctions affecting Taiwan markets"*) and SimpleFunctions runs the research on a cadence, posts results to your delivery channels, and stores history.

This is different from a [watch + alert rule](/build/watchlist-alerts), which fires on a structured condition (price threshold, econ release, ...). Research monitors are open-ended LLM runs over a topic.

## CLI

```bash theme={null}
sf monitor list                                  # list your monitors
sf monitor create "<intent>"                     # create + run once immediately
sf monitor show <id>                             # detail
sf monitor run <id>                              # run now
sf monitor run <id> --dry-run                    # plan only, no delivery
sf monitor delete <id>                           # delete
```

`sf monitor create` returns the new monitor and the first run result inline.

## API

All routes require `Authorization: Bearer sf_live_...` or browser session.

| Method | Path | Purpose |
| - | - | - |
| `GET` | `/api/research-monitors` | List your monitors. |
| `POST` | `/api/research-monitors` | Create a monitor (and optionally run it immediately). |
| `GET` | `/api/research-monitors/{id}` | Detail. |
| `PATCH` | `/api/research-monitors/{id}` | Update fields. |
| `DELETE` | `/api/research-monitors/{id}` | Delete. |
| `POST` | `/api/research-monitors/{id}/run` | Run now. Optional `?dryRun=true` or `{ dryRun: true }`. |

### POST /api/research-monitors

**Body**

| Field | Type | Required | Default | Notes |
| - | - | - | - | - |
| `intent` (or `query`, `text`) | string | yes | — | Natural-language description of what to watch. |
| `name` | string | optional | first 96 chars of `intent` | Display label. |
| `topics` (or `topic`) | string \| string\[] | optional | derived from intent | Topic tags for filtering and dedupe. |
| `cadenceMinutes` (or `cadence`) | number | optional | `360` | Run cadence in minutes. |
| `webhookEndpointId` (or `webhook`) | string | optional | none | Existing webhook endpoint id. |
| `telegramChatId` | string | optional | none | Telegram chat to deliver into. |
| `deliveryChannels` | array | optional | inferred | Override the default channel list. |
| `status` | string | optional | `active` | `active`, `paused`, or `archived`. |
| `runImmediately` | boolean | optional | `true` | Skip the first immediate run by sending `false`. |
| `metadata` | object | optional | — | Free-form metadata. |

**Response 201**

```json theme={null}
{
  "ok": true,
  "monitor": {
    "id": "rm_01J0...",
    "name": "Taiwan semiconductor sanctions",
    "intent": "semiconductor sanctions affecting Taiwan markets",
    "topics": ["geo", "semiconductor"],
    "cadenceMinutes": 360,
    "status": "active",
    "webhookEndpointId": null,
    "telegramChatId": null,
    "deliveryChannels": ["dashboard"],
    "nextRunAt": "2026-05-05T20:11:00.000Z",
    "createdAt": "2026-05-05T20:11:00.000Z"
  },
  "meta": { "fetchedAt": "2026-05-05T20:11:00.000Z" }
}
```

### PATCH /api/research-monitors/{id}

All fields are optional. Pass only the fields you want to change.

| Field | Notes |
| - | - |
| `name` | Up to 160 chars. |
| `intent` | Empty string returns `INVALID_INTENT`. Causes `topics` to be re-derived. |
| `topics` / `topic` | Override topic list. |
| `cadence` / `cadenceMinutes` | New cadence. |
| `status` | `active`, `paused`, `archived`. Other values return `INVALID_STATUS`. |
| `webhookEndpointId` / `webhook` | Pass `null` to detach. |
| `telegramChatId` | Pass `""` or `null` to detach. |
| `deliveryChannels` | Replace the channel list. |
| `metadata` | Replace metadata. |

### POST /api/research-monitors/{id}/run

```bash theme={null}
curl -X POST -H "Authorization: Bearer $SF_API_KEY" \
  "https://simplefunctions.dev/api/research-monitors/rm_01J0.../run"

# dry run — compute the plan without delivering
curl -X POST -H "Authorization: Bearer $SF_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"dryRun": true}' \
  "https://simplefunctions.dev/api/research-monitors/rm_01J0.../run"
```

Returns `{ ok: <bool>, result: <runResult>, meta: { fetchedAt } }`. Failures bubble up as 500 with `ok: false` so a webhook receiver can retry on transient errors.

### Errors

| Status | Code | Cause |
| - | - | - |
| `400` | `INTENT_REQUIRED` | Missing `intent`. |
| `400` | `INVALID_INTENT` | Empty intent on update. |
| `400` | `INVALID_STATUS` | Status not in `active`, `paused`, `archived`. |
| `401` | unauthorized | No / invalid auth. |
| `404` | `NOT_FOUND` | Monitor doesn't exist or isn't yours. |

## Patterns

### Watch a topic, post to Telegram

```bash theme={null}
sf monitor create "Taiwan semiconductor sanctions" --telegram-chat -100123 --cadence 240
```

### Programmatic create with webhook

```bash theme={null}
curl -X POST -H "Authorization: Bearer $SF_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "intent": "Fed-cut speculation in OIS and Kalshi",
    "cadenceMinutes": 360,
    "webhookEndpointId": "we_01J0...",
    "deliveryChannels": ["webhook", "dashboard"]
  }' \
  "https://simplefunctions.dev/api/research-monitors"
```

### Run on demand from a CI job

```bash theme={null}
curl -X POST -H "Authorization: Bearer $SF_API_KEY" \
  "https://simplefunctions.dev/api/research-monitors/rm_01J0.../run"
```

## See also

<CardGroup cols={2}>
  <Card title="Watchlist + alerts" href="/build/watchlist-alerts">
    Structured price / econ / gov alerts.
  </Card>

  <Card title="Webhooks" href="/build/webhooks">
    Signed delivery and replay.
  </Card>

  <Card title="Telegram bot" href="/cli/telegram">
    Bridge the CLI to a chat surface.
  </Card>

  <Card title="Direct API access" href="/build/direct-api-access">
    Auth, base URLs, language examples.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.