feat(openclaw): add recallInjectionPosition config to preserve prompt cache (#710)

* feat(openclaw): add recallInjectionPosition config to preserve prompt cache

Add configurable injection position for recalled memories to avoid
breaking prefix-based prompt caching (Anthropic/Google) when agents
have large static system prompts.

Options: 'prepend' (default, current behavior), 'append' (end of
system prompt, preserves cache), 'user' (before user message).

Closes #703

* docs(openclaw): document all plugin config flags

Add missing config options to the OpenClaw docs: recallTopK,
recallTypes, recallContextTurns, recallMaxQueryChars,
recallPromptPreamble, recallInjectionPosition, recallRoles,
retainEveryNTurns, retainOverlapTurns, and debug.
This commit is contained in:
Nicolò Boschi 2026-03-26 16:09:25 +01:00 committed by GitHub
parent c9ff37dcbf
commit 200bab233e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 25 additions and 3 deletions

View file

@ -102,6 +102,16 @@ Optional settings in `~/.openclaw/openclaw.json`:
- `retainRoles` - Which message roles to retain (default: `["user", "assistant"]`). Options: `user`, `assistant`, `system`, `tool`
- `recallBudget` - Recall effort: `"low"`, `"mid"`, or `"high"` (default: `"mid"`). Higher budgets use more retrieval strategies for better results.
- `recallMaxTokens` - Max tokens for recall response (default: `1024`). Controls how much memory context is injected per turn.
- `recallTopK` - Max number of memories to inject per turn (default: unlimited).
- `recallTypes` - Memory types to recall (default: `["world", "experience"]`). Options: `world`, `experience`, `observation`.
- `recallContextTurns` - Number of prior user turns to include in the recall query (default: `1`).
- `recallMaxQueryChars` - Max characters for the composed recall query (default: `800`).
- `recallPromptPreamble` - Custom preamble text placed above recalled memories. Overrides the built-in guidance text.
- `recallInjectionPosition` - Where to inject recalled memories: `"prepend"` (default), `"append"`, or `"user"`. Use `"append"` to preserve prompt caching with large static system prompts. Use `"user"` to inject before the user message instead of in the system prompt.
- `recallRoles` - Which message roles to include when composing the contextual recall query (default: `["user", "assistant"]`).
- `retainEveryNTurns` - Retain every Nth turn (default: `1` = every turn). Values > 1 enable chunked retention.
- `retainOverlapTurns` - Extra prior turns included when chunked retention fires (default: `0`).
- `debug` - Enable debug logging (default: `false`).
### Memory Isolation

View file

@ -726,6 +726,7 @@ function getPluginConfig(api: MoltbotPluginAPI): PluginConfig {
typeof config.recallPromptPreamble === 'string' && config.recallPromptPreamble.trim().length > 0
? config.recallPromptPreamble
: DEFAULT_RECALL_PROMPT_PREAMBLE,
recallInjectionPosition: typeof config.recallInjectionPosition === 'string' && ['prepend', 'append', 'user'].includes(config.recallInjectionPosition) ? config.recallInjectionPosition as PluginConfig['recallInjectionPosition'] : undefined,
debug: config.debug ?? false,
};
}
@ -1141,9 +1142,18 @@ ${memoriesFormatted}
debug(`[Hindsight] Auto-recall: Injecting ${results.length} memories from bank ${bankId}`);
// Inject recalled memories into system prompt space so they stay hidden from
// the end-user transcript/UI while still being available to the model.
return { prependSystemContext: contextMessage };
// Inject recalled memories. Position is configurable to preserve prompt caching
// when agents have large static system prompts.
const position = pluginConfig.recallInjectionPosition || 'prepend';
switch (position) {
case 'append':
return { appendSystemContext: contextMessage };
case 'user':
return { prependContext: contextMessage };
case 'prepend':
default:
return { prependSystemContext: contextMessage };
}
} catch (error) {
if (error instanceof DOMException && error.name === 'TimeoutError') {
console.warn(`[Hindsight] Auto-recall timed out after ${RECALL_TIMEOUT_MS}ms, skipping memory injection`);

View file

@ -3,6 +3,7 @@
export interface PluginPromptHookResult {
prependContext?: string;
prependSystemContext?: string;
appendSystemContext?: string;
}
export interface MoltbotPluginAPI {
@ -71,6 +72,7 @@ export interface PluginConfig {
recallContextTurns?: number; // Number of user turns to include in recall query context. Default: 1 (latest only)
recallMaxQueryChars?: number; // Max chars for composed recall query. Default: 800
recallPromptPreamble?: string; // Prompt preamble placed above recalled memories. Default: built-in guidance text.
recallInjectionPosition?: 'prepend' | 'append' | 'user'; // Where to inject recalled memories. 'prepend' = start of system prompt (default), 'append' = end of system prompt (preserves prompt cache), 'user' = before user message.
debug?: boolean; // Enable debug logging (default: false)
}