One row, many resolvers
conditionalresolveresolveBySignalKeyresolve_by_signal_keyA person, a service, an operator, an agent or a machine can resolve the same row. The workflow receives the same typed answer either way.
The situation
An inspection row is usually resolved by a person at a bench. Some days a vision service answers first, or an agent clears a backlog, or an operator scripts a fix. The workflow should not care which.
The recipe
const result = await conditional<{ pass: boolean }>(`inspect-${serialNumber}`, { role: 'inspection', metadata: { serialNumber },});# HTTP (a service or webhook)curl -X POST https://lt.acme.dev/api/escalations/resolve-by-signal-key \ -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \ -d '{ "signalKey": "inspect-SN-123", "resolverPayload": { "pass": true } }'
# CLI (an operator)ltc esc resolve $ESCALATION_ID --data '{"pass": true}'await lt.escalations.resolveBySignalKey({ signalKey: 'inspect-SN-123', resolverPayload: { pass: true } });The dashboard renders the role’s form for a person. An agent calls the resolve_by_signal_key MCP tool. A scan rule or a machine on MQTT resolves through the same endpoints.
The guarantee
Exactly one resolve wins. It marks the row resolved and delivers the payload to the waiting workflow in one guarded transaction; every later attempt answers 409. Every surface runs the same RBAC and, for roles that enforce, the same schema gate. See Conditional.
Related patterns
Resolving from anywhere
Resolve by signal key
A webhook that knows the deterministic signal id resumes the exact waiting workflow, with no id lookup and no facet to duplicate.
Resolving from anywhere
Resolve by domain key
A caller that knows only orderId resolves the right row in one atomic statement, with no lookup of the escalation id first.
The physical world
A machine is a resolver
A workflow parks a row and waits; a machine resolves it over MQTT exactly as a person would from the dashboard.
Agents and MCP
Humans as tools
An agent routes work to a person through the same tool protocol it uses for everything else, and gets the typed answer back.
