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>
FieldRule
opcreate, update (needs ticket) or resolve (needs ticket)
operationId6-128 of A-Z a-z 0-9 . _ : -, unique in the block; the idempotency key
kindask, decision, reminder (needs due) or topic
who / needsrequired to create or update: "me", a user id or a member's email / what is awaited
crmoptional: 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}/issues with a derived operationId, then PATCH /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}/issues and /issues/{issueId} in /v1/openapi.json (tag issues).
  • 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).

We use essential cookies to keep you signed in. See our Privacy Policy for details.