Follow-ups: never forget who we are waiting on
Status: not live yet. The contract below is enforced by the event bridge (client tooling that runs next to a
bot, not part of the GoodQA server), switched off per org by default (orgs.<id>.followups.enabled in the bridge
config). Nothing here changes the API, the OpenAPI document, MCP tools or /v1/me: a follow-up is an ordinary ticket,
so any agent can keep follow-ups today with the routes below.
The record is a ticket
A follow-up is a GoodQA ticket with isBlocked: true, needsUserId (the person we wait on) and blockedReason
(exactly what is awaited), plus dueDate for a dated reminder. GoodQA's own "blocked, needs X" notifications, My Tasks
and the overdue notification then remind the person. The org's follow-up project must include everyone the bot follows
up with: GoodQA refuses to block a ticket on someone without access to its project.
The contract an unattended turn must end with
<followups>[
{"op": "create", "operationId": "remind-counsel-thu", "kind": "reminder",
"title": "Remind Sam: counsel pages", "who": "me",
"needs": "Sam to say yes/no on sending the pages to counsel", "due": "2026-10-08"}
]</followups>
| Field | Rule |
|---|---|
op | create, update (needs ticket) or resolve (needs ticket) |
operationId | 6-128 of A-Z a-z 0-9 . _ : -, unique in the block; the idempotency key |
kind | ask, decision, reminder (needs due) or topic |
who / needs | required to create or update: "me", a user id or a member's email / what is awaited |
crm | optional: one of contactId/companyId and a note (a CRM timeline note) |
Nothing open is <followups>[]</followups>. Validation is all-or-nothing. A missing or invalid block gets one
extraction retry, then an escalation line (followups_missing / followups_invalid); a refused write escalates as
followups_apply_failed. The person always gets the normal reply.
How it is applied (ordinary routes, persona key)
- create:
POST /v1/projects/{projectId}/issueswith a derivedoperationId, thenPATCH /v1/issues/{issueId}(isBlocked,needsUserId,blockedReason); - update / resolve:
PATCH /v1/issues/{issueId}, plus a comment saying what answered it; - crm:
POST /v1/orgs/{orgId}/crm/timeline(best effort, CRM is per-org).
Scope: update and resolve reach only tickets in the org's follow-up projects.
Reference
- API reference:
/projects/{projectId}/issuesand/issues/{issueId}in/v1/openapi.json(tagissues). - MCP tools:
create_issue,update_issue,comment_on_issue,list_issues(see the MCP tool reference). - Runbook: event messaging runbook (the bridge that enforces the contract) and persona memory (lanes and digests extend the same block).