Instagram messages scored every 4 hours to help the team choose the best leads

In this pilot, the software read recent Instagram conversations and ranked each new lead. Good leads became tasks in ClickUp, the team's task list, with a score, a reason and the full chat. Setters, the people who book sales calls, decided whom to contact; the software sent no messages.

Client: Ascend StudioAgencies · Sales through Instagram messages

CreditDesigned and built by our founder, as lead developer for a partner agency.

From inbox to task list

Each lead comes with a reason for its score

The list ranks the leads, and the setter decides whom to contact.

Lead task list

Known profiles stop before paid lookups. New leads score 82 Hot, 71 Warm and 58 Cold. A score of 34 creates no task. The engine creates tasks, not outgoing messages.

50 is the task threshold. Followers must also be above zero. Hot: 80–100. Warm: 65–79. Cold: 50–64.

Look inside a lead task

See why each lead got its score

Choose a lead to see its reason and context.

Why this score?

Agency founder asking about onboarding, with a business website.

High confidence
Latest message
“What does your team do for onboarding?”

Service suggestionsNew-client setup · Customer records · Follow-up tasks

Why this score?

A relevant follow-up need, but the scope and buying timeline are unclear.

Medium confidence
Latest message
“Could this help with my client follow-up?”

Service suggestionsFollow-up tasks · Client forms · Booking setup

Why this score?

A business profile with general interest, but no clear project yet.

Low confidence
Latest message
“Just exploring options for my team.”

Service suggestionsProcess review · Client forms · Customer records

About Ascend Studio

The founder's Instagram audience sent many messages, and setters needed to know which to answer first.

Ascend Studio's conversations came from three places: automatic replies sent when someone commented on a post, people writing in directly, and messages the team sent first. Setters worked in ClickUp and booked calls from there. An older scoring setup, built in the automation tool n8n, needed a replacement that was easier to change, test and fix.

Client
Ascend StudioA founder-led AI automation studio that sells through Instagram messages
Industry
AI automation services
Sales motion
High-value sales calls booked from Instagram messages
Team task list
ClickUp

The problem

Serious questions were mixed in with automatic replies and fans

  • Different kinds of messages arrived together

    Replies to comment bots, fans and serious questions arrived in the same inbox. A new message alone did not show whether someone was a good fit.

  • The real Instagram username was often missing

    The message service often gave a display name. Paid profile lookups needed the person's real Instagram username.

  • The old setup was hard to fix

    The team wanted proper code that could be tested, could retry failed steps and could score earlier conversations again.

What was built

Each lead arrives with chat history and a reason for its score

  • Identity

    Several messages become one lead

    Messages already seen are dropped, and new messages are grouped by person. If the person is already in ClickUp, the job stops before any paid lookup.

  • Context

    The score uses more than the last message

    Profile details, a summary of their website and the last 10 messages inform the score, its reason and how confident it is.

  • Retry

    Failed steps try again

    Each step gets 3 attempts, with a longer wait each time. Every run records the chats it read, duplicates, skipped usernames and queued jobs.

  • Recovery

    The list can be rebuilt

    A reset job refills ClickUp from the last 30 days. Past conversations saved in a spreadsheet file (CSV) can be scored again the same way.

Control and safety

A ranked task helps a person decide, and nothing is sent automatically

The software reads messages and writes tasks. A setter decides whom to contact and what to say. Each score is the AI model's judgement, shown with a reason and a confidence level so a person can check it.

  • Only scores of 50 or more become tasks. A lead needs a score of at least 50 and more than zero followers to reach ClickUp. Lower scores create no task, but the messages are still stored.
  • The person is identified before paid lookups. Leads without a real username are skipped. Seen messages and existing profiles are checked, and ClickUp is checked again just before a task is created.
  • Each run has a limit. Each run reads up to 500 recently active chats, with up to 100 messages each. It queues at most 400 leads, in batches of 100.
  • A second check makes duplicate tasks less likely. ClickUp is checked again before each task is written. This makes duplicates from jobs running at the same time less likely, but it is not a guarantee.

For technical readers

How the system works

Three jobs run in order. One collects messages, one adds profile and website details, and one scores each new person. BigQuery, a database, stores the messages already seen and where the next run should start. ClickUp gets a task only after the score and follower checks pass.

Recent Instagram chatsEvery 4 hours · Unipile
Keep new messagesBigQuery checkpoint + IDs
Profile + websiteApify + Tavily
Score with a reasonLast 10 messages + context
ClickUp taskScore ≥50 and followers >0
No taskBelow the task threshold

Dashed lines show supporting connections, or parts that are paused or not yet built.

In more detail

Technology used (8 parts)Each part of the system, and why it was chosen.
LayerTechnologyWhy it was chosen
Jobs and scheduleTrigger.dev v3 · TypeScriptRuns scheduled tasks with retries and a run history, without a separately managed queue.
Instagram message dataUnipile APIReads chats, messages and participant details one page at a time, within a chosen period.
StateBigQueryStores seen message IDs and the checkpoint for the next run.
Profile contextApifyReads the public profile's followers, bio, badge and website link.
Website contextTavilySummarises the business behind a website link.
ScoringGPT-5.1 through OpenRouterReturns structured scores, confidence and reasons from profile, website and conversation context.
Team workspaceClickUp APICreates a task with 12 custom fields where the setters already work.
Validation and checksZod · ESLint · Prettier · manual scriptsChecks that incoming data has the expected fields and checks code quality. Five manual scripts cover the core paths; no automated suite is recorded.
5 engineering decisions that matteredThe problem, what was done, and what it changed.
  1. Read beyond the first page of chats

    An early version repeatedly returned the same 250 chats. The replacement reads successive pages through an Instagram-specific connection and saves where to resume. This replaced a sort option that did not work and a request that read only the first page.

  2. Sort by activity before keeping 500

    The API did not return chats newest-first. The job now fetches a wider window, sorts it itself and takes the most recently active 500.

  3. Make the checkpoint visible in the logs

    A timestamp conversion bug marked all 4,377 messages in one run as duplicates. BigQuery timestamp objects are now converted to ISO strings, and the value used is logged.

  4. Find the real username before paying for profile details

    The job reads the chat attendee record for the real Instagram username (the handle), then tries a four-rule cleanup. If neither works, the lead is skipped before any paid lookup.

  5. Leave space in the queue

    The platform queue limit was 500 jobs. Each run queues at most 400 leads in batches of 100, with a pause between batches and a final ClickUp check before task creation.

Testing and build recordHow it was tested, and the build by the numbers.

Quality and reliability

  • Five manual check scripts cover finding usernames, duplicate and classification logic, conversation types, a full pipeline run and live service connections. The source records no automated test suite.
  • Zod validates chats, attendees, messages and the internal lead payload.
  • Failed steps have 3 attempts, with waits growing from 1 to 10 seconds and random variation. Tasks can run for up to an hour.
  • Run logs record fetched chats, new and duplicate messages, skipped usernames and queued jobs. Reset and CSV replay jobs support recovery.

By the numbers (build)

  • 45 commits over 50 days, from 16 October to 5 December 2025. Built in about 7 weeks.
  • 7 connected services and 6 Trigger.dev tasks, including CSV replay and list reset.
  • About 2,300 lines of TypeScript across 3 jobs and 6 service modules.
  • 4 schedule changes before settling on a 4-hour interval, tuned against recorded runs.
  • The earlier workflow's 3,567 scored conversations included 121 hand-marked examples. Replay tooling was built; a completed replay is not claimed.

Is it a fit?

Could this work for your team?

  • Your sales calls start in Instagram messages. Setters at a coaching, education or agency business work through an inbox and book calls for closers, the people who run the sales call.
  • Your inbox mixes different kinds of messages. Replies to comment bots, direct questions and your own outreach all arrive together.
  • You want the reason behind a score. A setter needs the conversation and business context before deciding what to say.
  • Your team has its own idea of a good lead. The scoring and the task list can be adapted. Assigning leads, alerts for hot leads and updating existing tasks would be extra work.

Which conversation should your setters open first?

Conducted by Apurva · Not a sales call