Engagements

Inbound interactions to triage and respond to.

4 actions. Each is callable by the agent as a tool, over HTTP via /api/invoke, and (usually) from a UI page.

engagements.list

GET

List inbound engagements (comments / mentions / DMs), optionally filtered by mission.

  • AI tool: engagements_list
  • API: GET /api/invoke/engagements.list

Input

Field Type Required Description
missionId string
limit integer
offset integer
orderBy string
orderDir "asc" | "desc"
q string
JSON Schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "missionId": {
      "type": "string",
      "minLength": 1
    },
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 500
    },
    "offset": {
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "orderBy": {
      "type": "string"
    },
    "orderDir": {
      "type": "string",
      "enum": [
        "asc",
        "desc"
      ]
    },
    "q": {
      "type": "string"
    }
  }
}

engagements.create

POST · mutating

Record an inbound engagement (comment / mention / DM / reaction). Automatically resolves sourceTicketId from the supplied sourceUrl or externalParentId — so engagements.respond can later attribute the reply to the SAME persona that posted the original. Called by webhooks, channel ingestion, or manually when triaging a screenshot.

When the agent calls it: Pass sourceUrl whenever you have it — that's what lets engagements.respond pick the right persona via continuity. Without it, replies fall back to the picker.

  • AI tool: engagements_create
  • API: POST /api/invoke/engagements.create

Input

Field Type Required Description
missionId string yes
type "comment" | "mention" | "dm" | "reply" | "reaction" yes
platform string yes
authorName string yes
authorHandle string
authorFollowers integer
authorVerified boolean
content string yes
sentiment "positive" | "neutral" | "negative" | "mixed"
intent string
timestamp any
sourceUrl string
externalParentId string
pledgeAmountCents integer
rewardTierId string
JSON Schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "missionId": {
      "type": "string",
      "minLength": 1
    },
    "type": {
      "type": "string",
      "enum": [
        "comment",
        "mention",
        "dm",
        "reply",
        "reaction"
      ]
    },
    "platform": {
      "type": "string"
    },
    "authorName": {
      "type": "string"
    },
    "authorHandle": {
      "type": "string"
    },
    "authorFollowers": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "authorVerified": {
      "type": "boolean"
    },
    "content": {
      "type": "string"
    },
    "sentiment": {
      "type": "string",
      "enum": [
        "positive",
        "neutral",
        "negative",
        "mixed"
      ]
    },
    "intent": {
      "type": "string"
    },
    "timestamp": {},
    "sourceUrl": {
      "type": "string",
      "format": "uri"
    },
    "externalParentId": {
      "type": "string"
    },
    "pledgeAmountCents": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "rewardTierId": {
      "type": "string"
    }
  },
  "required": [
    "missionId",
    "type",
    "platform",
    "authorName",
    "content"
  ]
}

engagements.respond

POST · mutating

Send a reply to an inbound engagement. The reply is attributed to a persona resolved in this order: caller-passed personaSubjectId → engagement.sourceTicketId's personaSubjectId (continuity — reply from the SAME account that posted the original) → weighted picker over the mission's personas → the mission's primary subject. When the resolved persona has an active browser_session for the platform, Stagehand delivers the reply automatically; otherwise the reply is recorded as queued.

When the agent calls it: You normally do NOT need to pass personaSubjectId — the handler resolves it from continuity (the persona that posted the original) automatically. Override only when the user explicitly says "reply from " instead. If the resolved persona has no session for the platform, the response is queued. Surface this to the user: "I drafted the reply as @ but they have no session yet — authenticate in /integrations to enable auto-delivery."

  • AI tool: engagements_respond
  • API: POST /api/invoke/engagements.respond

Input

Field Type Required Description
id string yes
response string
respondedBy string
respondedByType "human" | "ai-agent"
personaSubjectId string
JSON Schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "minLength": 1
    },
    "response": {
      "type": "string"
    },
    "respondedBy": {
      "default": "agent",
      "type": "string"
    },
    "respondedByType": {
      "default": "ai-agent",
      "type": "string",
      "enum": [
        "human",
        "ai-agent"
      ]
    },
    "personaSubjectId": {
      "type": "string",
      "minLength": 1
    }
  },
  "required": [
    "id"
  ]
}

engagements.ignore

POST · mutating

Mark an engagement as ignored — no reply will be sent.

  • AI tool: engagements_ignore
  • API: POST /api/invoke/engagements.ignore

Input

Field Type Required Description
id string yes
JSON Schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "minLength": 1
    }
  },
  "required": [
    "id"
  ]
}