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"
]
}