Skip to main content

WhatsApp Thread Control

Developer guide: what your integration receives, sends and has to set up

When several responders share one WhatsApp number, Meta assigns every conversation to exactly one of them. Meta reports these changes to CM, and CM forwards them to your integration on your existing MO webhook. You move a conversation yourself by sending a thread control MT Event to CM.

TermMeaning in this guide
MOA message CM delivers to you on your MO webhook (inbound).
MTA message you send to the WhatsApp user through the CM Business Messaging (BM) API.
SRThe status report of an MT you sent.
MT EventAn action you send to CM that is not a message, such as mark as read, typing, or the thread control actions take, pass and release (section 8).
Service messageA free-form (non-template) message, typically a reply to the user.
TemplateA pre-approved marketing, utility or authentication message.

Reading guide

[New] marks something that is new on your existing MO and SR webhook. Phone numbers, IDs and timestamps in the examples are illustrative.

1. The goal of thread control​

A WhatsApp conversation is a thread between the business number and one WhatsApp user. Thread control decides who is allowed to answer in that thread, so that the user does not get two answers to one question, and two systems do not talk over each other.

  • One lead per thread. At any moment one responder leads the thread (Meta calls it the thread owner), or nobody does (idle). Only the lead may send Service messages. The one exception is the escalation partner: its Service message takes the thread (section 3.1).
  • Everyone else stays informed. Responders that do not lead are in standby. When the business allows it, they receive a copy of the user's messages as context. They can still send templates.
  • Control can move. The lead can hand a thread to another role (pass) or give it up (release). The escalation partner can take any thread. Typical case: an AI agent answers first and hands over to a human agent.

Thread control is not a feature you switch on in your integration. It is the result of how the business configures Conversation Routing in Meta Business Suite. Your integration has to recognise the new signals and respect them.

2. Who and when​

2.1 Who needs this​

You are...Why thread control matters to you
A customer integrating on the CM BM APIYou share the WhatsApp number with another responder, such as the Meta Business Agent (MBA) or a partner platform. You receive new MO types, and your Service messages can be rejected.
A partner platform on the same numberYou hold one role (for example marketing). Other responders may take the conversation from you or hand it to you.
A developer building the handlerYou need to recognise the signals, track the thread state, and avoid sending Service messages when you do not lead. Sections 6 to 8 and 10 are for you.

2.2 When does it apply​

Thread control only occurs when Conversation Routing is active on the WhatsApp account. That is the case when the account has more than one responder and the business has configured routing in Meta Business Suite. Without routing, every responder receives every message and none of the signals in this guide occur. Two typical situations:

  • An AI agent (Meta Business Agent) and your human-agent system share one number (section 4).
  • Two or more platforms share one number, each with its own role, for example marketing and utility (section 5).

3. Roles​

3.1 Two kinds of role​

Two things are called a role, so keep them apart. A role identifier says what a responder is on the account (for example marketing). A position says what a responder is in one conversation: the lead or standby. The escalation partner is a special responder that can become the lead of any conversation.

PositionMeaning
LeadOwns the thread. Receives the user's messages and may send Service messages.
StandbyDoes not own the thread. Receives copies of the user's messages only when the business granted Conversation visibility. Must not send Service messages and cannot pass or release.
Escalation partnerThe one responder (at most one per account) that can take any thread, and that receives threads passed to the escalation role. When it is not leading, it is in standby like any other responder.

3.2 Role identifiers​

The roles can be configured in the Conversation Routing domain in the Meta Business Suite under the WhatsApp Account > more > conversation routing.

IdentifierWho it isNotes
customer_servicePrimary for the Service entry point (a message that is not a reply to a recent template or ad).Configured by the business in Meta Business Suite.
marketingPrimary for replies to marketing templates.Configured by the business in Meta Business Suite.
utilityPrimary for replies to utility templates.Configured by the business in Meta Business Suite.
ctwaPrimary for Click-to-WhatsApp ad conversations.Configured by the business in Meta Business Suite.
ai_agentThe Meta Business Agent (MBA).The only role the business does not configure. Only available on accounts where MBA is enabled.
escalationThe escalation partner.At most one per account. The only role that can take a thread. Configured by the business in Meta Business Suite.
callsPrimary for WhatsApp calls.Never appears in thread control events: handling a call never makes a responder the lead. Configured by the business in Meta Business Suite.

The same identifiers appear in thread control MOs (previous_owner_role, new_owner_role) exactly as Meta sends them, and they are the values you use as target_role when you pass a thread (section 8.3). A responder can hold more than one role.

4. Thread control with the Meta Business Agent​

Situation: the Meta Business Agent (MBA, role ai_agent) answers first. When the user needs a human, MBA hands the conversation to the escalation partner. For this flow the business configures your CM integration as the escalation partner in Meta Business Suite. You are in standby until MBA hands over or you take the thread, then you lead and answer through the BM API.

#What happensWhat you receiveWhat you do
1The user writes. MBA leads the thread.MO with standby: true, only if the business granted Conversation visibility.Store as context. Do not reply.
2MBA answers the user.Nothing. CM does not forward messages that other responders send.No action.
3aMBA hands the thread over to you.MO thread_control with type: control_passed. It can include a conversation_context summary.You are the lead. Start your own handling, for example assign a human agent, and reply with a Service message.
3bOr: you step in yourself while MBA is answering.Nothing for your own take. Your next MOs have standby: false. MBA gets control_taken.Send a ThreadControlTake MT Event (section 8.2), or simply send a Service message: as escalation partner it takes the thread.
4You answer the user.SR of your MT.Send Service messages through the BM API.
5You are done with the conversation.Nothing. No event follows a release.Send a ThreadControlRelease MT Event. The thread becomes idle and the user's next message is routed again, for example to MBA. Or send a ThreadControlPass with target_role: ai_agent to hand it back to MBA right away.

4.1 Actions you can take​

Action (MT Event)WhenResult
ThreadControlTakeYou want the thread before MBA hands it over. Escalation partner only.You lead. MBA gets control_taken. Sending a Service message has the same effect (implicit take).
ThreadControlPassYou lead and want to hand the thread to another role, for example back to ai_agent.The target role leads and gets control_passed.
ThreadControlReleaseYou lead and the conversation is finished.The thread becomes idle. Nobody is notified.
  • Every Service message you send as escalation partner takes the thread from MBA. Only send one when you intend to take over the conversation. Templates never take the thread.
  • Release or pass the thread when you are done. Otherwise you stay the lead, and MBA does not answer, until the user has been inactive for 24 hours, or until the user clicks a Click-to-WhatsApp ad or taps a button on a marketing or utility template (that routes the thread again).
  • Use control_passed as the trigger to start your own handling of the conversation.
  • Your role is configured by the business in Meta Business Suite. If your integration is not the escalation partner, MBA's handover does not reach you and ThreadControlTake is rejected by Meta.

5. Thread control with several partners​

Situation: more than one platform shares the WhatsApp number. Example: a partner platform sends marketing templates and is primary for the marketing role. You, the customer through CM, send utility templates and are primary for the utility role. Meta routes every inbound message to one of you.

5.1 Who holds which role​

WhoRoleSends
Partner platformmarketingMarketing templates. Handles replies to marketing templates.
You (customer, via the CM BM API)utilityUtility templates. Handles replies to utility templates.
Meta Business Agent (optional)ai_agentService messages while it leads.
Escalation partner (optional)escalationAny message. Can take any thread.

5.2 Example flow​

#What happensWhat each side sees
1Both send templates to the user.Templates need no lead and do not change the lead. Nobody leads yet: the thread is idle.
2The user replies to the marketing template.Meta routes it to the partner platform, which becomes the lead and gets a regular message. You are in standby and get an MO with standby: true (only with Conversation visibility).
3You try to send a Service message.Rejected with a failed SR (error 131070). Send a template or wait.
4The user taps a quick-reply button on your utility template.Meta routes the thread again and you become the lead. You get a regular MO with standby: false. There is no control_passed for this: it is a re-route, not a handover. The partner platform is now in standby.
5You answer with a Service message.Allowed: you lead.
6Optional: you pass the thread back.Send ThreadControlPass with target_role: marketing. The partner platform gets control_passed and leads again.

5.3 Things to know​

  • Use the standby field to know your position. Read message.custom.standby on every regular MO: true means another responder leads, false means you lead. This also covers changes that arrive without a thread control MO, such as a release, 24 hours of user inactivity, or a template button tap that routes the thread to another responder.
  • Templates are always safe to send. Marketing, utility and authentication templates are allowed in every position and sending one never changes the lead.
  • The user's reaction can change the lead. A button tap, list selection or Flow reply on a marketing or utility template, or a Click-to-WhatsApp ad click, routes the thread again. Authentication templates never change the lead.

6. Thread control signals​

Thread control reaches you through your existing MO and SR webhook (you receive), and you act on it through MT Events and the BM API (you send). There is nothing new to subscribe to: CM receives Meta's routing and handover webhooks and forwards what is relevant to you.

6.1 What you receive​

SignalWhen you receive itWhat to do
[New] MO with standby: falseA user message on a thread you lead.Answer it with a Service message.
[New] MO with standby: trueA copy of a user message on a thread another responder leads. Only when the business granted you Conversation visibility.Context only. Do not reply.
[New] conversation_context on an MOAn AI-generated summary, when you pick up a conversation without having had standby copies of it (section 7.3).Show it to your agent. It is optional: never rely on it being present.
[New] MO control_passedAnother responder passed the thread to a role you hold. Only the new lead receives it.You are the lead now. You may send Service messages.
[New] MO control_takenThe escalation partner took a thread you led, by an explicit take or by sending a Service message. Only the previous lead receives it.You no longer lead. Stop sending Service messages.
[New] SR with error 131070Your Service message was rejected because you do not lead the thread, or the thread is idle.Do not retry. Mark the conversation as not led by you.

What you do not receive

  • Copies of messages other responders send (Meta calls them echoes) and their delivery or read receipts. CM does not forward these.
  • Any event for a release, for 24 hours of user inactivity, for a re-route (button tap, ad click), or for your own take or pass. Meta sends no event for these. Track them yourself (section 10, step 5).
  • A status report for a thread control MT Event, neither on success nor on rejection (section 8.5).

6.2 What you can send, by position​

ActionYou leadYou are in standbyYou are the escalation partner (not leading)Notes
Service message (BM API)YesNo (SR 131070)YesAs escalation partner it takes the thread (implicit take).
Template: marketing, utility, authentication (BM API)YesYesYesNever changes the lead.
ThreadControlPass (MT Event)YesNoNoLead only. As escalation partner, always set target_role: Meta rejects an untargeted pass from you (error 100).
ThreadControlRelease (MT Event)YesNoNoLead only. The escalation partner must take the thread first.
ThreadControlTake (MT Event)Not neededNo (Meta error 2494191)YesEscalation partner only.

6.3 How to recognise the signals​

All signals are recognised from the custom object of an MO, or from the description of an SR. Never parse message.text of a thread control MO.

SignalHow to recognise itWhat it means
[New] MO standby: falsemessage.custom.standby is falseYou lead. Handle as a customer message.
[New] MO standby: truemessage.custom.standby is trueAnother responder leads. Context only.
[New] Conversation summarymessage.custom.conversation_context is presentHuman-readable recap. Do not parse it.
[New] MO control_passedmessage.custom.message_type is "thread_control" and type is "control_passed"You are the new lead.
[New] MO control_takenmessage.custom.message_type is "thread_control" and type is "control_taken"The escalation partner took the lead from you.
[New] SR error 131070The SR description contains 131070Your Service message was rejected.

Thread control MOs use the same MO template as every other inbound message. These fields differ:

FieldValueNotes
referencehandover- + 32 charactersGenerated by CM, because Meta gives these events no message ID. Built from the WhatsApp Business Account ID, the user's number, the event type and Meta's timestamp, so it is identical when Meta retries the same event. Use it to de-duplicate.
from.numberThe WhatsApp userThe user's phone number, although the user wrote nothing.
message.textShort summaryThread control passed to <new_owner_role>. or Thread control taken by <new_owner_role>. Never parse it: use custom.
message.customEvent payloadmessage_type (thread_control), type, consumer_phone_number (as Meta sends it, without + or 00), timestamp (Unix seconds, as a string) and a control_passed or control_taken object. There is no standby field.

Do not treat a thread control MO as a customer message

from.number is the WhatsApp user, but the user wrote nothing. Check custom.message_type first. Never reply to it, never pass it to a chatbot, and never show it in an agent inbox as something the customer said.

Example: failed SR with error 131070​

Your Service message was rejected because you do not lead the thread, or the thread is idle. Meta's text says "another app" even when nobody leads.

wha: META#131070 - Error sending message in cloud. Message from Meta: (#131070) Message failed to send
because another app is controlling this thread now
  • Match the number 131070 in the SR description. Do not match the wording: it is Meta's free text and can change.
  • Do not retry the Service message. Mark the conversation as not led by you and wait for a signal that you lead again.
  • Templates are never rejected for this reason. The escalation partner never gets this error: its Service message takes the thread.

7. Examples of each MO​

The examples use the default JSON MO template. The envelope (reference, from, to, time, channel) follows the MO template configured on your account; the thread control information is always in message.custom.

7.1 MO with standby: false​

A user message on a thread you lead. Answer it with a Service message.

{
"reference": "wamid.HBgLMzE2MzYzNDI2MDUVAgASGBQzQTZCNzU4NzE2NUQ0RTk5MjAzNgA=",
"from": { "number": "31636342605", "name": "John Doe" },
"to": { "number": "31612345678" },
"message": {
"text": "Can you send me the invoice?",
"custom": {
"meta_received_time": "2026-10-28T09:14:02",
"message_type": "text",
"standby": false
}
},
"time": "2026-10-28 09:14:02",
"channel": "WhatsApp"
}

7.2 MO with standby: true​

A copy of a user message while another responder leads. Use it as context only. Do not reply.

{
"reference": "wamid.HBgLMzE2MzYzNDI2MDUVAgARGBI5QTM4RjhDOEUzOEYxOUYwQzQA",
"from": { "number": "31636342605", "name": "John Doe" },
"to": { "number": "31612345678" },
"message": {
"text": "Hi, is my order still on the way?",
"custom": {
"meta_received_time": "2026-10-28T09:05:11",
"message_type": "text",
"standby": true
}
},
"time": "2026-10-28 09:05:11",
"channel": "WhatsApp"
}

The reference is the normal WhatsApp message ID, so only the standby flag tells it apart from a message you should answer. You only receive standby MOs when the business has granted you Conversation visibility.

7.3 MO with a conversation summary​

When you pick up a conversation without having had standby copies of it, Meta can add an AI-generated summary of the conversation so far. It is sent on the first message of a new thread, on a handover (control_passed, section 7.4), and on your next message after another responder sent a template during your conversation. You never get both a summary and standby copies for the same conversation.

{
"reference": "wamid.HBgTTkwuMTk2MzcwNTA0MDkxMTYzNBUUABIYFDNBQUUyMTc4RTlDNjAzQ0I2NkM3AA==",
"from": { "number": "31636342605", "name": "John Doe" },
"to": { "number": "31612345678" },
"message": {
"text": "Great, thanks. I would like to talk to an employee please",
"custom": {
"meta_received_time": "2026-11-06T14:11:57",
"message_type": "text",
"standby": false,
"conversation_context": {
"type": "summary",
"summary": {
"text": "* The customer asked for a product recommendation. ..."
}
}
}
},
"time": "2026-11-06 14:11:57",
"channel": "WhatsApp"
}
  • Treat conversation_context as optional. Do not assume it is present.
  • summary.text is model-generated prose. Show it to your agent; do not parse it. Order numbers and amounts are kept verbatim, and open items are described as unresolved.

7.4 MO thread_control: control_passed​

Another responder (here: the AI agent) handed the conversation to a role you hold. You are the new lead. Reply with a Service message.

{
"reference": "handover-7f3a9c0e5b2d4a18f9c7e6b5a4d3c2f1",
"from": { "number": "31636342605", "name": "" },
"to": { "number": "31612345678" },
"message": {
"text": "Thread control passed to escalation.",
"custom": {
"message_type": "thread_control",
"type": "control_passed",
"consumer_phone_number": "31636342605",
"timestamp": "1793178734",
"control_passed": {
"previous_owner_role": "ai_agent",
"new_owner_role": "escalation",
"metadata": "WhatsApp user requested human agent",
"conversation_context": {
"type": "summary",
"summary": { "text": "* The customer wants to change order 40182. ..." }
}
}
}
},
"time": "2026-10-28 09:12:14",
"channel": "WhatsApp"
}
  • metadata is optional free text (up to 2,000 characters) from the responder that passed the thread.
  • conversation_context is optional: only included when you had no standby copies of the conversation.
  • timestamp is Unix seconds, as a string. 1793178734 is 2026-10-28 09:12:14 UTC.

7.5 MO thread_control: control_taken​

The escalation partner took a thread you led. Stop sending Service messages.

{
"reference": "handover-a1b2c3d4e5f60718293a4b5c6d7e8f90",
"from": { "number": "31636342605", "name": "" },
"to": { "number": "31612345678" },
"message": {
"text": "Thread control taken by escalation.",
"custom": {
"message_type": "thread_control",
"type": "control_taken",
"consumer_phone_number": "31636342605",
"timestamp": "1793179201",
"control_taken": {
"previous_owner_role": "customer_service",
"new_owner_role": "escalation",
"metadata": "Human agent stepping in"
}
}
},
"time": "2026-10-28 09:20:01",
"channel": "WhatsApp"
}
  • This is the only way you lose the lead with a notification. You are not notified when you release or pass, when the thread goes idle after 24 hours, or when a button tap or ad click routes the thread to another responder.
  • If Meta also sends app identifiers (previous_owner_app_id, new_owner_app_id, new_owner_business_id), CM forwards them in the same object. Use the role fields.

8. Sending thread control MT Events​

You take, pass and release a thread by sending an MT Event to CM, on the same endpoint and with the same product token you use for other WhatsApp MT Events such as mark as read and typing. CM validates the event and sends the action to Meta.

8.1 Request​

POST https://gw.messaging.cm.com/v1.0/event
Content-Type: application/json

Every thread control MT Event has the same body: your product token in authentication, your business number in from, the WhatsApp user in to, the action in event, and the channel. Only event differs per action.

FieldRequiredDescription
authentication.productTokenYesYour CM product token.
from.numberYesYour WhatsApp business number that the conversation is on, in international format, for example 0031000000001.
to.numberYesThe WhatsApp user. Either the phone number in international format with digits only (for example 0031000000002; no +, spaces or dashes), or the user's business-scoped user ID (BSUID), for example NL.164646464646.
event.typeYesThreadControlTake, ThreadControlPass or ThreadControlRelease.
event.custom.target_roleNo, Pass onlyThe role that should lead next: ai_agent, ctwa, customer_service, escalation, marketing or utility. Use lowercase. Leave it out for an untargeted pass: Meta then passes the thread to the escalation partner, the same as escalation. The escalation partner itself must always set it. Ignored for take and release.
channelYesWhatsApp

8.2 Take​

The escalation partner takes the thread from whoever leads. The previous lead receives control_taken (7.5). You are not notified of your own take.

{
"authentication": {
"productToken": "<your product token>"
},
"from": {
"number": "0031000000001"
},
"to": {
"number": "0031000000002"
},
"event": {
"type": "ThreadControlTake"
},
"channel": "WhatsApp"
}
  • Only the escalation partner can take. Meta rejects a take from any other responder (error 2494191).
  • Sending a Service message as escalation partner has the same effect (implicit take).

8.3 Pass​

The lead hands the thread to another role. There are two kinds of pass:

Passevent.customWho becomes the lead
Targetedtarget_role set to one of the role identifiersThe responder that holds that role. It receives control_passed.
UntargetedNo target_roleThe account's escalation partner. It receives control_passed. The escalation partner itself cannot send it.

Targeted pass​

Hands the thread to the role in target_role, here the Meta Business Agent.

{
"authentication": {
"productToken": "<your product token>"
},
"from": {
"number": "0031000000001"
},
"to": {
"number": "0031000000002"
},
"event": {
"type": "ThreadControlPass",
"custom": {
"target_role": "ai_agent"
}
},
"channel": "WhatsApp"
}

Untargeted pass​

Without target_role, Meta hands the thread to the account's escalation partner. Only a lead that is not the escalation partner can send it, for example a marketing or utility partner.

{
"authentication": {
"productToken": "<your product token>"
},
"from": {
"number": "0031000000001"
},
"to": {
"number": "0031000000002"
},
"event": {
"type": "ThreadControlPass"
},
"channel": "WhatsApp"
}
  • The escalation partner cannot send an untargeted pass, because it would pass the thread to itself. Meta rejects it with error 100: Caller business is an escalation partner; cannot pass thread control to self. As escalation partner, set target_role (for example ai_agent to hand back to MBA), or send a release.
  • Meta rejects a pass when the thread is idle, when you do not lead it, when the target role is not available on the account (for example ai_agent without MBA), when the role has no single primary, or when the target already leads the thread.

8.4 Release​

The lead gives up the thread. The thread becomes idle and the user's next message is routed again by entry point.

{
"authentication": {
"productToken": "<your product token>"
},
"from": {
"number": "0031000000001"
},
"to": {
"number": "0031000000002"
},
"event": {
"type": "ThreadControlRelease"
},
"channel": "WhatsApp"
}

No event is sent to anyone after a release, so update your own state when you send it. A release on a thread that is already idle succeeds. In every example, to.number can also be the user's BSUID, for example NL.164646464646.

8.5 Response and errors​

CM answers the request immediately:

ResponseMeaning
HTTP 200 {"details": "", "errorCode": 0}CM accepted the event and will send it to Meta.
errorCode 301, details Missing fromfrom.number is missing.
errorCode 302, details Missing toto.number is missing.
errorCode 304, details Missing body or Missing body/eventTypeevent or event.type is missing.
errorCode 305, details Missing channel or Unknown channelchannel is missing or unknown.

Accepted is not the same as applied

A 200 response means CM accepted the event, not that Meta applied it. There is no status report for a thread control MT Event. If the event is invalid (for example a target_role that is not one of the roles above, or a to.number with a +) or Meta rejects it (for example a take from a responder that is not the escalation partner, an untargeted pass from the escalation partner, or a pass on an idle thread), you are not notified.

Confirm the result from the next signals instead: after a successful take, your next MO has standby: false and your Service messages are delivered; after a successful pass or release, your next MO (if any) has standby: true, and a Service message from you fails with 131070.

9. Prerequisites​

9.1 On the WhatsApp account (Meta)​

  • The account has more than one responder that can answer an inbound message, for example CM and the Meta Business Agent, or CM and another partner.
  • The business has configured Conversation Routing in Meta Business Suite (which responder is primary for each entry point).
  • The business has accepted the Meta Business Agents and Platform Terms of Service. Without it, Conversation visibility, the escalation partner and thread control are not available.

9.2 Meta Business Suite settings (made by the business)​

SettingWhat it does
Message routingMaps each entry point (service, marketing replies, utility replies, Click-to-WhatsApp) to its primary responder. Optionally, replies to a template go to the responder that sent it (Route to Sender).
Thread controlDesignates the escalation partner: at most one per account.
Conversation visibilityLets responders that do not lead receive copies of the user's messages (MOs with standby: true). Off by default. Without it you receive nothing while you are in standby, but you may receive a conversation_context summary when a conversation comes to you.

9.3 At CM​

  • Nothing to subscribe to. CM receives Meta's routing and handover webhooks and forwards them on your existing MO webhook.
  • Thread control MT Events use your existing product token and the MT Event endpoint (section 8).

10. Implementation​

Follow these steps in order. Steps 3 and 4 depend on your situation; the other steps apply to both.

Step 1. Read message.custom on every MO​

Do not decide on message.text alone. Branch in this order:

  1. message_type is "thread_control": update your thread state (control_passed: you lead, control_taken: you no longer lead). Never reply, never route it to a chatbot or an inbox.
  2. standby is true: another responder leads. Store as context. Never reply.
  3. Everything else: a regular message on a thread you lead. Handle it as a customer message. If conversation_context is present, show the summary to your agent.

Step 2. Send thread control MT Events​

Add take, pass and release to your integration with the MT Event endpoint and your product token (section 8).

Step 3. For the Meta Business Agent​

Ask the business to configure your CM integration as the escalation partner. Then follow section 4: treat standby MOs as context, use control_passed (or a take) to become the lead, send your MTs, and release or pass the thread back to ai_agent when you are done.

Step 4. For several partners​

Agree with the business which entry points your integration is primary for. The business sets this up in Meta Business Suite under Conversation Routing. Then read standby on every MO to know your position (section 5.3).

For both situations

Ask the business to grant your integration Conversation visibility if you want copies of the user's messages while another responder leads. Without it you receive no MOs with standby: true.

Step 5. Track state and handle errors​

  • Keep the thread state per conversation, keyed by the user's phone number: thread control MOs identify the user by phone number only. Meta has no endpoint that returns the current lead.
  • Never send a Service message when you do not lead, unless you are the escalation partner and want to take the thread. Templates are always allowed.
  • On a failed SR with 131070, do not retry. Mark the conversation as not led by you. Match the number, not Meta's wording.
  • When you send a release or a pass, set your state to "not leading" yourself: no event confirms it.
  • After 24 hours without a user message the thread is idle and nothing tells you. Clear your state.
  • De-duplicate thread control MOs on reference, and ignore events whose custom.timestamp is older than the last one you processed for that user.

Step 6. Test your setup​

#TriggerCheck
1A user writes while another responder leads.You get an MO with standby: true and do not reply.
2The other responder passes the thread to you.You get a control_passed MO, set your state to lead and can send a Service message.
3The escalation partner takes a thread you lead.You get a control_taken MO and stop sending Service messages.
4You send a Service message without leading (and you are not the escalation partner).The SR fails with 131070 and you do not retry.
5You send ThreadControlPass with target_role: ai_agent.MBA answers the user's next message. If you have Conversation visibility, you get it as standby: true.
6You send ThreadControlRelease.No MO follows. The user's next message is routed by entry point.
7As escalation partner, you send ThreadControlTake while MBA leads.The user's next message reaches you with standby: false.