Search documentation

Jump to any section of the Crispy docs

Guides

Post engagement campaigns

Find the people who reacted to or commented on LinkedIn posts about your topic. Review each name. Then put the people you approve in an invitation campaign.

How it works

Your agent pulls the people from a post and shows them to you. You approve the names. Your agent then puts only the approved people in a list and sets up a campaign for that list. The campaign stays off until you approve the launch.

  1. search_posts finds posts about your topic. You can also give your agent a post URL.
  2. list_post_reactions and list_post_comments pull the people who engaged.
  3. check_block_list removes people on your block list.
  4. manage_lists and import_data put the people you approve in a new list.
  5. upsert_campaign and manage_outreach set up the campaign. It stays off.
  6. preview_campaign_launch shows sample messages. Then confirm_campaign_launch starts the campaign.

You approve each step that writes data or contacts people. For the steps before launch, that approval is an instruction in the prompt, so your agent host must stop and wait for your reply. The launch is different. Crispy turns a campaign on only by consuming a launch_receipt from preview_campaign_launch. The receipt proves a preview of this exact config ran. It is not proof that a human read the preview.

The prompt

Paste this into your agent, then answer the three questions it asks.

You have the Crispy MCP tools connected to my LinkedIn account.

I want to invite people who reacted to or commented on LinkedIn posts about a topic.

Ask me for three things first.
  1. A keyword to search posts for, or the URL of a post I already have.
  2. A name for the list and the campaign.
  3. The invitation note. It must be 300 characters or less.

Then follow these steps. Stop after each step and wait for my reply.

1. If I gave a keyword, call search_posts with that keyword and limit 10. Show me
   a numbered list with the author, a one-line summary and the engagement counts.
   Ask me which posts to use. Do not choose for me.

2. For each post I choose, call list_post_reactions with limit 100 and
   list_post_comments with limit 100. If a result has a cursor and I ask for more,
   call the tool again with that cursor. list_post_comments returns top-level
   comments only.

3. Combine the people. Reactions give provider_id and profile_url. Comments give
   author_provider_id and author_profile. Remove duplicates. Remove anyone without
   a profile URL and any company page.

4. Read crispy_context for each person. Put a person in a KNOWN group if
   is_connection, invitation_pending or invitation_accepted is true. Put everyone
   else in a NEW group. Tell me that these flags cover only invitations sent
   through Crispy.

5. Call check_block_list without a linkedin_url to get my block list. Remove
   anyone who matches an entry. Tell me that this check can miss a blocked person.

6. Show me the NEW group with name, headline and profile URL. Ask me which people
   to include. Do not add anyone to a list until I approve the names.

7. Show me the list name and the approved people. Do not create the list until I
   approve it. After I approve, call manage_lists with action "create". Use the
   list.id from the manage_lists result as list_id in every later step. Then call
   import_data with target "contacts", that list_id and only the approved people.
   Give each person as { "linkedin_url": "<profile URL>" }. Report how many people
   were imported and how many were skipped.

8. Show me the campaign settings. Use kind "acquisition", my list, my note and 10
   invitations a day. Do not create the campaign until I approve the settings.
   After I approve, call upsert_campaign with the name, kind and list_id. Use the
   campaign.id from the upsert_campaign result as campaign_id in every later step.
   Then call manage_outreach with action "setup", that campaign_id, the list_id,
   daily_invites and invite_message. Do not pass enabled.

9. Call preview_campaign_launch. Show me every sample message and every warning.
   Keep the launch_receipt it returns. Do not lose it.

10. Stop. Tell me the campaign is ready but not live.

Rules for this whole conversation:
- Do not call confirm_campaign_launch until I approve the preview. When I
  approve, call it with the launch_receipt from that preview.
- Do not call manage_outreach with action "resume".
- Do not pass enabled true to any tool.
- If the campaign changed after the preview, if the receipt was already
  used, or if 15 minutes have passed, run preview_campaign_launch again and
  show me the new preview before you launch.

Approval

A campaign turns on only by consuming a launch receipt. preview_campaign_launch returns a single-use launch_receipt that lasts 15 minutes. confirm_campaign_launch checks that receipt. It refuses a campaign that changed after the preview, a receipt that was already used, and a receipt that has expired. manage_outreach with action "resume", or with enabled set to true, goes through the same gate and needs the same receipt. The receipt proves a preview of this exact config ran. It is not proof that a human read the preview. An agent can preview and confirm in two calls, so use an agent host that asks you before it calls a tool that writes data. Read each call before you allow it.

Preview, then launch

The invitation note is one template for the whole campaign. It can use {first_name}. It cannot name the post that each person engaged with.

preview_campaign_launch shows sample first-touch messages (10 by default, 50 at most). It also shows block list and duplicate hits for those samples. It is read-only. It sends nothing. It returns a single-use launch_receipt for the config it just previewed. The receipt lasts 15 minutes.

When you approve the preview, tell your agent to call confirm_campaign_launch with that launch_receipt. A campaign config turns on only by consuming a launch receipt from preview_campaign_launch. The launch refuses when no receipt is given, when the receipt does not match this campaign and account, when it was already used, when it has expired, and when the campaign changed after the preview. It also refuses when no list is bound to the campaign. It also refuses an acquisition campaign when more than 90% of the people on the list are already your connections. If the campaign changed after the preview, run the preview again and read the new preview before you launch. The receipt proves a preview of this exact config ran. It is not proof that a human read the preview.

Launch turns the campaign on and starts processing. It does not ask you again. Crispy then tries to invite eligible people on the list, on its schedule. It can defer or skip a person. Reasons include the daily pacing limits, an existing connection, a pending invitation, the block list, a failed eligibility check, a refusal from LinkedIn and a note that is too long. Any person on the list can get an invitation, so put only approved people on the list. Before each invitation, the campaign can view the person’s profile, and the person can see that view.

Why the prompt is shaped this way

Remove duplicates first. One person can react and comment on the same post, and can appear on several posts. Reactions call the ID provider_id. Comments call it author_provider_id.

Read the context flags. Each person carries a crispy_context block with is_connection, invitation_pending and invitation_accepted. The invitation flags cover only invitations sent through Crispy. Invitations you sent on LinkedIn yourself do not show. If Crispy cannot read these flags, a person can look new. Review the names yourself.

Check the block list. Crispy checks the block list before it sends an invitation. It can miss a person that you blocked by profile URL if Crispy has not matched that URL to the person. Review every name before you approve it.

Keep the launch for yourself. The prompt forbids each tool call that can start the campaign. Creating the list and the campaign sends nothing. After launch, Crispy can send invitations with no further approval, and you cannot take back an invitation that it sent.

Limits worth knowing

  • search_posts returns 1-25 results per call. Searches share a daily limit with search_people and search_companies (300 a day by default).
  • list_post_reactions returns 1-100 people per call, with a cursor for more.
  • list_post_comments returns 1-100 top-level comments per call (20 by default). Replies need a separate call with comment_id.
  • import_data skips a person without a LinkedIn profile URL.
  • daily_invites sets a daily maximum of 1-50 invitations. Crispy can send fewer.
  • A launch_receipt works once and lasts 15 minutes. If the campaign changed after the preview, the receipt is refused.

Variations

A competitor’s post. Pull the people who engaged with a competitor’s post. A reaction shows interest in that post. It does not show more than that.

Your own post. Many people may already be connections. An invitation does not apply to them, and an acquisition campaign skips them.

Repeat runs. Use a new list and a new campaign for each run. If you add people to the list of a live campaign, Crispy can invite them with no new preview.

See also the Campaigns guide for the two outreach modes and how sequences execute.