fix(meta): expose messaging_type/tag on Instagram + dedupe across Meta Send API actions
loading diff…
INSTAGRAM_SEND_TEXT_MESSAGE (and INSTAGRAM_SEND_IMAGE) fail in production with status 403 — error_subcode 2534022: "This message is sent outside of allowed window." The actions had no way to set messaging_type=MESSAGE_TAG + tag=HUMAN_AGENT, the only escape from Meta's 24-hour reply window.mercury/utils/meta_messaging.py with MessagingType / MessageTag enums, a MessagingWindowMixin (defaulted fields + validator), and an apply_messaging_window(payload, request) helper. Route Instagram's two send actions and Facebook's two send actions through it.send_message.py used a model_validator, send_media_message.py raised mid-execute(). Both now share the same primitive. The mid-execute raise in send_media_message.py is gone; validation happens at request-construction time.| Scenario | Before | After |
|---|---|---|
| Instagram default reply within 24h | works (RESPONSE implicit) | works (RESPONSE explicit, no behavior change) |
| Instagram reply outside 24h | 403 / 2534022 — no surface to fix | caller can pass messaging_type=MESSAGE_TAG, tag=HUMAN_AGENT |
MESSAGE_TAG without tag | (Instagram) hit API and 400; (FB) raised inline | pydantic ValidationError before any HTTP work |
Facebook callers passing messaging_type="RESPONSE" etc. | works | works (string → enum coercion) |
Invalid string like messaging_type="bogus" | would have failed at the API | now fails at pydantic |
ruff check + ruff format --check: passnox -s chk_app -- apps/instagram (ruff + mypy 1.13): passnox -s chk_app -- apps/facebook (ruff + mypy 1.13): passnox -s chk (full repo, every app + mercury core + tests): all checks passedMESSAGE_TAG without tag — raises at RequestWrapper.parse() boundaryMESSAGE_TAG + HUMAN_AGENT — parses; payload contains both fields"RESPONSE", "ACCOUNT_UPDATE", etc.) — coerce cleanly to enumsRequestWrapper.schema()) contains messaging_type, tag, MESSAGE_TAG, HUMAN_AGENT for all four actionstests/*instagram* / tests/*facebook* / tests/*meta_messaging* to regress.run.py against a connected Instagram Business account with a stale PSID (>24h since last user message):
error_subcode=2534022 (reproduces the bug){"messaging_type": "MESSAGE_TAG", "tag": "HUMAN_AGENT"} succeeds (requires Human Agent app permission)INSTAGRAM_SEND_IMAGE with the same MESSAGE_TAG / HUMAN_AGENT paramsFACEBOOK_SEND_MESSAGE regression: existing string messaging_type="RESPONSE" callers continue to succeedFACEBOOK_SEND_MEDIA_MESSAGE regression: existing callers using messaging_type + tag continue to succeed🤖 Generated with Claude Code