Summary
If the extraction model answers with prose instead of tool calls, the memory agent treats that as "the agent has finished" and the document is finalized with 0 memories and status done. No error, no retry, no warning.
This is not the timeout path — there is no catchAndFallback, no skipping memory generation, nothing in the log except the finalized: N chunks, 0 memories line.
Evidence
Self-hosted, server v0.0.5, extraction LLM = local vLLM (Qwen3.6-35B-A3B-FP8). Captured with a logging proxy in front of the LLM.
Document A — the agent searched correctly, then narrated instead of acting:
call 1: prompt=2957 gen=477 finish=tool_calls → 5 × searchMemories ✅
call 2: prompt=23674 gen=159 finish=stop → NO tool calls
content: "I have a good understanding of the existing memories. Now let me
create the atomic memories from this document. The document is about
a specific bug/fix related to reasoning leaks in the Sovereign /run
endpoint. Key facts to extract: 1. On 2026-05-14, ..."
The agent announced the memories it was about to create — and stopped. finalized: 4 chunks, 0 memories, status done.
Document B — it never even got as far as searching:
call 1: prompt=3322 gen=1197 finish=stop → NO tool calls
content: "The user wants me to extract all atomic facts from a document about
a hermes plugin/hook API. I need to: 1. Search for existing memories..."
Pure chain-of-thought as plain text. finish_reason: stop. Document finalized empty.
Both documents are ordinary (3 090 and 3 638 characters). Re-running the same documents succeeds, so this is stochastic, not content-dependent.
Cause
Qwen3.6 (and other reasoning-tuned open models) sometimes emit their chain-of-thought as bare content instead of invoking tools — no <think> tags, just prose. The agent loop reads "no tool calls" as "the model is finished" and exits.
Rate in my backfill: 3 of 470 documents (0.6 %) — low, but permanent and silent, and it lands on whichever documents happen to draw the short straw.
What I'd ask for
- Do not treat a tool-call-free turn as completion when nothing was created yet. If the agent has produced zero memories and the model returned prose, re-prompt it — "you did not call any tool; call
CreateMemory" — and retry at least once. This alone would fix all three of my cases.
- Same ask as the timeout issue: do not finalize as
done when memoriesCreated === 0. Whatever the cause, an empty extraction should be distinguishable from a successful one via the API, not only via grep on the server log.
- Optional, and cheap: allow passing
chat_template_kwargs (e.g. {"enable_thinking": false}) through to an OpenAI-compatible endpoint. vLLM supports it, and it suppresses this class of leak at the source. Right now there is no way to set it.
Point 1 is the real fix — it is model-agnostic and costs one extra round trip in a rare case.
Note: the resulting empty document cannot be repaired through the API (re-ingesting unchanged content is skipped) — see #1300 and #1302.
Summary
If the extraction model answers with prose instead of tool calls, the memory agent treats that as "the agent has finished" and the document is finalized with 0 memories and status
done. No error, no retry, no warning.This is not the timeout path — there is no
catchAndFallback, noskipping memory generation, nothing in the log except thefinalized: N chunks, 0 memoriesline.Evidence
Self-hosted, server v0.0.5, extraction LLM = local vLLM (Qwen3.6-35B-A3B-FP8). Captured with a logging proxy in front of the LLM.
Document A — the agent searched correctly, then narrated instead of acting:
The agent announced the memories it was about to create — and stopped.
finalized: 4 chunks, 0 memories, statusdone.Document B — it never even got as far as searching:
Pure chain-of-thought as plain text.
finish_reason: stop. Document finalized empty.Both documents are ordinary (3 090 and 3 638 characters). Re-running the same documents succeeds, so this is stochastic, not content-dependent.
Cause
Qwen3.6 (and other reasoning-tuned open models) sometimes emit their chain-of-thought as bare
contentinstead of invoking tools — no<think>tags, just prose. The agent loop reads "no tool calls" as "the model is finished" and exits.Rate in my backfill: 3 of 470 documents (0.6 %) — low, but permanent and silent, and it lands on whichever documents happen to draw the short straw.
What I'd ask for
CreateMemory" — and retry at least once. This alone would fix all three of my cases.donewhenmemoriesCreated === 0. Whatever the cause, an empty extraction should be distinguishable from a successful one via the API, not only viagrepon the server log.chat_template_kwargs(e.g.{"enable_thinking": false}) through to an OpenAI-compatible endpoint. vLLM supports it, and it suppresses this class of leak at the source. Right now there is no way to set it.Point 1 is the real fix — it is model-agnostic and costs one extra round trip in a rare case.
Note: the resulting empty document cannot be repaired through the API (re-ingesting unchanged content is skipped) — see #1300 and #1302.