Skip to content

Commit 69d45f4

Browse files
committed
docs: proactive engagement (P6) - config keys, CLI, scheduler memory note
1 parent 1f4203d commit 69d45f4

4 files changed

Lines changed: 58 additions & 1 deletion

File tree

docs/CONFIG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,12 @@ Every config knob has a `ODEK_*` counterpart:
133133
| `ODEK_MEMORY_EXTENDED_MAX_SIZE_MB` | `--memory-extended-max-size-mb` | int |
134134
| `ODEK_MEMORY_EXTENDED_ATOM_MAX_CHARS` | `--memory-extended-atom-max-chars` | int |
135135
| `ODEK_MEMORY_EXTENDED_MEMORY_BUDGET_CHARS` | `--memory-extended-memory-budget-chars` | int |
136+
| `ODEK_MEMORY_EXTENDED_FOLLOW_UP_SUGGESTIONS_ENABLED` || bool |
137+
| `ODEK_MEMORY_EXTENDED_FOLLOW_UP_SUGGESTION_MIN_CONFIDENCE` || float |
138+
| `ODEK_MEMORY_EXTENDED_PROACTIVE_NUDGES_ENABLED` || bool |
139+
| `ODEK_MEMORY_EXTENDED_NUDGE_MAX_PER_DAY` || int |
140+
| `ODEK_MEMORY_EXTENDED_NUDGE_COOLDOWN_HOURS` || int |
141+
| `ODEK_MEMORY_EXTENDED_NUDGE_STALE_GOAL_DAYS` || int |
136142
| `ODEK_GUARD_PROVIDER` | `--guard-provider` | string |
137143
| `ODEK_GUARD_URL` | `--guard-url` | string |
138144
| `ODEK_GUARD_BATCH_URL` | `--guard-batch-url` | string |
@@ -421,6 +427,12 @@ The `memory` section controls the persistent memory system (see [docs/MEMORY.md]
421427
| `predictive_intents` | `3` ||| Reserved for future predictive-intent recall (P5). Currently accepted but ignored. |
422428
| `auto_extract_per_turn` | `true` ||| Extract atoms after every user message. |
423429
| `infer_user_state` | `true` ||| Reserved for future user-state model inference (P3). Currently accepted but ignored. |
430+
| `follow_up_suggestions_enabled` | `true` | `ODEK_MEMORY_EXTENDED_FOLLOW_UP_SUGGESTIONS_ENABLED` || Capture high-confidence predicted intents at recall time as follow-up suggestions (zero extra LLM cost). |
431+
| `follow_up_suggestion_min_confidence` | `0.6` | `ODEK_MEMORY_EXTENDED_FOLLOW_UP_SUGGESTION_MIN_CONFIDENCE` || Minimum predicted-intent confidence for a follow-up suggestion. |
432+
| `proactive_nudges_enabled` | `false` | `ODEK_MEMORY_EXTENDED_PROACTIVE_NUDGES_ENABLED` || Master switch for proactive nudge delivery (`TakeNudges`). Opt-in. |
433+
| `nudge_max_per_day` | `1` | `ODEK_MEMORY_EXTENDED_NUDGE_MAX_PER_DAY` || Maximum proactive nudges delivered per day. |
434+
| `nudge_cooldown_hours` | `24` | `ODEK_MEMORY_EXTENDED_NUDGE_COOLDOWN_HOURS` || Per-kind cooldown before a nudge of the same kind can fire again. |
435+
| `nudge_stale_goal_days` | `7` | `ODEK_MEMORY_EXTENDED_NUDGE_STALE_GOAL_DAYS` || Days without activity before a goal/intent atom counts as stale for nudges. |
424436
| `llm` | omitted ||| Dedicated memory LLM. If omitted, the main agent LLM is reused. A warning is emitted if that model has thinking enabled. |
425437
| `embedding` | omitted ||| Dedicated embedding backend for atoms. If omitted, inherits `memory.embedding` or the shared top-level `embedding`. |
426438

docs/EXTENDED_MEMORY.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,12 @@ Extended Memory is configured under the `memory.extended` section.
380380
"style_mirroring_enabled": true,
381381
"anaphora_resolution_enabled": true,
382382
"follow_up_anticipation_enabled": true,
383+
"follow_up_suggestions_enabled": true,
384+
"follow_up_suggestion_min_confidence": 0.6,
385+
"proactive_nudges_enabled": false,
386+
"nudge_max_per_day": 1,
387+
"nudge_cooldown_hours": 24,
388+
"nudge_stale_goal_days": 7,
383389

384390
"llm": {
385391
"base_url": "http://localhost:11434/v1",
@@ -428,6 +434,12 @@ Extended Memory is configured under the `memory.extended` section.
428434
| `style_mirroring_enabled` | `true` | Inject a style-guidance directive based on the inferred user model. |
429435
| `anaphora_resolution_enabled` | `true` | Resolve the first pronoun in a user message against recent trusted atoms when the top atom's score is high enough. |
430436
| `follow_up_anticipation_enabled` | `true` | Generate predicted intents and recall atoms for them. |
437+
| `follow_up_suggestions_enabled` | `true` | Capture high-confidence predicted intents at recall time and expose them as follow-up suggestions (zero extra LLM cost). |
438+
| `follow_up_suggestion_min_confidence` | `0.6` | Minimum predicted-intent confidence for a follow-up suggestion to be captured. |
439+
| `proactive_nudges_enabled` | `false` | Master switch for proactive nudge delivery via `TakeNudges`. Opt-in. |
440+
| `nudge_max_per_day` | `1` | Maximum proactive nudges delivered per day. |
441+
| `nudge_cooldown_hours` | `24` | Per-kind cooldown before a nudge of the same kind can fire again. |
442+
| `nudge_stale_goal_days` | `7` | Days without activity before a goal/intent atom counts as stale for nudges. |
431443
| `llm` | omitted | Dedicated memory LLM config. **If omitted, the default global model is used.** A warning is emitted if that model has thinking enabled. |
432444
| `embedding` | omitted | Dedicated embedding backend. If omitted, uses the shared `embedding` config. |
433445

@@ -513,6 +525,32 @@ Once Extended Memory is enabled, the following proactive behaviors are active by
513525

514526
These behaviors are always data-driven by trusted atoms and the user model, never by tainted content.
515527

528+
## P6 — Proactive Engagement
529+
530+
P6 turns Extended Memory from a passive recall layer into a source of proactive, user-facing suggestions. All three surfaces are read-only over trusted atoms and degrade to "nothing" on any failure — a broken LLM backend or malformed response can never break a session.
531+
532+
### Follow-up suggestions
533+
534+
Predictive recall (P5) already generates likely follow-up intents on every recall to widen the search. P6 captures those intents instead of discarding them: after the `minPredictedIntentConfidence` (0.3) noise floor, intents at or above `follow_up_suggestion_min_confidence` (default `0.6`) are kept — at most 3 per recall — and exposed via `ExtendedMemory.LastFollowUps()` / `MemoryManager.FollowUpSuggestions()` for the CLI/Web/Telegram surfaces to render as suggested next steps. The capture costs zero extra LLM calls (it reuses the prediction the recall pipeline already paid for) and is replaced on every recall. Disable with `follow_up_suggestions_enabled: false` (recall behavior is unchanged either way).
535+
536+
### Open loops
537+
538+
The extraction prompt now emits `question` atoms for user questions that went unanswered in the session and `goal` atoms for stated intentions ("I want to…", "we should…", "next week I'll…"). Commands and action requests are still rejected. Exact and semantic write-path dedup collapse repeats automatically.
539+
540+
`ExtendedMemory.OpenLoops(ctx, limit)` returns the trusted `question`/`goal`/`intent` atoms, newest first — the machine-readable "what is still open" view that powers the nudges engine and any presentation-layer listing. Tainted atoms are always excluded.
541+
542+
### Proactive nudges
543+
544+
`ExtendedMemory.ProactiveNudges(ctx, maxN)` (preview) and `ExtendedMemory.TakeNudges(ctx, maxN)` (delivery) synthesize up to `maxN` (default 2) concise, user-facing nudges from: open loops, stale goals (goal/intent atoms with no activity in `nudge_stale_goal_days`, default 7), and the user model's current focus (blockers, project drift). Each nudge carries a `kind` (`open_question`, `stale_goal`, `blocker`, `drift`) and the source atom IDs it was derived from. Synthesis is a single memory-LLM call with defensive JSON parsing; any failure returns an empty result with no error.
545+
546+
Anti-annoyance caps are enforced by `TakeNudges` only and persisted to `nudges.json` in the extended directory (atomic, 0600):
547+
548+
- **Master switch**: `proactive_nudges_enabled` (default `false` — strictly opt-in).
549+
- **Daily budget**: at most `nudge_max_per_day` nudges per day (default `1`); the budget resets on day rollover, per-kind cooldowns persist.
550+
- **Per-kind cooldown**: a kind that fired cannot fire again within `nudge_cooldown_hours` (default `24`).
551+
552+
`ProactiveNudges` is a pure preview: it computes nudges without checking or recording any cap, so a CLI/Telegram "what would you nudge me about?" surface never consumes the daily budget. `MemoryManager.PreviewNudges` / `MemoryManager.TakeNudges` are nil-safe passthroughs that return empty when Extended Memory is disabled.
553+
516554
## Security Architecture
517555

518556
Extended Memory inherits and extends the provenance model from [MEMORY.md](MEMORY.md).
@@ -565,6 +603,7 @@ This runs memory extraction, user-state inference, predictive intent generation,
565603
| **P3 — User-state model** | Background inference of a persistent user model, pending-review queue, user correction flow. | Implemented |
566604
| **P4 — Quarantine and promotion** | Tainted atom quarantine, inline promotion commands, `quarantine_ttl_days`, atom pinning. | Implemented |
567605
| **P5 — Predictive and proactive surfaces** | Predicted-intent recall, return-after-break summary, anaphora resolution, style mirroring, follow-up anticipation. | Implemented |
606+
| **P6 — Proactive engagement** | Follow-up suggestions captured at recall time, open-loop (`question`/`goal`) atoms, proactive nudges engine with daily budget and per-kind cooldown. | Implemented |
568607

569608
## Relationship to Existing Memory
570609

docs/MEMORY.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,9 @@ Key properties:
169169
- **Trust boundary**: per-turn extraction only produces `user_said` atoms. Tainted source classes (`tool_output`, `file_read`, `web`, `mcp`, `subagent`, `agent_generated`, `inferred`) can be stored but are quarantined and excluded from recall until promoted.
170170
- **Size cap**: defaults to 100 MB with `retention_decay` eviction; pinned atoms are never evicted.
171171
- **Tool surface**: `memory` tool actions `add_atom`, `search_atoms`, `forget_atom`, `pin_atom`, `list_quarantine`, `confirm_pending_review`, `reject_pending_review`, and `list_pending_review`.
172-
- **CLI surface**: `odek memory extended forget|promote|pin|quarantine|compact|stats|consolidate|pending|confirm|reject`.
172+
- **CLI surface**: `odek memory extended forget|promote|pin|quarantine|compact|stats|consolidate|nudges|pending|confirm|reject`.
173+
174+
**Proactive nudges** (opt-in): when `memory.extended.proactive_nudges_enabled` is `true` (default `false`), Extended Memory can synthesize short, user-facing nudges from trusted atoms — open questions, stale goals, blockers, and drift. Delivery is capped by `nudge_max_per_day` with a per-kind cooldown (`nudge_cooldown_hours`); goals only become "stale" after `nudge_stale_goal_days`. The Telegram bot pushes at most one nudge after a completed turn (in the background, prefixed with 💡). `odek memory extended nudges` prints a preview of up to 2 nudges without consuming the daily cap.
173175

174176
When enabled, Extended Memory atoms are injected as a separate system message after the legacy memory block and episode summaries on each turn. For the full design, config reference, and implementation status, see [docs/EXTENDED_MEMORY.md](EXTENDED_MEMORY.md).
175177

docs/SCHEDULES.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ container-only behaviour.
1212
# A weekday stand-up nudge delivered to Telegram
1313
odek schedule add --cron "0 9 * * 1-5" --deliver telegram "Remind me: stand-up in 15 minutes"
1414

15+
# A weekly proactive-nudge digest from Extended Memory (opt in with
16+
# memory.extended.proactive_nudges_enabled: true first)
17+
odek schedule add --cron "0 9 * * 1" --deliver telegram "Review my proactive nudges (open questions, stale goals) and summarize what deserves attention this week"
18+
1519
# Run the scheduler (headless), or just start `odek telegram` — it hosts one too
1620
odek schedule daemon
1721
```

0 commit comments

Comments
 (0)