AgentChatInstagram AgentChat

AgentChat turns comments under your Instagram reels into DMs, followers and leads. You talk to it through your AI assistant (Claude, ChatGPT, Codex), through the REST API or in the dashboard. It only uses the official Instagram API.

Connect

There are two ways in. Both only see the data of your own Instagram account.

Way 1: connector with login (recommended)

Add this URL once as a connector. Your assistant opens a login page, you log in with Instagram and allow access. There is no key to copy.

https://agentchat.georgkinzel.de/mcp
  • Claude.ai and the Claude apps: Settings, Connectors, Add custom connector. Name AgentChat, URL as above.
  • Claude Code: claude mcp add --transport http agentchat https://agentchat.georgkinzel.de/mcp, then run /mcp and choose AgentChat to log in.
  • ChatGPT: custom connectors need developer mode (Settings, Connectors). Add a connector with the URL above and authentication OAuth.
  • Codex: codex mcp add agentchat --url https://agentchat.georgkinzel.de/mcp, then codex mcp login agentchat.

Then ask: “Check the status of AgentChat.” Connected apps are listed in your dashboard under Settings, Assistant, where you can revoke each one.

Way 2: API key

For everything without OAuth: n8n, Make, scripts, the REST API and MCP clients that can send a header. Create the key in your dashboard under Settings, Assistant, API key. It is shown once, right after it is created, and only stored as a hash. Lost it? Generate a new one, the old one stops working at once.

Always send it as a header, never in a URL:

Authorization: Bearer <your API key>
  • REST: curl -H "Authorization: Bearer $KEY" https://agentchat.georgkinzel.de/api/v1/status
  • MCP with a header: URL https://agentchat.georgkinzel.de/mcp plus the header above. In Claude Code: claude mcp add --transport http agentchat https://agentchat.georgkinzel.de/mcp --header "Authorization: Bearer $KEY"

Quick start

One sentence to your assistant is enough:

Set up the keyword GUIDE for my latest reel. Reply under the comment with three variants, send the link only to followers, the link is https://example.com/guide.

The assistant finds the reel with list_posts, creates the automation with create_automation and shows you a preview of every message. Ask for preview_automation to see the link check as well. If comments are already there, it can answer them with run_automation_on_existing_comments (a dry run comes first).

Automations

Triggers

  • comment: a comment under a post or reel. Limit it to posts with media_ids, or leave it empty for all posts.
  • dm: a direct message.
  • story_reply: a reply to one of your stories.

Keywords are case insensitive. match_mode decides how they match: word (default), contains, exact or any (every text).

What a follower gets

  1. A public reply under the comment, picked at random from public_replies.
  2. A DM. Without follower check and without opening_button it already holds the link.
  3. With follower check: the DM has a button. Instagram only allows the follower check after the person wrote or tapped a button, so the tap comes first.
  4. Not following yet: gate_text with a button to check again. After 3 checks the link goes out anyway, because Instagram sometimes reports fresh follows late.
  5. The link DM with up to two more link buttons (extra_links). Clicks are counted through a redirect unless track_clicks is off.

Email

With email_gate the automation asks for the email before the link. An email in the reply is stored on the contact. A reply without an email gets email_retry_text once; after the second miss the link goes out anyway. A run waits 72 hours for the answer. Contacts with a stored email are not asked again (email_skip_if_known). For comments the email question is the one private reply and replaces the button DM. Optional webhook_url gets a POST on email_captured and link_sent, signed with webhook_secret if set.

Reminder

follow_up_text plus follow_up_minutes sends one reminder with the link to people who did not click. It only works inside the 24 hour window, so the maximum is 1380 minutes.

Next post

Reel not online yet? Use next_post: true. The automation waits and attaches itself to your next post, at most 2 minutes after you publish it.

Automation fields

ParameterTypeMeaning
namestringInternal name, e.g. 'Reel 16.10. VAULT'
activebooleanActive (default true)
triggerstring: comment, dm, story_replycomment = comment under a post/reel, dm = direct message, story_reply = reply to a story
media_idsarray or nullcomment only: IDs of the posts/reels (from list_posts). Empty/null = all posts
next_postbooleancomment only: wait for the next new post/reel and attach to it automatically (at most 2 minutes after posting). Ideal when the reel is not online yet
keywordsarray of stringTrigger words, case-insensitive
match_modestring: word, contains, exact, anyword (default): word appears in the text. contains: substring anywhere. exact: whole text = word. any: every text
exclude_keywordsarray of stringDo not trigger if one of these words appears
public_repliesarray of stringcomment only: replies under the comment, one is picked at random. E.g. ['Sent you the link {username} 📩']. Empty = no public reply
opening_textstringFirst DM with button (default: "Hey {username}! Tap the button and I'll send you the link.")
opening_buttonstringButton of the first DM (default with follower check: "Send link"). Without follower check and without opening_button the link goes out in the first DM
follow_gatebooleanLink only for followers. Non-followers get gate_text with a button to check again
gate_textstringText for non-followers (default: "Almost there! Follow me real quick, then tap the button again and the link comes right away.")
gate_buttonstringButton to check again (default: "I follow you now")
link_urlstringTarget link (https://...)
link_textstringText of the DM with the link (default: "Here's your link 👇")
link_buttonstringTitle of the link button (default: "Open")
extra_linksarray of objectUp to 2 more link buttons in the link DM
follow_up_textstringReminder for people who did not click the link, e.g. 'Did you check it out yet? 👀'. Sent once, with the link button, only inside the 24h window
follow_up_minutesintegerMinutes without a click before the reminder (e.g. 120). 0 = off, max 1380
email_gatebooleanAsk for the email before sending the link (default false). See the server instructions for the order with comments and follow_gate
email_textstringEmail question (default: "Quick one: which email should I send it to? 📩")
email_retry_textstringSent once if the reply contains no email; after the second miss the link goes out anyway (default: "Hm, that didn't look like an email. Just type it in here 🙂")
email_skip_if_knownbooleanSkip the email question for contacts with a stored email (default true)
webhook_urlstring or nullOptional https URL that gets a POST on email_captured and link_sent. No private or local addresses. null = off
webhook_secretstring or nullOptional secret; the body is signed as header X-AgentChat-Signature: sha256=<HMAC-SHA256 hex>. Never shown again in responses
track_clicksbooleanCount clicks through our own redirect (default true)
tagsarray of stringTags the contact gets
once_per_userbooleanEach user gets this automation only once (default true)
priorityintegerHigher number wins when several match (default 0)
notesstringNote
skip_if_answeredbooleancomment only: skip the comment if your account already replied to it without AgentChat, e.g. ManyChat (default true). The run gets state skipped_other_tool

Placeholders in texts: {username} and {name}. Button titles up to 20 characters, DM texts up to 640.

Preview and go live

preview_automation shows how an automation looks for a follower: the public reply, every DM with its buttons and the link. It also checks the link live (HEAD request, GET if the server refuses HEAD, 5 seconds; private addresses are not fetched) and flags broken links.

Imported automations start as drafts. Drafts answer nothing. Check the preview, then switch them on with go_live (single ids, one import batch or all drafts). The dashboard shows the same preview as a chat for every draft.

Save the link for a comment keyword once with set_keyword_link (list_keyword_links shows all). suggest_automations_from_posts then fills in the link when it finds the keyword in a caption.

Switch from ManyChat

The goal: no reel goes quiet during the switch and nobody gets the same DM twice. Fastest way in Claude Code: install the plugin and type /agentchat:manychat. Claude tells you first what it needs (Claude in Chrome on, logged in to ManyChat) and then walks you through. The full guide is on Switch from ManyChat.

  1. Connect AgentChat. Keep ManyChat running.
  2. Export from ManyChat, read only: a browser agent reads your automations (MCP prompt manychat_migration_prompt or the script in the skill) and your contacts (CSV, see below). Or paste screenshots or a list, or let suggest_automations_from_posts read your captions.
  3. import_automations with dry_run: true shows the post it found for each entry, warnings and errors. With dry_run: false every valid entry is created as a draft.
  4. Check preview_automation for every draft and import the contacts.
  5. go_live. While ManyChat is still connected, AgentChat skips comments ManyChat already answered.
  6. Remove ManyChat in the Instagram app: Settings, App and website permissions, Apps and websites, ManyChat, Remove. That stops all ManyChat automations at once. You can connect it again in ManyChat any time.
  7. finish_migration with confirm_manychat_disconnected: true switches on follower check and buttons. Then the gap_fill calls (run_automation_on_existing_comments with since_minutes: 30) answer comments from the switch that nobody answered.

Contacts and DM history

Your contacts move with you, including where they came from. The DMs themselves live at Instagram, so AgentChat loads them from there.

  1. ManyChat has no CSV export for contacts. A browser agent (Claude in Chrome, Codex) reads them from the ManyChat web app, read only, and saves a CSV after your OK. The script is in the AgentChat skill. It changes nothing in ManyChat.
  2. import_contacts with the CSV text (or a JSON list). The dry run comes first and counts new, updated, skipped and errors, with examples.
  3. Column names are matched loosely: Instagram Username, ig_username or username; Instagram ID, ig_id or user_id; First Name, Last Name, Full Name, Email, Phone, Tags, Subscribed or Opt-in date, Last Interaction, Status. Other columns become custom_fields. Invalid emails are skipped and listed.
  4. Origin: a tag like link_clicked (<date>) or an automation or widget column becomes the contact's source and marks the contact as clicked. If an AgentChat automation has the same name or keyword, the contact is linked to it; otherwise pass source_map.
  5. Existing contacts are matched by Instagram ID, else by username (case does not matter). The Instagram ID from ManyChat is the same one AgentChat sees, so new contacts are linked right away. AgentChat only fills empty fields and adds tags, it never overwrites. Run it with dry_run: false when the numbers look right.
  6. backfill_conversations then reads your Instagram conversations (read only) and saves the messages on the contacts, skipping messages it already has. It runs in the background in small steps; status shows the progress under backfill. Every contact shows the conversation in the dashboard.

Limits from Meta: Instagram returns details only for the 20 most recent messages of each conversation, and conversations in the Requests folder that were inactive for 30 days are not returned (Conversations API, checked on 18 October 2026). Imported contacts without an Instagram ID that AgentChat has seen get linked as soon as they comment or write, or when the backfill finds their conversation: ManyChat's Instagram ID is the same one the Instagram API gives AgentChat (checked on 12 shared contacts), so contacts with an ID are linked right away; contacts without one are linked by username.

Transition mode

While ManyChat is connected it owns your conversations, and AgentChat may only send the one private reply to a comment. Imported automations therefore start in transition mode: the link goes out directly in that reply. Follower check, button, email question and reminder are saved as target settings. DM and story automations start paused. finish_migration switches everything to the target settings. Instagram has no API that tells whether ManyChat still owns your conversations, so without the confirmation it only shows what would change.

Protection against double DMs

Instagram allows exactly one private reply per comment. Before AgentChat answers a comment it reads the replies under it. If your account already replied and that reply did not come from AgentChat (for example from ManyChat), AgentChat sends neither the public reply nor the DM and marks the run as skipped_other_tool. If Meta rejects the private reply because the comment was already answered, that also counts as skipped. If the reply list cannot be loaded, the automation runs as usual. This is skip_if_answered, on by default. stats counts skipped_other_tool separately.

Old ManyChat buttons

People keep tapping buttons from old ManyChat messages after the switch. AgentChat matches such a tap (or a reply that is exactly an old button text such as “Link schicken” or “ich folge jetzt”) to the comment automation of the person's last comment within 7 days, remembers the button for the next person if that person commented on only one post and continues with follower check and link. You see legacy_tap_resolved in the activity. If nothing matches, the activity shows unhandled_button or unhandled_dm and the operator is notified. The same tap arriving twice (webhook and polling) sends only one message.

Thread owner and follower check

A follow up message that fails with “not the thread owner” means another app (often ManyChat, sometimes an older Meta app) owns the conversation. You see thread_owner_blocked in the activity and a warning in status and dashboard until finish_migration ran. That is why follower check and email only switch on after the migration is finished.

On “not the thread owner” AgentChat tries once to take over the conversation and then sends the message again once. Meta documents the takeover only for Facebook Page logins, so on accounts where Instagram rejects it, AgentChat remembers that and does not try again. Then the operator gets the contact and the link to send by hand.

Reel scheduling

Your assistant can publish a reel now or at a set time and attach a comment automation to exactly that reel. The server operator has to switch publishing on; status shows it under publishing.

  1. upload_video returns a one time upload URL (1 hour, MP4 or MOV). Upload with curl -T reel.mp4 -H "Content-Type: video/mp4" <upload_url>. Or skip this and pass a public video_url.
  2. schedule_reel with video_id or video_url, caption, publish_at (now or ISO time with time zone) and optional automation.
  3. The server checks Instagram's daily publishing limit first (get_publishing_limit) and publishes at most 2 minutes after the set time. Uploaded files are deleted right after publishing, cancelling or failing.
  4. list_scheduled and cancel_scheduled show and cancel.

If status shows publishing.permission as missing or unknown, log in with Instagram once more on /start and allow publishing.

REST API

The MCP tools as REST endpoints (all except check_follower, subscribe_webhooks, refresh_token and billing_status, which are MCP only) under https://agentchat.georgkinzel.de/api/v1, with your API key as Bearer header. The full description is openapi.json (OpenAPI 3.1, no key needed).

curl -H "Authorization: Bearer $KEY" https://agentchat.georgkinzel.de/api/v1/automations
curl -X PATCH -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" -d '{"active":false}' https://agentchat.georgkinzel.de/api/v1/automations/3
curl -H "Authorization: Bearer $KEY" "https://agentchat.georgkinzel.de/api/v1/export/contacts?format=csv"

Errors always come as {"error": "..."}: 400 validation, 401 missing or wrong key, 402 plan needed, 404 not found, 429 rate limit, 502 Instagram error.

MCP tools reference

Generated from the tool definitions of this server. Your assistant sees the same list.

status

Check the connection: Instagram account, token expiry, webhook subscription, counts, webhook URL, migration and publishing state; for the operator also health (degraded plus problems, as /health).

No parameters.

list_posts

Latest posts and reels with ID, caption, link, comment count and the automations attached to them.

ParameterTypeMeaning
limitintegerDefault 12, max 50

list_automations

All automations with short stats.

No parameters.

get_automation

One automation in full, including funnel numbers.

ParameterTypeMeaning
id (required)integer

create_automation

Create a new automation. Returns it plus a preview of the messages.

Plus every field from Automation fields.

update_automation

Change fields of an automation (only the given ones). Pause with active=false.

ParameterTypeMeaning
id (required)integer

Plus every field from Automation fields.

delete_automation

Delete an automation (history stays in the export).

ParameterTypeMeaning
id (required)integer

test_automation

Dry run: which automation would react to this text and which messages would go out? Sends nothing.

ParameterTypeMeaning
text (required)string
trigger (required)string: comment, dm, story_reply
media_idstring
followsbooleanAssumption for the follower check (default true)

run_automation_on_existing_comments

Apply an automation to comments that already exist on a post (only comments younger than 7 days, each comment only once). Default is dry_run=true: only shows who would get something.

ParameterTypeMeaning
automation_id (required)integer
media_id (required)string
dry_runboolean
limitintegermax comments, default 100
since_minutesintegerOnly comments from the last N minutes, e.g. 30 for the switch from ManyChat. Default: all younger than 7 days

list_comments

Comments under a post/reel. answered is true if your account replied under the comment or AgentChat sent something for it (reply or DM); answered_by says who: agentchat, other (for example ManyChat) or null.

ParameterTypeMeaning
media_id (required)string
limitinteger
only_unansweredboolean

reply_to_comment

Reply publicly to a comment.

ParameterTypeMeaning
comment_id (required)string
text (required)string

send_dm

Send a DM to a contact. Only works within 24 hours after their last message or button tap.

ParameterTypeMeaning
contact (required)stringInstagram ID or @username of the contact
text (required)string
link_urlstring
button_titlestring

check_follower

Checks live whether a contact follows the connected account (only works if the contact has written or tapped a button before).

ParameterTypeMeaning
contact (required)stringInstagram ID or @username of the contact

list_contacts

Filter and list contacts.

ParameterTypeMeaning
searchstringPart of the username
tagstring
followsboolean
has_emailbooleantrue = only contacts with an email, false = only without
clickedbooleantrue = only contacts that clicked a link, false = only those that did not
automation_idintegerOnly contacts that triggered this automation
sincestringLast active since (YYYY-MM-DD)
limitintegerDefault 50, max 500
offsetinteger

get_contact

One contact with all runs and the history.

ParameterTypeMeaning
contact (required)stringInstagram ID or @username of the contact

update_contact

Set tags, email or note of a contact.

ParameterTypeMeaning
contact (required)stringInstagram ID or @username of the contact
add_tagsarray of string
remove_tagsarray of string
emailstring
notesstring

activity

Latest events (incoming comments/DMs, sent messages, errors).

ParameterTypeMeaning
limitintegerDefault 50
kindstringe.g. comment_in, dm_in, button_in, dm_out, comment_reply_out, follow_check, email_captured, email_given_up, email_expired, webhook_out, webhook_error, error
automation_idinteger
contactstringInstagram ID or @username of the contact

stats

Funnel per automation: triggered, DM out, button tapped, at follower gate, asked for email, email captured, link out, clicked, errors.

ParameterTypeMeaning
daysintegerPeriod, default 30

export_data

Data export. With table the rows come back directly as CSV (up to 2000 rows). Without table it lists the tables and the REST download URLs (they need the API key as Bearer header).

ParameterTypeMeaning
tablestring: contacts, automations, runs, events, clicks, scheduled_posts, videos, messages
sincestringYYYY-MM-DD
inlinebooleanKept for compatibility: the rows of a table always come back inline

subscribe_webhooks

Subscribe the Instagram account to webhooks (comments, messages, messaging_postbacks). Call once after setup.

No parameters.

refresh_token

Extend the Instagram token by 60 days right now (otherwise runs daily automatically).

No parameters.

billing_status

Subscription of this account: plan, status, trial end, whether automations may send, and the upgrade link (subscribe or manage the subscription).

No parameters.

upload_video

Get a one-time upload URL for a reel video (MP4 or MOV). Upload the file with HTTP PUT within 1 hour, e.g. curl -T reel.mp4 -H "Content-Type: video/mp4" <upload_url>. Returns video_id for schedule_reel. The file is stored on the server only until the reel is published, cancelled or failed, at most 7 days. Instagram accepts reels with 3 s to 15 min and up to 300 MB. Needs the Node server; on Cloudflare pass video_url to schedule_reel instead.

ParameterTypeMeaning
filenamestringOptional original file name, only for your overview
content_typestring: video/mp4, video/quicktimeDefault video/mp4

schedule_reel

Publish a reel now or at a set time. Source: video_id (from upload_video) or video_url (public URL Instagram downloads itself). Checks the daily publishing limit first. Optional automation: same fields as create_automation (trigger is always comment); it waits like next_post and attaches to exactly this reel once it is published. Publishing happens at most 2 minutes after publish_at.

ParameterTypeMeaning
video_idintegerID from upload_video
video_urlstringPublic https URL of an MP4/MOV, instead of video_id. Must still work at publish time
captionstringCaption, max 2200 characters, 30 hashtags, 20 @mentions
publish_at (required)string'now' or ISO 8601 with time zone, e.g. 2026-10-20T18:00:00+02:00. Uploaded files: at most 7 days after the upload
cover_urlstringOptional public JPEG for the cover (wins over thumb_offset)
thumb_offsetintegerOptional cover frame in milliseconds from the start
share_to_feedbooleantrue = reel may also appear in the feed, false = Reels tab only. Default: Instagram's default
trialbooleanTrial reel: shown only to non-followers first; graduate it manually in the Instagram app
automationobjectOptional comment automation for this reel (same fields as create_automation)

list_scheduled

Scheduled, published, failed and cancelled reels of this account, newest first.

ParameterTypeMeaning
statusstring: open, published, failed, cancelled, allDefault open
limitintegerDefault 20, max 100

cancel_scheduled

Cancel a scheduled reel that is not published yet. The uploaded file is deleted right away. An attached automation stays paused (delete it with delete_automation if not needed).

ParameterTypeMeaning
id (required)integer

get_publishing_limit

Instagram's publishing limit for this account: posts published via the API in the last 24 hours, the maximum, and reels already scheduled for the next 24 hours.

No parameters.

import_automations

Bulk import for switching from ManyChat: all automations in one call. dry_run=true (default) only resolves the posts (permalink, caption part, media_id or next_post), validates and shows per entry what would be created plus warnings (post not found, keyword conflict, follower check and email need thread ownership). dry_run=false creates every valid entry (each on its own, invalid ones are skipped), by default as drafts with an import_batch: check preview_automation, then go_live. go_live returns the order to follow without a gap: the AgentChat automation is live, then pause it in ManyChat (checklist), then gap-fill the last 30 minutes with run_automation_on_existing_comments. transition_mode (default true while ManyChat is still connected): follower check, button, email and reminder are stored as target settings and switched on later by finish_migration; until then the link goes out directly in the one private reply.

ParameterTypeMeaning
automations (required)array of objectThe automations to import, e.g. read from ManyChat screenshots or from suggest_automations_from_posts
dry_runbooleanDefault true: only check and show, create nothing
start_pausedbooleanCreate them paused (default false). Then turn each one on with update_automation active=true
transition_modebooleanDefault true until finish_migration ran: run without thread-ownership features until ManyChat is disconnected
draftbooleanDefault true: create as drafts that answer nothing until go_live (check preview_automation first). false = live right away

suggest_automations_from_posts

Scans the captions of the latest posts for comment-keyword calls like 'Comment GUIDE', 'Kommentier KI', 'Kommentiere „VAULT“', 'type AI' or 'DM me AUDIT' and suggests one automation per post. Posts that already have an AgentChat automation are flagged. import_input can be passed straight to import_automations; link_url is taken from the keyword link library or a URL in the caption, otherwise null (add the link first).

ParameterTypeMeaning
limitintegerNumber of latest posts to scan, default 12, max 50

finish_migration

Ends the transition mode after ManyChat is disconnected in Instagram (Settings → App and website permissions → Apps and websites): switches every automation in transition mode to its target settings (follower check, button, email, reminder, DM automations on). Instagram has no API that tells whether ManyChat still owns your conversations, so without confirm_manychat_disconnected=true this only shows what would change.

ParameterTypeMeaning
confirm_manychat_disconnectedbooleantrue = ManyChat is disconnected in Instagram, switch now
automation_idsarray of integerOptional: only these automations

Keyword link library for caption suggestions: keyword → link. url null removes the keyword.

ParameterTypeMeaning
keyword (required)string
urlstring or nullhttps://... or null to remove

All entries of the keyword link library.

No parameters.

preview_automation

Shows how an automation looks for the follower: public reply under the comment, every DM with its buttons and the link, plus a live link check (HTTP status, broken links are flagged). Works for drafts. In transition mode it also shows what changes after finish_migration.

ParameterTypeMeaning
id (required)integer

go_live

Switch drafts live: one or more automation_ids, every draft of one import (import_batch) or all drafts (all_drafts=true). Returns link checks and the order without a gap: live now, then pause in ManyChat (manychat_pause_checklist), then the gap_fill calls.

ParameterTypeMeaning
automation_idsarray of integer
import_batchstringFrom the import_automations result
all_draftsboolean

import_contacts

Import contacts from ManyChat as CSV (ManyChat has no export: a browser agent reads them with the AgentChat skill script) or from a JSON list. Column names are matched loosely (Instagram Username / ig_username / username, Instagram ID / ig_id / user_id, First Name, Last Name, Full Name, Email, Phone, Tags, Subscribed / Opt-in date, Last Interaction, Status, custom fields). Tags like 'link_clicked (<date>)' and automation or widget names become the contact's source and mark it as clicked; a source is linked to an AgentChat automation with the same name or keyword (or via source_map). Matches existing contacts by Instagram ID, else by username (case-insensitive) and only fills empty fields and adds tags, never overwrites. dry_run (default true) shows counts new / updated / skipped / errors with examples. Emails are validated.

ParameterTypeMeaning
csvstringText of the CSV export (first row = column names)
contactsarray of objectInstead of csv: list of contact objects with the same field names
dry_runbooleanDefault true: only count and show examples, change nothing
source_mapobjectOptional: ManyChat automation name or tag → AgentChat automation id, e.g. {"Agent vault copy 4": 12}

backfill_conversations

Load the DM history from Instagram (read only, sends nothing): reads your conversations page by page with the 20 most recent messages each, saves them on the contacts (creates missing contacts with their username) and skips messages it already has (message ID). Runs in steps in the background every 2 minutes; progress is in status.backfill. Instagram only gives the 20 most recent messages per conversation.

ParameterTypeMeaning
max_conversationsintegerStop after this many conversations (default 1000, max 10000)
restartbooleanStart again from the newest conversation even if a backfill is running
cancelbooleanStop a running backfill. Loaded messages stay

Prompts

  • manychat_migration_prompt: Prompt for a browser agent that reads ManyChat without changing anything and imports into AgentChat as drafts.
  • migrate_from_manychat: Guided move from ManyChat: say what is needed, export automations and contacts, drafts with preview, go live, remove ManyChat in Instagram, finish_migration.
  • new_reel_automation: Create a comment keyword automation for one reel (posted or next), with preview and link check before it goes live.

Limits

Instagram

  • One private reply per comment, only up to 7 days after the comment.
  • More DMs only within 24 hours after the person's last message or button tap.
  • The follower check only works after the person wrote or tapped a button.
  • Button titles up to 20 characters, DM texts up to 640 characters.

Sending limits per account

To protect all accounts from being flagged as spam, each account sends at most 300 messages (DMs plus comment replies) per hour and 3000 per day, during the free trial 60 per hour and 300 per day. Private replies to comments over the limit, or blocked by an Instagram rate limit, are not lost: they wait and go out automatically within the 7 days Instagram allows.

Rate limits of this server

AreaRequestsWindow
Login pages (/start, /connect, /auth/callback, /oauth/authorize) per IP10per minute
REST API per account120per minute
REST API per IP300per minute
REST API writes (POST, PATCH, PUT, DELETE) per account30per minute
MCP per account120per minute
MCP per IP300per minute
Wrong keys per IP (then the IP is locked for a while)20per minute
Dashboard forms per account60per minute
Reel uploads per account10per hour
OAuth client registration per IP30per minute
OAuth token requests per IP300per minute

Over the limit you get 429 with Retry-After in seconds.

Troubleshooting

  • Nothing happens on a comment: ask for status. Check that webhooks are subscribed (otherwise subscribe_webhooks), that the automation is active and not a draft, and use test_automation with the comment text.
  • The DM with the link never arrived: look at activity. Instagram rejects DMs outside the 24 hour window; the person has to write or tap a button first.
  • “not the thread owner” or thread_owner_blocked: Another app (often ManyChat, sometimes an older Meta app) owns the conversation. Remove it in Instagram (Settings, App and website permissions, Apps and websites) or in Meta Business Suite under conversation routing, then run finish_migration. If only single threads are blocked while others go through, it does not have to be ManyChat: look for an older Meta app.
  • Runs show skipped_other_tool: your account had already answered that comment without AgentChat. This is the double DM protection working.
  • Connection shows token_invalid: log in with Instagram again on /start. After the login AgentChat catches up on its own: comments from the outage (Instagram allows a private reply up to 7 days), runs that stopped and DMs from the last 23 hours. The activity shows recovery_done with the numbers, recovery_not_possible for what was too old.
  • list_comments shows answered_by: agentchat means AgentChat replied or sent the DM, other means your account replied without AgentChat (for example ManyChat).
  • Your assistant says the token is invalid or expired: reconnect the connector. A wrong API key gives 401; too many wrong keys lock the IP for a while.
  • A tool answers that AgentChat is paused: the free trial ended or the payment failed. Choose a plan on your plan page. Reading and exporting keep working.

Skills for Claude and Codex

Ready-made workflows for your assistant: connect, switch from ManyChat, a new reel, stats, scheduling and troubleshooting. They ask before anything goes live or reaches real people. Source: https://github.com/epictaste/agentchat-skills

  • Claude Code: /plugin marketplace add epictaste/agentchat-skills, then /plugin install agentchat@agentchat. This also adds the AgentChat connector. Or paste the prompt from the home page and Claude installs it. Short commands: /agentchat:manychat and /agentchat:reel.
  • Any agent with Agent Skills, including Codex: npx skills add epictaste/agentchat-skills
  • Claude.ai: download the folder plugins/agentchat/skills/agentchat from the repository as a ZIP and upload it under Settings, Capabilities, Skills.