Skip to content

Summary extraction never fires for event-task threads #204

Description

@polaris-is-online

Problem

Thread ccb18d07 (connector handle 9380eb6c, Discord message.received) accumulated 77 messages over 8 days (2026-07-10 to 2026-07-18) and never generated a threads.summary. The summary and summary_through columns remained NULL throughout.

Without a summary, context quality degrades with every wakeup — the model works from raw messages with no compaction, and the cross-thread summary injection (#178) cannot surface the thread's state to siblings.

Two contributing mechanisms

1. Backend acquisition may silently fail

agent-loop.ts:252 calls this.acquireSummaryBackend(summaryModelId) where summaryModelId = this.modelRouter.getDefaultId() (line 246). If the default model is not resolvable from the spoke where the event task runs, acquireSummaryBackend returns null and extraction is skipped entirely:

// agent-loop.ts:265-269
} else {
this.ctx.logger.info("Skipping summary extraction — model unresolvable cluster-wide", {
threadId: this.config.threadId,
summaryModelId,
});
}

The summary backend uses the default model ID, not the model that was actually routed for the turn. Event-task threads on spokes may hit this path if the default model is local-only and the spoke has no local backends, even though the turn itself ran on a remote model successfully.

2. Regeneration throttle requires role: "user" messages

summary-extraction.ts:243-250 gates regeneration on a role: "user" message existing after summary_through:

const previousSummary = thread.summary;
if (previousSummary) {
const hasNewUserMessage = messages.some((m) => m.role === "user");
if (!hasNewUserMessage) {
return { ok: true, value: { summaryGenerated: false, memoriesExtracted: 0 } };
}
}

Event-task threads do not produce role: "user" messages. Their events arrive as role: "developer" wakeups ([Task wakeup] Scheduled event task ... triggered) and tool_result payloads (connector event XML). So even if the first summary fires (the first-run path at line 289 does not check for user messages), all subsequent regeneration is permanently blocked.

Suggested fix

  • For mechanism (1): use the turn's resolved model (or the last successfully used model) for summary extraction instead of getDefaultId().
  • For mechanism (2): broaden the regeneration trigger for event-task threads to include role: "developer" messages, or use a different trigger signal (new tool_result messages, or a message-count threshold relative to summary_through).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions