> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Meta comment-to-DM private replies

> Wire a Meta (Instagram / Facebook) automation so a public comment triggers a one-shot private DM reply routed into the Inbox — from comment-webhook ingestion through HMAC signature verification to the published comment_received flow trigger.

# Meta Comment-to-DM Private Replies

A comment-to-DM automation turns a public Instagram or Facebook comment into a private conversation: the moment a comment matches your rules, Orbit sends one private reply direct message to the commenter and opens that DM thread in the omnichannel Inbox. The public thread stays public, but the actual answer happens one-to-one.

This guide walks the full loop — register/connect the channel, ingest comment events, verify the webhook signature before any auto-reply, build the flow that replies, and understand the guardrails that keep the automation compliant.

## 1. When you'd use it

Reach for comment-to-DM when a public thread is about to spiral and the useful answer should not happen under the post:

* **Runaway comment threads** — a complaint, a "DM me the discount code" giveaway, or a shipping question that everyone in the thread asks one at a time. A private reply moves the question to a 1:1 thread where an agent (or an AI agent) can resolve it without the whole thread watching.
* **Comment marketing triggers** — "comment SEND to get the link" and a DM with the link arrives; the classic ManyChat-style growth play. Orbit fires the first matching flow's reply once per comment, so the lead capture always routes into the Inbox for follow-up.
* **Moderation triage** — a keyword-filtered auto-reply ("comment contains `cancel` → DM: here's the self-service link + a human will follow up") plus an inbox thread means the triage surface is one queue, not a public multi-person pile-on.

If the public content itself can stay public (a simple FAQ-style answer), a regular inbox reply on the post's comment thread is lighter — comment-to-DM is for when you want the conversation off the public stage.

## 2. Connect the Meta channel (the agent registration step)

Before any comment event can drive a reply, Orbit needs a connected Meta identity to send from.

* **Facebook (Page) comments** — connect a Facebook Page you administer under **Channels → Messenger**. The Page access token Orbit captured at OAuth time is what signs each private reply.
* **Instagram (Professional account) comments** — connect an Instagram Business or Creator account under **Channels → Instagram**. See the [Instagram onboarding playbook](/guides/instagram-onboarding) for the exact prerequisites (Business/Creator account, linked Facebook Page, Page admin). Replies are sent through the same Messenger Platform plumbing the regular Instagram DM channel uses.

The connected account is the "agent" the page → DM bridging uses. When a comment event arrives, Orbit resolves the connected account for the commented Page / professional account, picks up that account's token, and sends the reply through it — this is the path the runtime walks rather than a separate registry you maintain by hand. If no connected account covers the Page that owns the comment, the flow logs `not_configured` instead of guessing.

The registration surface at `POST /api/v1/channels/amb/agents` exists for Apple Messages for Business (the related `amb` channel family) — if you also run Apple Messages, see the [Apple Messages for Business onboarding guide](/guides/apple-messages-for-business-onboarding). For Meta comment-to-DM the OAuth connect above is all that is needed.

## 3. Build the comment → DM flow

Comment-to-DM is configured as a **flow** with a `comment_received` trigger node. A flow is published in the Flow Studio; only published flows fire (a draft can never send a live DM).

1. Open **Automation → Flow Studio → New flow**, and add a **trigger** node whose trigger source is "comment received" (`comment_received`).
2. On the trigger node, configure:
   * **Post filter** — optional. Limit to specific post/reel ids; left empty, the flow fires for every public comment on the account.
   * **Keyword filter** — optional. Comma-separated keywords the comment must contain (case-insensitive); left empty, the flow fires for any comment.
   * **Reply message** — the DM body. Keep it under 1000 characters (Meta's DM body limit).
3. Publish the flow.

At ingest time Orbit reads the new comment, finds the published comment-trigger flows that match, applies post + keyword filters, and fires the **first** matching flow's reply. Matching is deterministic (most recently published first) so a comment never receives more than one auto-reply — Meta accepts exactly one private reply per comment, and Orbit enforces the same bound.

### What happens to the comment → DM thread

After the reply sends, Orbit routes the resulting DM into the omnichannel **Inbox** as a normal `social_mention`/DM thread. An agent (or an AI agent) picks it up there and continues the conversation; the private reply only opened the thread, it does not have to be the whole conversation.

## 4. Verify the Meta inbound webhook (HMAC before you trust)

The comment-to-DM flow fires **only** for inbound comment events that arrived through Meta's signed webhook channel. Meta signs every inbound event with `X-Hub-Signature-256` over the raw body using your app secret. Orbit re-checks that signature before the event ever reaches a flow trigger.

Operationally:

* Orbit's comment ingestion endpoint rejects missing or mismatched `X-Hub-Signature-256` with a 401 and logs the pattern for observability — the reject happens before any flow evaluation, so a forged "comment" can never trigger a DM.
* If you run your own **outbound** webhook consumer on `message.received` / social-listening events to mirror comment traffic into a warehouse, still verify Orbit's Standard Webhooks signature (the guide is [verify webhook signatures](/guides/verify-webhook-signatures)) before processing.
* A 401 on the inbound channel means Meta sent an unprocessable event (missing/wrong signature) — reconcile the app secret in **Channels → your Meta channel**, don't retry the trigger.

If you also poll Meta comments from a third-party listening provider, treat that ingest as untrusted until the provider's own signature passes; the same "verify first, auto-reply after" rule applies.

## 5. Guardrails — opt-out and one-shot parity with mass DM policy

Comment-to-DM is an automated DM, so it inherits Orbit's DM sending discipline rather than inventing a new one:

* **One reply per comment, no retries.** Even a crash-loop mid-send cannot stack multiple DMs onto one commenter; the one-shot bound is enforced by matching a single published flow and by Meta's own one-private-reply-per-comment rule. The flow's execution log (Flows → Executions) records what fired.
* **Opt-out honoured.** If the commenter ever opts out of DMs from your Page / professional account, Orbit's sends respect Meta's recipient block — the flow logs a `send_failed` outcome and the thread opens for a human instead of pretending the DM landed.
* **24-hour-style window discipline is not the bound here** — Meta gives comment private replies a **7-day window**, longer than the standard 24-hour DM rule. Orbit refuses the send (without burning the one allowed reply) if the comment's known `posted_at` is more than 7 days old, so an old comment sweep can't spam a "from the archives" DM.
* **Keywords and post filters keep the trigger civil.** Tighten the flow to the post ids / keywords you actually intend rather than auto-DMing every comment on the account.

Public policy (Meta's platform terms) still applies — a comment-to-DM automation on a giveaway or promo must comply with Meta's commerce/promotions rules on your Page.

## 6. Example: comment → flow evaluates → private reply opens the thread

Walk one event end to end:

1. A user comments `any discount codes?` on your post at 14:03 UTC. Meta pushes a `comments` webhook event to Orbit; the inbound handler verifies `X-Hub-Signature-256` and accepts.
2. The social-listening ingest normalizes the comment as an `instagram_comment` (or `facebook_comment`) mention and calls the comment-to-DM dispatcher.
3. The dispatcher scans **published** flows with a `comment_received` trigger; your flow ("Comment keywords → DM the discount link") matches because `discount` is in its keyword filter.
4. The dispatcher calls the private-reply service; Orbit checks the comment's `posted_at`, sees it is minutes old, and sends the DM: "Thanks for asking! Code ORBIT10 takes 10% off at checkout — or press 1 to talk to a human."
5. Meta returns the message id; the dispatcher records a flow execution ("comment\_to\_dm: ok") and the Inbox thread appears with the commenter as the contact.

Resulting Inbox view: a normal DM conversation, with the private reply as the first outbound message, ready for an agent to continue.

```jsonc theme={null}
// What the flow execution log actually records (one row per fired reply)
{
  "flow": "Comment keywords → DM the discount link",
  "trigger": "comment_received",
  "outcome": "ok",
  "message_id": "m_abc123...",
  "platform": "instagram_comment"
}
```

If your monitoring consumer listens on the flow execution event, `message_id` is the value you join to the Inbox thread for full-thread reporting.

## See also

* [Instagram channel page](/channels/instagram) — the send/receive contract for Instagram DMs
* [Messenger channel page](/channels/messenger) — the Facebook Page counterpart
* [Apple Messages for Business onboarding](/guides/apple-messages-for-business-onboarding) — sibling `amb` channel registration guide
* [Verify webhook signatures](/guides/verify-webhook-signatures) — the Standard Webhooks scheme for your own outbound consumers
* [Instagram onboarding playbook](/guides/instagram-onboarding) — full connect prerequisites on the Instagram side
