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

# From a Monitor signal to a Play

> Watch target accounts for a hiring signal, store each posting, and run a Play that finds the leader of the team that is hiring.

[Human guide: work with your agent →](https://deepline.com/docs/human/guides/monitor-to-play.md)

> [!NOTE]
>
> Turn one hiring signal into a repeatable Play: a scoped Monitor stores each
> posting, and a published Play finds the right contact for every new row.

This walkthrough builds one complete signal workflow. When a target account
posts a revenue operations role, Deepline stores the posting and runs a Play
that finds the account's revenue operations leader. You need one Monitor and
one Play. Neither needs your agent or terminal to stay open after you publish.

[Set up a Monitor](https://deepline.com/plays/set-up-a-monitor) is the command reference for every
step below, including Fleets, pausing, and billing suspension.

## Before you start

A Monitor and each Play run spend Deepline credits, so check your balance
first:

```bash theme={"languages":{"custom":["/languages/deepline-prompt.json"]}}
deepline billing balance
```

## 1. Choose the source and its stream

List the Monitor types available to your workspace, then inspect the one you
want:

```bash theme={"languages":{"custom":["/languages/deepline-prompt.json"]}}
deepline tools list --categories monitors
deepline describe deepline_native.company_radar
```

The Deepline Native company radar has a `company_job_openings` stream. Each
stored row has the account `domain`, the `job_title`, the `job_url`, and the
`job_posted_at` date, among other columns. `describe` shows the full column
list and current pricing.

## 2. Scope the Monitor before you deploy it

Save this definition as `acme-revops-openings.monitor.json`:

```json theme={"languages":{"custom":["/languages/deepline-prompt.json"]}}
{
  "key": "acme-revops-openings",
  "tool": "deepline_native.company_radar",
  "payload": {
    "domain": "acme.com",
    "radar_type": "company_job_openings",
    "job_titles": "\"Revenue Operations\""
  }
}
```

`job_titles` narrows what the Monitor accepts. That matters for cost: a
Monitor charges for the events it accepts, and a filter inside a Play cannot
undo that. Put the narrowest useful scope in the Monitor, then use the Play to
decide what to do with each row.

To watch many accounts, keep one Monitor per account. A
[Fleet](https://deepline.com/plays/set-up-a-monitor#monitor-many-rows-from-a-table-beta) creates
and maintains those Monitors from a Database table of accounts.

## 3. Check, preview, and deploy

```bash theme={"languages":{"custom":["/languages/deepline-prompt.json"]}}
deepline monitors check --file acme-revops-openings.monitor.json
deepline monitors deploy --dry-run --file acme-revops-openings.monitor.json
```

`check` validates the definition without spending credits. The dry run shows
the price and any existing Monitor that already covers this scope. Reuse an
existing Monitor instead of deploying a duplicate.

When the plan looks right, deploy it and read it back:

```bash theme={"languages":{"custom":["/languages/deepline-prompt.json"]}}
deepline monitors deploy --file acme-revops-openings.monitor.json
deepline monitors get acme-revops-openings
```

A new Monitor can show `provisioning` until the provider confirms it. It
starts storing rows, and billing, once it is `active`.

## 4. Write the Play

Save this as `revops-opening-to-contact.play.ts`:

```ts theme={"languages":{"custom":["/languages/deepline-prompt.json"]}}
import deepline from 'deepline';
import type { SqlListenerEvent } from 'deepline';

type JobOpeningRow = {
  domain?: string | null;
  job_title?: string | null;
  job_url?: string | null;
  job_posted_at?: string | null;
};

export const config = {
  description:
    'Find the revenue operations leader when a watched account posts a revenue operations role.',
  compatibility: { authoringContract: 'explicit-freshness' },
  sqlListeners: [
    {
      id: 'revops-openings',
      tool: 'deepline_native.company_radar',
      stream: 'company_job_openings',
      operations: ['INSERT'],
      where: {
        after: {
          job_title: { ilike: '%revenue operations%' },
        },
      },
    },
  ],
};

export default async function (event: SqlListenerEvent<JobOpeningRow>) {
  const posting = event.after;
  if (!posting?.domain) return { handled: false, reason: 'no_domain' };

  const contact = await deepline.runPlay(
    'revops_leader',
    'prebuilt/company-to-contact',
    {
      domain: posting.domain,
      roles: ['VP Revenue Operations', 'Head of Revenue Operations'],
      limit: 1,
    },
    { description: 'Find the leader of the team that is hiring.' },
  );

  return {
    handled: true,
    domain: posting.domain,
    job_title: posting.job_title ?? null,
    job_url: posting.job_url ?? null,
    job_posted_at: posting.job_posted_at ?? null,
    contact,
  };
}
```

The listener names the Monitor's tool and stream, not its key. Every Monitor
that writes to `company_job_openings` can start this Play, so one Play covers
every watched account. The `where` filter runs before the Play starts; rows
that do not match never cost a run.

A `where` filter has no OR. To also catch a spelling such as `RevOps`, add it
to the Monitor's `job_titles` and add a second listener with its own `ilike`.
A title that matches both listeners starts two runs.

## 5. Check and publish the Play

```bash theme={"languages":{"custom":["/languages/deepline-prompt.json"]}}
deepline plays check revops-opening-to-contact.play.ts
deepline plays publish revops-opening-to-contact.play.ts
```

`plays check` validates the listener's tool, stream, and filter columns, and
shows the event shape the Play receives. After you publish, each new matching
row starts one run. There is nothing to poll.

To try the Play before a real posting arrives, run it once with a sample row.
This is a real run and spends credits for the contact lookup:

```bash theme={"languages":{"custom":["/languages/deepline-prompt.json"]}}
deepline plays run revops-opening-to-contact.play.ts --input '{"operation":"INSERT","after":{"domain":"acme.com","job_title":"Revenue Operations Manager","job_url":"https://acme.com/careers/revops"}}'
```

## 6. Watch it work

```bash theme={"languages":{"custom":["/languages/deepline-prompt.json"]}}
deepline monitors get acme-revops-openings
deepline runs list --play revops-opening-to-contact
```

`monitors get` shows the Monitor's state and the Plays connected to its
stream. `runs list` shows each run the Monitor started. A quiet stream is not
an error: the account may not have posted a matching role yet.

## Keep it running

* **Credits run out:** Deepline turns the workspace's Monitors off and
  resumes them after you add credits. Events from the time they were off are
  not replayed.
* **Change the scope:** run `deepline monitors update` with only the fields
  you want to change. The Play does not need to change.
* **Pause:** `deepline monitors stop` keeps the definition; `start` applies
  it again. A stopped Monitor stays stopped until you start it.

## Verify this task

Confirm the Monitor is `active` and scoped to the roles you want. Confirm that
`plays check` accepts the listener, and that each run returns the posting and
a contact or a miss reason.

Ask your agent to explain a failed check before repeating work or widening the
scope.


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