Skip to content

Pluggable resolution strategy

The escalation boundarySDKLTEscalationStrategyescalationStrategyRegistryonResolution

One registered class decides what a resolution does: re-run the step or hand it to triage. Routing rules live in code you own.

The situation

Your team wants triage only for one document type, and only when the reviewer left a note. The built-in strategies are all-or-nothing; the decision belongs in your own code.

The recipe

strategies/notes-triage.ts
import type { LTEscalationStrategy, ResolutionContext, ResolutionDirective } from '@hotmeshio/long-tail';
export class NotesTriageStrategy implements LTEscalationStrategy {
async onResolution(context: ResolutionContext): Promise<ResolutionDirective> {
const { escalation, resolverPayload } = context;
if (escalation.type === 'intake' && resolverPayload?.notes) {
return { action: 'triage', triageEnvelope: buildTriageEnvelope(context) };
}
return { action: 'rerun' };
}
}
start.ts
await start({
database: { connectionString: process.env.DATABASE_URL },
workers: [/* ... */],
escalation: { adapter: new NotesTriageStrategy() },
});

The strategy sees the escalation record, the resolver’s payload and the original envelope, and returns a directive. Register it through start() or with escalationStrategyRegistry.register(...).

The guarantee

The resolution route consults the registered strategy before it starts a re-run, every time. With no strategy configured the default applies and always answers rerun. Swapping the strategy changes routing without touching any workflow. See Triage.