LearnNewsExamplesServices
Frontmatter
id12742
titleDefault summarization + mini-summary to a local provider (remote opt-in)
stateClosed
labels
bugaiarchitectureperformancemodel-experience
assigneesneo-opus-grace
createdAtJun 8, 2026, 10:00 AM
updatedAtJun 8, 2026, 5:06 PM
githubUrlhttps://github.com/neomjs/neo/issues/12742
authorneo-opus-grace
commentsCount2
parentIssue12740
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtJun 8, 2026, 2:53 PM

Default summarization + mini-summary to a local provider (remote opt-in)

Closed v13.0.0/archive-v13-0-0-chunk-17 bugaiarchitectureperformancemodel-experience
neo-opus-grace
neo-opus-grace commented on Jun 8, 2026, 10:00 AM

Context

The 2026-06-08 €50+ Gemini cost incident (~1,200 req/min) root-caused to the memory miniSummary backfill calling remote gemini-3.5-flash instead of a local fast model. This is the actionable fix for the root cause identified in #12713 ("mini-summaries should be cheap"). Operator directive: "mini-summaries → configurable remote/local, default local. No remote call to summarize 5k chars → a tweet."

Incident timeline (orchestrator.log): 06:43:24Z Starting memory miniSummary backfill (pending-memory-minisummary:50) looping back-to-back; after the operator's gemini-2.5→3.5-flash switch made the calls succeed (they were failing 00:00–02:00), the backfill drained the pending backlog over the billed remote API → 429-retry storm → €50+.

The Problem

Summarization (session + mini-summary) is cheap by design — compress a ~5k-char memory to a tweet-sized summary — and belongs on a local model (gemma4). It currently resolves to remote Gemini Flash by default, which is (a) needlessly expensive, (b) network/quota-failure-prone (the #12713 hang AND this cost storm), and (c) a per-item cost multiplier across a backlog.

Root cause: aiConfig.modelProvider defaults to 'gemini' and is shared between the chat/agent path and the summarization path, so summarization inherits the remote default whenever NEO_MODEL_PROVIDER is unset.

The Architectural Reality

  • ai/config.template.mjs:136modelProvider: leaf('gemini', 'NEO_MODEL_PROVIDER', 'string') — default 'gemini', shared by chat + summarization.
  • ai/services/memory-core/SessionService.mjs:241 (session summary) + ai/services/memory-core/MemoryService.mjs:713 (mini-summary) — resolve aiConfig.modelProviderbuildChatModel(...) → Gemini client on 'gemini'.
  • Local providers already exist: graphProvider / embeddingProvider default 'openAiCompatible' (local), localModels.ollama.model = 'gemma4:31b'. The local summarization path is available; only the default/routing is wrong.
  • ADR 0019 (AiConfig reactive-Provider SSOT) owns the config; this is a declarative-leaf change, read at the use site.

The Fix

Decouple the summarization provider from the chat/agent modelProvider, defaulting summarization to local; remote is explicit opt-in:

  • Introduce a summarization-scoped provider resolution (e.g. a summaryProvider leaf, or a documented derivation) that defaults to a local provider (ollama / openAiCompatible → gemma4), independent of the chat/agent provider.
  • SessionService + MemoryService summary paths read the summarization provider (not the shared chat modelProvider).
  • Remote (Gemini) summarization requires an explicit opt-in (env or config), never the silent default.
  • Declarative + by-construction (ADR 0019) — no runtime singleton mutation.

Contract Ledger

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
summarization provider (new/derived leaf) ADR 0019 AiConfig SSOT default LOCAL (gemma4 via ollama/openAiCompatible); remote = explicit opt-in local provider; if local unavailable, fail loud (NOT silent remote) learn/agentos/AiConfigModel.md + ADR 0019 this incident (orchestrator.log 06:43:24Z); config.template.mjs:136
SessionService / MemoryService summary calls the summarization-provider leaf read summarization provider, not chat modelProvider service JSDoc SessionService.mjs:241, MemoryService.mjs:713

Decision Record impact

aligned-with ADR 0019 — a declarative config-leaf addition/derivation within the reactive Provider SSOT (default local, read at use site). No mutation / aliasing.

Acceptance Criteria

  • With NEO_MODEL_PROVIDER unset, session + mini-summary resolve to a local provider (gemma4) — verified by a by-construction config test (ADR 0019, not singleton mutation).
  • Remote (Gemini) summarization is reachable only via an explicit opt-in (env/config), never the silent default.
  • Summarization provider is decoupled from the chat/agent modelProvider (agents' provider choice unaffected, or the shared-default change is explicitly justified).
  • (inherited from #12713) mini-summaries are reliably cheap/fast on the local path (bounded; no remote network dependency).
  • No runtime mutation of the shared AiConfig singleton (B4 / ADR 0019).

Out of Scope

  • Backfill loop-safety (rate-limit / no-back-to-back / bounded 429-retry) — separate ticket (the runaway amplifier).
  • Live-remote-AI test isolation (QA/Librarian skip(!KEY) inversion) — separate (Refs #12435).
  • KB-ask provider configurability — gpt's #12737.
  • API key spend-cap / rotation — operator / console.

Avoided Traps

  • Just rate-limiting the remote calls — treats the symptom; the root is the wrong (remote) default for cheap summarization.
  • Changing the SHARED modelProvider default to local without decoupling — could silently downgrade chat/agent quality; summarization needs its own scoped default.
  • Snapshot/restore test isolationrestore() is itself a B4 singleton mutation (ADR 0019, the #12660 Drop); isolate by construction.

Related

  • #12713 — root-cause origin ("mini-summaries should be cheap"); this ticket is its fix. Recommend #12722 (abort-guard) Refs (not Resolve) #12713, with #12713's "reliably cheap" AC carried here.
  • #12456 — AiConfig-SSOT antipattern epic (ADR 0019). #12435 — test-isolation (B4). #12737 — KB-ask provider (gpt, sibling path). #12712 / #12722 — symptom guards (timeout / abort).
  • €50 Gemini cost incident, 2026-06-08.

Live latest-open sweep: checked latest 25 open issues at 2026-06-08T07:54Z; closest is #12713 (root-cause investigation — this is its fix, Refs not dup) + gpt's #12737 (KB-ask, distinct path). No equivalent fix ticket exists.

Origin Session ID: 1cf2ad9f-28af-4242-9069-fd14c04e1b62

Retrieval Hint: query_raw_memories("Gemini cost incident miniSummary backfill modelProvider default local") or commit-range anchor on the orchestrator.log 06:43:24Z backfill loop.

Authored by Claude Opus 4.8 (Claude Code), @neo-opus-grace.

tobiu referenced in commit 018e569 - "fix(ai): default model/summary provider to local, remote opt-in (#12742) (#12760) on Jun 8, 2026, 2:53 PM
tobiu closed this issue on Jun 8, 2026, 2:53 PM