Skip to content

feat: proactive engagement — follow-up suggestions, open loops, nudges#91

Merged
jkyberneees merged 7 commits into
mainfrom
feat/proactive-engagement
Jul 22, 2026
Merged

feat: proactive engagement — follow-up suggestions, open loops, nudges#91
jkyberneees merged 7 commits into
mainfrom
feat/proactive-engagement

Conversation

@jkyberneees

Copy link
Copy Markdown
Contributor

Implements the approved Layer 1+2 design: the agent now anticipates follow-ups, tracks open loops (unanswered questions / stale goals), and can deliver opt-in proactive nudges derived from memory — all built on previously dormant machinery. Four per-workstream commits.

WS4 — scheduler memory wiring (892e755)

runTaskHeadless built scheduled-job agents without MemoryDir/MemoryConfig, so cron jobs couldn't analyze memory. Now wired; regression test proves a seeded atom reaches the model context headless. This unlocks memory-driven scheduled messages with zero further code (odek schedule add --deliver telegram "review my open goals and nudge me").

Core (4b78f1a)

  • Follow-up intent capture — the Predictor already generated follow-up intents every turn and discarded them after widening recall. Surviving intents (≥ follow_up_suggestion_min_confidence, default 0.6, cap 3) are now captured and exposed via ExtendedMemory.LastFollowUps / MemoryManager.FollowUpSuggestions. Zero extra LLM cost.
  • Open-loop atoms — the extractor now emits question atoms (unanswered user questions) and goal atoms (stated intentions); new OpenLoops query is the blind-spot data source.
  • ProactiveNudges engine — one LLM call synthesizes ≤2 concise nudges (open_question/stale_goal/blocker/drift) from open loops, goals stale ≥ nudge_stale_goal_days (7), and user-model focus. Anti-annoyance is persisted (nudges.json): opt-in master switch (default off), 1/day cap, 24h per-kind cooldown. Preview never consumes the budget; every failure degrades to empty — proactivity can never break a turn.

Surfaces (1f4203d)

  • ── You might also want to ── block printed after answers in run/REPL (engaging/enhance only; presentation-only, never in transcripts).
  • ReturnAfterBreak everywhere — the "where you left off" injection (previously run --continue only) extracted into a shared helper, wired into REPL resume and Telegram /resume.
  • odek memory extended nudges — preview pending nudges (kind + source atoms) without consuming the cap.
  • Telegram 💡 push — the bot now gets full memory wiring; after each completed turn, an opt-in background TakeNudges pushes a nudge message, honoring the shared persisted caps (no double-firing with CLI/other surfaces).

Verification

  • go test ./... — all green; -race green on memory/config/telegram.
  • golangci-lint run ./... — 0 issues.
  • 30+ new tests (capture threshold/cap, open-loop filtering, nudge caps/cooldown/rollover/degradation, presentation gating, RAB placement, Telegram push, scheduler memory wiring).

Docs

docs/EXTENDED_MEMORY.md (new P6 section + config rows), docs/CONFIG.md (6 new keys), docs/MEMORY.md, docs/SCHEDULES.md (memory-wired jobs + nudge cron example).

Out of scope (Layer 3, future): Web UI idle-push, serve-hosted scheduler, timing nudges via InteractionPatterns.

runTaskHeadless built the agent without MemoryDir/MemoryConfig, so
scheduled jobs could not analyze memory or past sessions - the
prerequisite for memory-driven proactive messages. Mirrors the
interactive-run wiring (cmd/odek/main.go). Test proves a pre-seeded
extended-memory atom reaches the model context in a headless run.
…ps, nudges engine

- recall-time predicted intents are now captured (>=0.6 confidence, cap 3)
  instead of discarded, exposed via ExtendedMemory.LastFollowUps and
  MemoryManager.FollowUpSuggestions - zero extra LLM cost
- the extractor now emits 'question' atoms (unanswered user questions)
  and 'goal' atoms (stated intentions); new OpenLoops query surfaces
  them as the blind-spot data source
- new ProactiveNudges engine: one LLM call synthesizes concise nudges
  from open loops, stale goals, and user-model focus; persisted
  anti-annoyance ledger (nudges.json) enforces an opt-in master switch
  (default off), a daily cap (1), and a per-kind cooldown (24h);
  preview (ProactiveNudges) never consumes the budget; all failures
  degrade to empty so proactivity can never break a turn
- config: 6 new memory.extended keys with env plumbing
- run/REPL print a compact '-- You might also want to --' block after
  answers (engaging/enhance modes only; presentation-only, never part
  of the response transcript)
- ReturnAfterBreak extracted into a shared helper and wired into REPL
  session resume and Telegram /resume (previously run --continue only)
- new 'odek memory extended nudges' preview command (shows pending
  nudges without consuming the daily cap)
- Telegram bot: agent now gets full memory wiring, and after each
  completed turn an opt-in (proactive_nudges_enabled) background
  TakeNudges pushes a nudge message, honoring the shared persisted caps
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 22, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
odek ec80de2 Commit Preview URL

Branch Preview URL
Jul 22 2026, 01:56 PM

…odes

The suggestions gate only matched the literal strings engaging/enhance,
but the loop treats every mode except off/verbose as engaging - so
configs with a legacy or invalid interaction_mode (e.g. "all", which
some configs carry from the tool_progress domain) silently suppressed
the block while otherwise behaving as engaging. Gate on exclusion
(only verbose/off suppress), matching the loop's interpretation.
Both profiles now opt into follow-up suggestions and proactive nudges
(capped at 1/day with a 24h per-kind cooldown, stale goals after 7 days),
matching the batteries-included intent of the compose stack - the
telegram profiles get the push behavior, all profiles get follow-up
suggestions after answers.
@jkyberneees
jkyberneees merged commit af875d8 into main Jul 22, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant