Skip to content

Context Handlers

Permission required: context_handler

Context handlers run before prompt assembly. They can enrich or modify the generation context that feeds into the assembler.

spindle.registerContextHandler(async (context) => {
  // Add custom data to the generation context
  return {
    ...context,
    myExtensionData: {
      customField: 'value',
    },
  }
}, 50) // priority: lower runs first (default: 100)

Use this when you need to influence how the prompt is built rather than modifying the final messages.

Generation context

The context object carries:

Field Type Description
chatId string Chat the generation targets.
generationType string 'normal', 'continue', 'regenerate', 'swipe', or 'impersonate'.
dryRun boolean true for tokenize/preview assemblies that never reach an LLM. Skip side effects when set.
userId string Requesting user.

Hosts that stamp these fields advertise it via spindle.contracts.preAssemblyGenerationContext >= 1. Check the contract before relying on them:

if ((spindle.contracts?.preAssemblyGenerationContext ?? 0) >= 1) {
  spindle.registerContextHandler(handler)
}

Cancelling a generation

Return the context with cancelGeneration: true to stop the generation before any LLM call. The host routes this through the same path as a user-initiated stop.

spindle.registerContextHandler(async (context) => {
  if (await shouldBlock(context)) {
    return { ...context, cancelGeneration: true }
  }
  return context
})

Timeout

Each invocation runs inside a 10-second wall-clock budget by default. Handlers that legitimately need longer can request a bigger budget at registration (clamped to 1s–120s):

spindle.registerContextHandler(handler, 100, { timeoutMs: 30_000 })

On timeout the host logs an error and continues with the previous context, so a slow handler delays but never blocks generation.

Context Handlers vs Interceptors

Context handlers run before prompt assembly and modify the context that drives assembly. Interceptors run after assembly and modify the final message array. Use context handlers when you need to affect how the prompt is constructed; use interceptors when you need to tweak the finished output.