Skip to main content
Glama

Create a DM automation (paused)

postfjord_create_automation

For direct messages on Instagram and Facebook; an email series that starts by itself is postfjord_create_email_automation. Creates a DM automation on Instagram or Facebook, always paused: it answers nobody until it is switched on. Triggers: dm_keyword (a word in a DM), comment_keyword (a word in a comment, answered with a DM that must hold a link; postIds "any" or "next"; optional publicReplies under the comment), story_reply, story_mention, ref_link (an ig.me or m.me link with refCode, exactly one channel), default_reply (any DM, optional hours) and after_purchase (after a booking or a Stripe sale, events ["booking","sale"], a message with the review link: the Ask for a review automation). Steps run in order: message (text, optional link, link button and up to three buttons), followGate, collectEmail, followUp, delay, question, addTag (tag names; a new name makes the tag) and aiReply (last). Steps that remove a tag, set a field or branch are added in the app. Write the texts in the brand voice and the language of the audience. Needs the Draft scope. If the answer lists sameKeywords, another automation answers those words first: say so. Afterwards show the person you work for what it does and switch it on with postfjord_set_automation only after they approve. On a retry after a timeout or error, send the same idempotency_key: the first answer comes back and nothing is made or sent twice.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "name": "<name>",
      "trigger": "<trigger>",
      "steps": "<steps>"
    },
    "name": "postfjord_create_automation"
  }
}

Input Schema

NameRequiredDescriptionDefault
nameYesThe name on the Automations screen, for example "Comment GUIDE".
stepsYes
triggerYes
likeCommentNocomment_keyword only: like the comment.
publicRepliesNocomment_keyword only: public replies under the comment, one picked at random.
idempotency_keyNoYour own id for this one action, for example post-20261006-launch. Make a new one for each new thing; send the same one again only when you retry. Left out, the exact same call within 10 minutes counts as a retry.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedInput schema / properties / steps / items / oneOf
      Previous value: -[
      -  {
      -    "properties": {
      -      "buttons": {
      -        "description": "Quick reply buttons that continue to the next step, for example \"Send it\". At most three with the link button.",
      -        "items": {
      -          "maxLength": 20,
      -          "type": "string"
      -        },
      -        "maxItems": 3,
      -        "type": "array"
      -      },
      -      "link": {
      -        "properties": {
      -          "url": {
      -            "description": "https:// address. Postfjord shortens it and counts the clicks.",
      -            "maxLength": 2000,
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "url"
      -        ],
      -        "type": "object"
      -      },
      -      "linkButton": {
      -        "description": "Show the link as a button with this title instead of in the text.",
      -        "properties": {
      -          "title": {
      -            "maxLength": 20,
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "title"
      -        ],
      -        "type": "object"
      -      },
      -      "text": {
      -        "description": "The DM text.",
      -        "maxLength": 1000,
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "message",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "text"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "buttonLabel": {
      -        "maxLength": 20,
      -        "type": "string"
      -      },
      -      "notFollowingText": {
      -        "maxLength": 1000,
      -        "type": "string"
      -      },
      -      "text": {
      -        "description": "Asks the person to follow the account first.",
      -        "maxLength": 1000,
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "followGate",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "text"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "askConsent": {
      -        "description": "Also ask for a yes to the email list.",
      -        "type": "boolean"
      -      },
      -      "askText": {
      -        "maxLength": 1000,
      -        "type": "string"
      -      },
      -      "invalidText": {
      -        "maxLength": 1000,
      -        "type": "string"
      -      },
      -      "thanksText": {
      -        "maxLength": 1000,
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "collectEmail",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "askText"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "delayMinutes": {
      -        "maximum": 1380,
      -        "minimum": 5,
      -        "type": "integer"
      -      },
      -      "onlyIfNoClick": {
      -        "description": "Default true: only when the link was not clicked.",
      -        "type": "boolean"
      -      },
      -      "text": {
      -        "maxLength": 1000,
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "followUp",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "text"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "amount": {
      -        "maximum": 9007199254740991,
      -        "minimum": 1,
      -        "type": "integer"
      -      },
      -      "type": {
      -        "const": "delay",
      -        "type": "string"
      -      },
      -      "unit": {
      -        "enum": [
      -          "minutes",
      -          "hours",
      -          "days"
      -        ],
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "amount",
      -      "unit"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "answer": {
      -        "enum": [
      -          "text",
      -          "email",
      -          "number",
      -          "date",
      -          "birthday",
      -          "yesno"
      -        ],
      -        "type": "string"
      -      },
      -      "invalidText": {
      -        "maxLength": 1000,
      -        "type": "string"
      -      },
      -      "key": {
      -        "description": "The contact field the answer is saved to.",
      -        "pattern": "^[a-z0-9_]{1,30}$",
      -        "type": "string"
      -      },
      -      "noLabel": {
      -        "maxLength": 20,
      -        "type": "string"
      -      },
      -      "text": {
      -        "maxLength": 1000,
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "question",
      -        "type": "string"
      -      },
      -      "yesLabel": {
      -        "maxLength": 20,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "text",
      -      "key"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "tags": {
      -        "description": "Tag names to give the person, for example after collectEmail. A new name makes the tag. A tag can start an email automation once their address is confirmed.",
      -        "items": {
      -          "maxLength": 40,
      -          "minLength": 1,
      -          "type": "string"
      -        },
      -        "maxItems": 10,
      -        "minItems": 1,
      -        "type": "array"
      -      },
      -      "type": {
      -        "const": "addTag",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "tags"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "instruction": {
      -        "description": "What Postfjord's AI should do in the conversation from here, in the brand voice.",
      -        "maxLength": 1500,
      -        "type": "string"
      -      },
      -      "maxTurns": {
      -        "maximum": 10,
      -        "minimum": 1,
      -        "type": "integer"
      -      },
      -      "type": {
      -        "const": "aiReply",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "instruction"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "properties": {
      +      "buttons": {
      +        "description": "Quick reply buttons that continue to the next step, for example \"Send it\". At most three with the link button.",
      +        "items": {
      +          "maxLength": 20,
      +          "type": "string"
      +        },
      +        "maxItems": 3,
      +        "type": "array"
      +      },
      +      "link": {
      +        "properties": {
      +          "url": {
      +            "description": "https:// address. Postfjord shortens it and counts the clicks.",
      +            "maxLength": 2000,
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "url"
      +        ],
      +        "type": "object"
      +      },
      +      "linkButton": {
      +        "description": "Show the link as a button with this title instead of in the text.",
      +        "properties": {
      +          "title": {
      +            "maxLength": 20,
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "title"
      +        ],
      +        "type": "object"
      +      },
      +      "text": {
      +        "description": "The DM text.",
      +        "maxLength": 1000,
      +        "type": "string"
      +      },
      +      "type": {
      +        "const": "message",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "text"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "buttonLabel": {
      +        "maxLength": 20,
      +        "type": "string"
      +      },
      +      "notFollowingText": {
      +        "maxLength": 1000,
      +        "type": "string"
      +      },
      +      "text": {
      +        "description": "Asks the person to follow the account first.",
      +        "maxLength": 1000,
      +        "type": "string"
      +      },
      +      "type": {
      +        "const": "followGate",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "text"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "askConsent": {
      +        "description": "Also ask for a yes to the email list. On a Free workspace a step with this on is skipped: the DM does not ask and goes on to the next step.",
      +        "type": "boolean"
      +      },
      +      "askText": {
      +        "maxLength": 1000,
      +        "type": "string"
      +      },
      +      "invalidText": {
      +        "maxLength": 1000,
      +        "type": "string"
      +      },
      +      "thanksText": {
      +        "maxLength": 1000,
      +        "type": "string"
      +      },
      +      "type": {
      +        "const": "collectEmail",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "askText"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "delayMinutes": {
      +        "maximum": 1380,
      +        "minimum": 5,
      +        "type": "integer"
      +      },
      +      "onlyIfNoClick": {
      +        "description": "Default true: only when the link was not clicked.",
      +        "type": "boolean"
      +      },
      +      "text": {
      +        "maxLength": 1000,
      +        "type": "string"
      +      },
      +      "type": {
      +        "const": "followUp",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "text"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "amount": {
      +        "maximum": 9007199254740991,
      +        "minimum": 1,
      +        "type": "integer"
      +      },
      +      "type": {
      +        "const": "delay",
      +        "type": "string"
      +      },
      +      "unit": {
      +        "enum": [
      +          "minutes",
      +          "hours",
      +          "days"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "amount",
      +      "unit"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "answer": {
      +        "enum": [
      +          "text",
      +          "email",
      +          "number",
      +          "date",
      +          "birthday",
      +          "yesno"
      +        ],
      +        "type": "string"
      +      },
      +      "invalidText": {
      +        "maxLength": 1000,
      +        "type": "string"
      +      },
      +      "key": {
      +        "description": "The contact field the answer is saved to.",
      +        "pattern": "^[a-z0-9_]{1,30}$",
      +        "type": "string"
      +      },
      +      "noLabel": {
      +        "maxLength": 20,
      +        "type": "string"
      +      },
      +      "text": {
      +        "maxLength": 1000,
      +        "type": "string"
      +      },
      +      "type": {
      +        "const": "question",
      +        "type": "string"
      +      },
      +      "yesLabel": {
      +        "maxLength": 20,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "text",
      +      "key"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "tags": {
      +        "description": "Tag names to give the person, for example after collectEmail. A new name makes the tag. A tag can start an email automation once their address is confirmed.",
      +        "items": {
      +          "maxLength": 40,
      +          "minLength": 1,
      +          "type": "string"
      +        },
      +        "maxItems": 10,
      +        "minItems": 1,
      +        "type": "array"
      +      },
      +      "type": {
      +        "const": "addTag",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "tags"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "instruction": {
      +        "description": "What Postfjord's AI should do in the conversation from here, in the brand voice.",
      +        "maxLength": 1500,
      +        "type": "string"
      +      },
      +      "maxTurns": {
      +        "maximum": 10,
      +        "minimum": 1,
      +        "type": "integer"
      +      },
      +      "type": {
      +        "const": "aiReply",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "instruction"
      +    ],
      +    "type": "object"
      +  }
      +]
  2. First observed

TDQS

A4.8/5.0
Behavior5/5

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

Goes well beyond the annotations: discloses that the automation is created paused and answers nobody, that it needs the Draft scope, that the first call returns sameKeywords when another automation already answers those words, and that retries with the same idempotency_key return the first answer rather than duplicating. None of this is derivable from readOnlyHint/destructiveHint/idempotentHint.

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?

Extremely dense but nearly every clause carries distinct, actionable information, and the sibling differentiation is front-loaded. It is delivered as one long paragraph of semicolon-separated clauses, which makes the trigger and step enumerations harder to scan than a short list would be.

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

Completeness4/5

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

For a nested, multi-shape tool with no output schema, the description covers triggers, step ordering, unsupported step types, auth scope and retry semantics. The one gap is the return payload: it hints that the response can list sameKeywords but does not say what else comes back (e.g. the created automation id).

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

Parameters5/5

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

The description maps parameters to trigger types that the schema leaves ambiguous (hours for default_reply, postIds for comment_keyword, events for after_purchase, exactly one channel for ref_link) and adds ordering rules absent from the schema (steps run in order, aiReply must be last, addTag creates unknown tags). With 67% schema coverage, this compensates meaningfully rather than restating field names.

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 ('Creates a DM automation on Instagram or Facebook') and immediately scopes it against the sibling: 'an email series that starts by itself is postfjord_create_email_automation.' It also names the paused initial state, which an agent could not infer from the name alone.

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?

Explicitly routes away from the email sibling, states the approval workflow ('show the person you work for what it does and switch it on with postfjord_set_automation only after they approve'), and names the channel-id source (postfjord_list_channels in the schema). When-to-use, when-not-to-use and the follow-up tool are all present.

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