@@ -1779,31 +1779,6 @@ Groups: ${groupNames.length > 0 ? groupNames.join(", ") : "(none)"}`,
17791779 { name : "network_skill_pull" } ,
17801780 ) ;
17811781
1782- // ─── Inject recall context as system message (hidden from chat UI) ───
1783- // `prependContext` (from before_agent_start) is prepended to user messages and
1784- // therefore visible in the chat box. To keep injected memories invisible to the
1785- // user while still feeding them to the model, we stash the recall result in
1786- // `pendingRecallContext` and inject it as a system-level message via the
1787- // `before_context_send` hook, which fires synchronously during prompt assembly.
1788- let pendingRecallContext : string | null = null ;
1789-
1790- api . on ( "before_context_send" , ( event : { messages : Array < { role : string ; content : string | unknown } > } ) => {
1791- if ( ! pendingRecallContext ) return ;
1792- const memoryContext = pendingRecallContext ;
1793- pendingRecallContext = null ;
1794- // Insert after the last system message (before the first user/assistant turn).
1795- // This keeps the static system prompt at the very beginning of the sequence so
1796- // KV-cache prefixes stay stable across requests — the provider can reuse the
1797- // cached keys/values for the system prompt even though the memory block changes.
1798- const firstNonSystemIdx = event . messages . findIndex ( ( m ) => m . role !== "system" ) ;
1799- if ( firstNonSystemIdx === - 1 ) {
1800- event . messages . push ( { role : "system" , content : memoryContext } ) ;
1801- } else {
1802- event . messages . splice ( firstNonSystemIdx , 0 , { role : "system" , content : memoryContext } ) ;
1803- }
1804- ctx . log . info ( `before_context_send: injected recall context as system message at idx=${ firstNonSystemIdx === - 1 ? event . messages . length - 1 : firstNonSystemIdx } (${ memoryContext . length } chars)` ) ;
1805- } ) ;
1806-
18071782 // ─── Auto-recall: inject relevant memories before agent starts ───
18081783
18091784 api . on ( "before_prompt_build" , async ( event : { prompt ?: string ; messages ?: unknown [ ] } , hookCtx ?: { agentId ?: string ; sessionKey ?: string } ) => {
@@ -1909,8 +1884,7 @@ Groups: ${groupNames.length > 0 ? groupNames.join(", ") : "(none)"}`,
19091884 "\n\nYou SHOULD call `skill_get` to retrieve the full guide before attempting the task." ;
19101885 ctx . log . info ( `auto-recall-skill (no-memory path): injecting ${ topSkills . length } skill(s)` ) ;
19111886 try { store . recordApiLog ( "skill_search" , { type : "auto_recall_skill" , query } , JSON . stringify ( topSkills ) , dur , true ) ; } catch { /* best-effort */ }
1912- pendingRecallContext = skillContext ;
1913- return { } ;
1887+ return { prependContext : skillContext } ;
19141888 }
19151889 } catch ( err ) {
19161890 ctx . log . debug ( `auto-recall-skill (no-memory path): failed: ${ err } ` ) ;
@@ -1919,11 +1893,11 @@ Groups: ${groupNames.length > 0 ? groupNames.join(", ") : "(none)"}`,
19191893
19201894 if ( query . length > 50 ) {
19211895 const noRecallHint =
1922- "## Memory system\n\n" +
1896+ "## Memory system — ACTION REQUIRED \n\n" +
19231897 "Auto-recall found no results for a long query. " +
1924- "Call `memory_search` with a shortened query (2-5 key words) before answering." ;
1925- pendingRecallContext = noRecallHint ;
1926- return { } ;
1898+ "You MUST call `memory_search` now with a shortened query (2-5 key words) before answering. " +
1899+ "Do NOT skip this step. Do NOT answer without searching first." ;
1900+ return { prependContext : noRecallHint } ;
19271901 }
19281902 return ;
19291903 }
@@ -1959,7 +1933,7 @@ Groups: ${groupNames.length > 0 ? groupNames.join(", ") : "(none)"}`,
19591933 } ) , dur , true ) ;
19601934 if ( query . length > 50 ) {
19611935 const noRecallHint =
1962- "## Memory system\n\n" +
1936+ "## Memory system — ACTION REQUIRED \n\n" +
19631937 "Auto-recall found no relevant results for a long query. " +
19641938 "You MUST call `memory_search` now with a shortened query (2-5 key words) before answering. " +
19651939 "Do NOT skip this step. Do NOT answer without searching first." ;
@@ -2011,9 +1985,11 @@ Groups: ${groupNames.length > 0 ? groupNames.join(", ") : "(none)"}`,
20111985 const tipsText = "\n\nAvailable follow-up tools:\n" + tips . join ( "\n" ) ;
20121986
20131987 const contextParts = [
2014- "## Recalled memories " ,
1988+ "## User's conversation history (from memory system) " ,
20151989 "" ,
2016- "The following facts were retrieved from previous conversations with this user. Treat them as established knowledge." ,
1990+ "IMPORTANT: The following are facts from previous conversations with this user." ,
1991+ "You MUST treat these as established knowledge and use them directly when answering." ,
1992+ "Do NOT say you don't know or don't have information if the answer is in these memories." ,
20171993 "" ,
20181994 lines . join ( "\n\n" ) ,
20191995 ] ;
@@ -2097,18 +2073,18 @@ Groups: ${groupNames.length > 0 ? groupNames.join(", ") : "(none)"}`,
20972073 } ) , recallDur , true ) ;
20982074 telemetry . trackAutoRecall ( filteredHits . length , recallDur ) ;
20992075
2100- ctx . log . info ( `auto-recall: stashing recall context for system message injection (${ context . length } chars), sufficient=${ sufficient } , skills=${ skillSection ? "yes" : "no" } ` ) ;
2076+ ctx . log . info ( `auto-recall: returning prependContext (${ context . length } chars), sufficient=${ sufficient } , skills=${ skillSection ? "yes" : "no" } ` ) ;
21012077
21022078 if ( ! sufficient ) {
21032079 const searchHint =
21042080 "\n\nIf these memories don't fully answer the question, " +
21052081 "call `memory_search` with a shorter or rephrased query to find more." ;
2106- pendingRecallContext = context + searchHint ;
2107- return { } ;
2082+ return { prependContext : context + searchHint } ;
21082083 }
21092084
2110- pendingRecallContext = context ;
2111- return { } ;
2085+ return {
2086+ prependContext : context ,
2087+ } ;
21122088 } catch ( err ) {
21132089 const dur = performance . now ( ) - recallT0 ;
21142090 store . recordToolCall ( "memory_search" , dur , false ) ;
0 commit comments