Buying-trigger feed
Each week, the companies in your customer sentence that raised money, posted the role you replace, or dropped the tool you replace.
- Kind
- Workflow
- Price
- $1.55 per week
- Your time
- 7 minutes
- Approval
- Runs on its own
- Deepens
- Outbound
Tell me which property managers in my ICP started hiring a leasing coordinator this week, spend up to $2, and show me the plan first.
curl -X POST "https: //api.sb/ leaseline.app/ icps/ track? mode= try" \
-H "Authorization: Bearer $SB_TOKEN" \
-H "Content-Type: application/ json" \
-d '{"goal": "Tell me which property managers in my ICP started hiring a leasing coordinator this week, spend up to $2, and show me the plan first.", "budget": {"amount": 2, "currency": "USD"}}'
npx startup-builder do ICP.track --try --data '{"goal": "Tell me which property managers in my ICP started hiring a leasing coordinator this week, spend up to $2, and show me the plan first.", "budget": {"amount": 2, "currency": "USD"}}'
{
"name": "do",
"arguments": {
"mode": "try",
"code": "return await $.ICP.track({ goal: 'Tell me which property managers in my ICP started hiring a leasing coordinator this week, spend up to $2, and show me the plan first.', budget: { amount: 2, currency: 'USD' } })"
}
}
import { $ } from 'startup-builder'
const result = await $.try.ICP.track({ goal: 'Tell me which property managers in my ICP started hiring a leasing coordinator this week, spend up to $2, and show me the plan first.', budget: { amount: 2, currency: 'USD' } })
{
"mode": "try",
"stored": false,
"estimate": "About $1.55 a week",
"sample": {
"company": "Cedar Hollow Rentals",
"trigger": "hiring",
"detail": "Leasing coordinator, posted 2026-10-24",
"in your ICP": "yes",
"added": "account Audience"
}
}
What you get
- 1 week · Each week, the companies in your customer sentence that raised money, posted the role you replace, or dropped the tool you replace. · Audience
added[]· Each company added this week, withwhyNow: the Event and its detail, such as “Leasing coordinator, posted 2026-10-24”.updated[]· Companies already on the Audience with a new trigger; never added twice.skipped· Trigger hits outside your customer sentence, by reason and count.
How long: About 5 minutes.
Trigger
It runs weekly, as three Monitors with change set to funding, hiring and technology.
every('mon 06:00' , ($) => $.ICP.track({ icp: 'icps/icp_4' , changes: ['funding', 'hiring', 'technology'] }))Steps
Your agent does these steps, one row per step; each step’s check is part of its row and its price.
| Step | Verb | Returns | Price | Approval |
|---|---|---|---|---|
| 1. Read the week’s funding rounds | Organization.find | Companies in your sentence that announced a round in the last 7 days | About 80¢ | Runs on its own |
| 2. Read the week’s job posts for your roles | Organization.find | Companies in your sentence that posted the role you replace | About 25¢ | Runs on its own |
| 3. Read what changed at the watched accounts | Organization.enrich | Technology adopted or dropped at 50 accounts, oldest-read first | About 50¢ | Runs on its own |
| 4. Keep the hits that match your sentence | Collection.query | The hits that pass every filter in your sentence, by a declared rule | Free | Runs on its own |
| 5. Add them to the account Audience with why now | Audience.create | Rows added or updated, each emitting its Event so a Play’s Trigger can act on it | Free | Runs on its own |
Calls: Organization.find, then Organization.enrich, then Collection.query, then Audience.create.
About $1.55 a week, each time it runs, capped at $2.00.
Example: give it a goal
Tell me which property managers in my ICP started hiring a leasing coordinator this week, spend up to $2, and show me the plan first.
The plan it shows runs 5 steps, priced before it spends anything; Run it above shows the result it returns.
When something fails
Each failure, and what happens next
| When | Then |
|---|---|
| A trigger source fails on every route | That change kind is skipped for the week with a note; the other two still land. |
| A company already on the Audience fires again | Its row is updated with the new whyNow, never added twice. |
| Fewer than 10 hiring hits match in goal mode | The agent may widen to adjacent titles, such as “assistant property manager”, as a Decision with its cost; it never widens your sentence. |
| You call it twice in one ISO week | The second call returns the week’s hits at $0: it is idempotent per ICP, change and week. |
Each step retries three times, then falls through to the next route; one item's failure lands in skipped with its reason, never failing the call. Before a step would cross maxCost it stops and returns what it has, with a resume link. Each step's idempotency key is the call's key plus the step and the item: leaseline-icp-track-1-<step>-<item>.
Change it
| Ask | Compiles to |
|---|---|
| Write to the operations lead at each new hit within a day. | Prospect.reach |
| Also watch for property managers hiring an assistant property manager. | ICP.track |
| Only tell me about funding rounds over $1M. | ICP.track |
import { $, workflow } from 'startup-builder'
export default workflow({
name: 'icp-track',
verb: 'ICP.track',
input: { icp: 'string', changes: "('funding' | 'hiring' | 'technology')[]", roles: 'string[]' },
trigger: { schedule: 'mon 06:00' },
maxCost: 2,
execute: async (ctx, { icp, changes = ['funding', 'hiring', 'technology'], roles = ['leasing coordinator'], watch = 'audiences/audience_accounts' }) => {
const hits = []
if (changes.includes('funding')) hits.push(...(await ctx.step('funding', () => $.Organization.find({ icp, where: { event: { kind: 'funded', within: '7d' } }, maxCost: 1 }))).organizations)
if (changes.includes('hiring')) hits.push(...(await ctx.step('hiring', () => $.Organization.find({ icp, where: { hiringFor: roles, within: '7d' }, maxCost: 0.3 }))).organizations)
if (changes.includes('technology')) hits.push(...(await ctx.step('technology', () => $.Organization.enrich({ audience: watch, fields: ['events'], limit: 50, maxCost: 0.6 }))).changed)
return ctx.step('append', () => $.Audience.create({ name: 'Buying triggers', members: matchIcp(hits, icp), merge: true })) // emits each Event
},
})Extend it with extends: and base(), or compose your own from these steps.
Works with
Plays that order it: lead reactivation, Moment outreach, Objection watch.
It serves Find your first customers, and runs in Hands-on. It deepens Outbound.
For agents
For agents: the guide, its approvals, retries and lookups
| Fact | Value |
|---|---|
| Guide | ICP.track |
| Guide approval | limits |
| Goal | Tell me which property managers in my ICP started hiring a leasing coordinator this week, spend up to $2, and show me the plan first. It may change counts, the order of steps, soft filters and the route a read takes, and it stops early when the goal is met. It never relaxes your words, raises its own budget, answers its own approval, calls a Play or acts outside your standing approval. |
| Trigger | every('mon 06: |
| Retry | Three times with backoff, then the next route; the same idempotency key never charges, sends or posts twice |
| Idempotency key | leaseline-icp-track-1 |
| Lookups | A find: input asks unless exactly one record fits |
| Step |
|---|
| 1. Read the week’s funding rounds |
| 2. Read the week’s job posts for your roles |
| 3. Read what changed at the watched accounts |
| 4. Keep the hits that match your sentence |
| 5. Add them to the account Audience with why now |
The amounts live once, on the hub (approvals).
Who does each step, and how it is checked
| Step | Function | Doer | Checker | Assurance | Inputs |
|---|---|---|---|---|---|
| 1. Read the week’s funding rounds | code | Code | Code checks each result against its declared type | measured | $0.icp |
| 2. Read the week’s job posts for your roles | code | Code | Code checks each result against its declared type | measured | $0.icp, |
| 3. Read what changed at the watched accounts | code | Code | Code checks each result against its declared type | measured | $0.watch |
| 4. Keep the hits that match your sentence | code | Code | Code checks each result against its declared type | measured | $1, |
| 5. Add them to the account Audience with why now | code | Code | Code reads the result back from where it landed | measured | $4.hits |
The doer is never the checker, and the weakest assurance on the path is the whole call’s.
Under the hood
Under the hood: the Systems, Nouns and Events it touches
| Kind | What it touches |
|---|---|
| Systems | Ads |
| Nouns | Organization, Collection, Audience |
| Events | Collection.queried, Audience.created |
Reference
Inputs, outputs, its Event and its errors
| Name | Type | Default | Meaning |
|---|---|---|---|
icp | ICP | Required | Your saved customer sentence. |
changes | ('funding' | 'hiring' | 'technology')[] | ['funding', | The buying triggers to watch. |
roles | string[] | ['leasing coordinator'] | The job titles whose posting means the pain is growing: the role your product saves. |
watch | Audience | your account Audience | The accounts read for technology changes each week, 50 at a time, oldest-read first. |
every | string | '7d' | How often the feed reads. |
maxCost | number | 2.00 | The most this call spends each time it runs, in USD. It stops before a step would cross it and returns what it has, with a resume link. |
Emits ICP.tracked. Refuses with max-cost before it spends, and with the Data calls and Accounts groups (refusals).