Skip to main content
Glama

Postkey: Instagram DM Automation and Comment-to-DM

Reply in a conversation

postkey_send_reply
Destructive

Postkey: Sends a text message to the person in a conversation, as the business. It reaches a real person on Instagram and cannot be taken back. Assistants can reply only within 24 hours of the person's last message: after that nothing is sent (code outside_24h_window) and a person answers by hand. If this connection must ask a person first (the default), the reply is NOT sent: it waits in Approvals in Postkey, and the result has waiting_for_approval true, which is not an error: do not call it again or say it was sent. A reply that carries a link, a handle, a phone number or an email that is not the account's own always waits for approval. At most 3 replies an hour to one conversation. Call postkey_preview_action first. For a note only the team sees use postkey_add_conversation_note.

Input Schema

NameRequiredDescriptionDefault
textYesThe message, 1 to 1000 characters, plain text.
closeNotrue: also mark the conversation Closed after sending. Default false.
preview_idNoOptional: the preview_id postkey_preview_action gave for exactly these arguments today (UTC). Approvals then shows the person that you showed them the preview. A preview_id that does not match is ignored, never refused.
conversation_idYesThe conversation id from postkey_list_conversations (or conversation_id in postkey_get_contact), as it was given.

Output Schema

NameRequiredDescriptionDefault
atNoWhen it was sent.
okYesfalse: refused (isError; code, message, guide_topic, url); no change.
sentNotrue: the message went out. false: it failed, or it waits for approval.
stateNoThe conversation's state now (open or closed).
messageNoWhat happened.
message_idNoThe sent message's id.
request_idNoThe held request: read it with postkey_get_approval or postkey_list_waiting_for_approval. A post held in Posts > Approvals has none.
held_becauseNoWhy it waits on a direct connection.
conversation_idNoThe conversation id.
waiting_for_approvalNotrue: NOT sent; waits for a person in Approvals.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedOutput schema / properties / ok / description
      Previous value: -"false: refused (isError true; code, message, guide_topic, url), nothing changed."New value: +"false: refused (isError; code, message, guide_topic, url); no change."
  2. Changed5 schema fields changed
    • changedInput schema / properties / close / description
      Previous value: -"Also mark the conversation Closed after sending."New value: +"true: also mark the conversation Closed after sending. Default false."
    • changedInput schema / properties / conversation_id / description
      Previous value: -"The conversation id from postkey_list_conversations."New value: +"The conversation id from postkey_list_conversations (or conversation_id in postkey_get_contact), as it was given."
    • changedInput schema / properties / preview_id / description
      Previous value: -"Optional: the preview_id postkey_preview_action gave for exactly these arguments. The person then sees in Approvals that you showed them the preview."New value: +"Optional: the preview_id postkey_preview_action gave for exactly these arguments today (UTC). Approvals then shows the person that you showed them the preview. A preview_id that does not match is ignored, never refused."
    • changedInput schema / properties / text / description
      Previous value: -"The message, 1 to 1000 characters."New value: +"The message, 1 to 1000 characters, plain text."
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "additionalProperties": true,
      +  "properties": {
      +    "at": {
      +      "description": "When it was sent.",
      +      "type": [
      +        "string",
      +        "null"
      +      ]
      +    },
      +    "conversation_id": {
      +      "description": "The conversation id.",
      +      "type": "string"
      +    },
      +    "held_because": {
      +      "description": "Why it waits on a direct connection.",
      +      "type": "string"
      +    },
      +    "message": {
      +      "description": "What happened.",
      +      "type": "string"
      +    },
      +    "message_id": {
      +      "description": "The sent message's id.",
      +      "type": [
      +        "string",
      +        "null"
      +      ]
      +    },
      +    "ok": {
      +      "description": "false: refused (isError true; code, message, guide_topic, url), nothing changed.",
      +      "type": "boolean"
      +    },
      +    "request_id": {
      +      "description": "The held request: read it with postkey_get_approval or postkey_list_waiting_for_approval. A post held in Posts > Approvals has none.",
      +      "type": "string"
      +    },
      +    "sent": {
      +      "description": "true: the message went out. false: it failed, or it waits for approval.",
      +      "type": "boolean"
      +    },
      +    "state": {
      +      "description": "The conversation's state now (open or closed).",
      +      "type": [
      +        "string",
      +        "null"
      +      ]
      +    },
      +    "waiting_for_approval": {
      +      "description": "true: NOT sent; waits for a person in Approvals.",
      +      "type": "boolean"
      +    }
      +  },
      +  "required": [
      +    "ok"
      +  ],
      +  "type": "object"
      +}
  3. Changed1 schema field changed
    • changedInput schema / properties / conversation_id / pattern
      Previous value: -"^([0-9]{1,40}|[0-9a-f]{24})$"New value: +"^([0-9]{1,40}|[0-9a-f]{24}|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$"
  4. First observed

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true and idempotentHint=false, and the description adds substantive context beyond them: the message reaches a real person and cannot be recalled, replies outside 24 hours fail with code outside_24h_window, approval-gated sends return waiting_for_approval true rather than an error, content with links/handles/phone/email always waits for approval, and there is a rate limit of 3 replies per hour per conversation. None of this contradicts the mutation and destructiveness hints.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense but well-ordered: action and irreversibility first, then eligibility (24h), then the approval behavior, then rate limit, then the prerequisite call and the sibling alternative. Every sentence carries operational information, though the run of policy clauses makes it longer than ideal and slightly hard to scan.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive, open-world send operation with approval gating, the description covers irreversibility, failure semantics with the specific error code, the approval outcome shape, rate limits, and the required preview prerequisite. An output schema exists, so return values need not be explained further, and nothing an agent needs to avoid a mis-send is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all four parameters are already documented in the schema, including preview_id's matching semantics and close's effect. The description references preview_id indirectly by telling the agent to call postkey_preview_action first, but adds no further parameter-level meaning. Baseline 3 applies when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Sends a text message to the person in a conversation, as the business") and names the delivery channel (Instagram DM to a real person). It also explicitly distinguishes itself from postkey_add_conversation_note, the closest sibling, so an agent can separate replying from internal note-taking without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use routing ("Call postkey_preview_action first") and when-not-to-use routing ("For a note only the team sees use postkey_add_conversation_note"). It also names the blocking preconditions: the 24-hour reply window and the approval flow, including the instruction not to retry when waiting_for_approval is true.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources