251
All workflows

Follow up on low NPS scores while they are fresh

Pulls low scores from your Typeform NPS survey, posts each with its comment and HubSpot owner to Slack, and drafts a reply.

Outcome

  • A Slack post for each detractor, with the score, the comment, the company and the owner.

  • A drafted reply for each detractor, for its owner to send.

  • A HubSpot note on each matched contact, and the emails that matched no contact.

How it works

  1. T

    Pull detractors, by Retrieve responses by Typeform

    Read the responses to survey submitted in the last lookback_days. Keep those with a score_field of 6 or less, with the email from email_field, the score and the comment_field answer.

  2. H

    Find their owner, by Search CRM records by HubSpot

    Search contacts by each email. Keep the contact ID, company name and hubspot_owner_id; note the emails with no contact.

  3. S

    Route it, by Post a message by Slack

    Post one message per detractor to cs_channel with the score, the comment, the company and the owner ID.

  4. Write the reply, by Your agent

    Draft a short plain-text reply for each detractor's owner to send that thanks them, restates their comment in one line and asks for 15 minutes. Show the drafts to the user.

  5. H

    Log it, by Create a note by HubSpot

    Add a note to each contact ID with the score, the comment and the approved reply.

You'll be asked for

  • The Typeform NPS survey, by name

    e.g. Quarterly NPS

  • The ref of its 0 to 10 question

    e.g. nps_score

  • The ref of its open question

    e.g. nps_reason

  • The ref of the email question, or the name of the hidden field that carries the email

    e.g. email

  • How far back to read responses

    e.g. 7

  • The Slack channel to post in

    e.g. #customer-success

nps-detractor-rescue.mdView markdown

Follow up on low NPS scores while they are fresh

Pulls low scores from your Typeform NPS survey, posts each with its comment and HubSpot owner to Slack, and drafts a reply.

Set up the tools below, then run the steps in order for the user, carrying each step's results into the next. The run is done when the user has the outcome below.

Outcome

  • A Slack post for each detractor, with the score, the comment, the company and the owner.
  • A drafted reply for each detractor, for its owner to send.
  • A HubSpot note on each matched contact, and the emails that matched no contact.

Inputs

Ask the user for these before you start.

  • survey: the Typeform NPS survey, by name, e.g. Quarterly NPS
  • score_field: the ref of its 0 to 10 question, e.g. nps_score
  • comment_field: the ref of its open question, e.g. nps_reason
  • email_field: the ref of the email question, or the name of the hidden field that carries the email, e.g. email
  • lookback_days: how far back to read responses, e.g. 7
  • cs_channel: the Slack channel to post in, e.g. #customer-success

Set up

Retrieve responses (Typeform, tool:typeform/retrieve-responses)

Use the API.

Note: Forms with more than 1,000 responses need narrower since and until ranges or the before and after cursors. Responses from the last 30 minutes or so may be missing: use a webhook for real-time leads.

HubSpot (tool:hubspot/search-crm-records, tool:hubspot/create-note)

For each call, use the first option your agent supports that lists it.

Notes:

  • Search CRM records: The MCP tool takes up to five groups of six filters and returns up to 200 records per page.
  • Create a note: hs_timestamp is required; attach the note to existing records with an associations object.
MCP (official, remote)

Add this server to your agent's MCP settings, then sign in when asked.

{ "mcpServers": { "hubspot": { "url": "https://mcp.hubspot.com" } } }
  • Search CRM records: call the MCP tool search_crm_objects
API (official)
  • Base URL: https://api.hubapi.com
  • Search CRM records: POST /crm/objects/2026-09/{objectType}/search
  • Create a note: POST /crm/objects/2026-09/notes
  • Auth: send the header Authorization: Bearer $HUBSPOT_API_KEY

Note: Use a service key or an app's static access token with the CRM scopes the calls need; paths carry a dated version such as 2026-09.

Post a message (Slack, tool:slack/post-message)

Use the first option your agent supports.

Note: Needs the chat:write scope. Over MCP it posts as the signed-in user; the API and CLI post as the app's bot.

MCP (official, remote)

Add this server to your agent's MCP settings, then sign in when asked.

{ "mcpServers": { "slack": { "url": "https://mcp.slack.com/mcp" } } }

Call the MCP tool slack_send_message.

CLI (official)

Install the command, then confirm it runs.

curl -fsSL https://downloads.slack-edge.com/slack-cli/install.sh | bash
slack --version

Run slack api chat.postMessage.

Set $SLACK_BOT_TOKEN in your environment first (get a key: https://api.slack.com/apps).

Before step 1, confirm access to each service with its cheapest read-only call, like a list or a search. Never send or change anything to test access.

Steps

  1. Pull detractors with Retrieve responses (Typeform). Read the responses to survey submitted in the last lookback_days. Keep those with a score_field of 6 or less, with the email from email_field, the score and the comment_field answer.
  2. Find their owner with Search CRM records (HubSpot). Search contacts by each email. Keep the contact ID, company name and hubspot_owner_id; note the emails with no contact.
  3. Route it with Post a message (Slack). Post one message per detractor to cs_channel with the score, the comment, the company and the owner ID.
  4. Write the reply yourself. Draft a short plain-text reply for each detractor's owner to send that thanks them, restates their comment in one line and asks for 15 minutes. Show the drafts to the user.
  5. Log it with Create a note (HubSpot). Add a note to each contact ID with the score, the comment and the approved reply.

Rules

  • Use only the services set up above. The read-only calls they need, like listing ids or polling for results, are fine.
  • Ask the user before anything that sends messages, costs money, or changes data, and say how many records it touches. One approval covers a batch the user has seen.
  • Never print API keys.