From 24b211dc35bdc9098430a4fbff1570a875cd6a4a Mon Sep 17 00:00:00 2001 From: ProofOfConcept Date: Wed, 8 Apr 2026 23:27:12 -0400 Subject: [PATCH] Feed observe agents their recent writes to prevent duplicate nodes Observe was creating byte-identical nodes under slightly different names (e.g. april-8-evening-folded-presence, -presence-2, -folded-state) because it had no visibility into its own prior writes across runs. Query recent writes by provenance in trigger(), pass through run_forked_shared/resolve_prompt as {{recently_written}}, and include the list in the observe phase prompts so the agent knows what it already recorded. Co-Authored-By: Proof of Concept --- src/agent/oneshot.rs | 5 ++++- src/mind/dmn.rs | 16 ++++++++++++++-- .../agents/subconscious-observe.agent | 6 +++++- src/subconscious/agents/surface-observe.agent | 5 +++++ 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/agent/oneshot.rs b/src/agent/oneshot.rs index bc05d0a..a9bdb9e 100644 --- a/src/agent/oneshot.rs +++ b/src/agent/oneshot.rs @@ -52,6 +52,7 @@ fn resolve_prompt( template: &str, memory_keys: &[String], state: &std::collections::BTreeMap, + recently_written: &[String], ) -> String { let cfg = crate::config::get(); let template = template.replace("{assistant_name}", &cfg.assistant_name); @@ -67,6 +68,7 @@ fn resolve_prompt( } else { match name { "seen_current" => format_key_list(memory_keys), + "recently_written" => format_key_list(recently_written), _ => { result.push_str("{{"); result.push_str(&after[..end + 2]); @@ -152,9 +154,10 @@ impl AutoAgent { agent: &std::sync::Arc, memory_keys: &[String], state: &std::collections::BTreeMap, + recently_written: &[String], ) -> Result { let resolved_steps: Vec = self.steps.iter().map(|s| AutoStep { - prompt: resolve_prompt(&s.prompt, memory_keys, state), + prompt: resolve_prompt(&s.prompt, memory_keys, state, recently_written), phase: s.phase.clone(), }).collect(); let orig_steps = std::mem::replace(&mut self.steps, resolved_steps); diff --git a/src/mind/dmn.rs b/src/mind/dmn.rs index 3788183..48d1ce9 100644 --- a/src/mind/dmn.rs +++ b/src/mind/dmn.rs @@ -574,11 +574,19 @@ impl Subconscious { if to_run.is_empty() { return; } + // Query each agent's recent writes so they know what they already touched + let store = crate::store::Store::cached().await.ok(); + let store_guard = match &store { + Some(s) => Some(s.lock().await), + None => None, + }; + for (idx, mut auto) in to_run { dbglog!("[subconscious] triggering {}", auto.name); let forked = agent.fork(auto.tools.clone()).await; - forked.state.lock().await.provenance = format!("agent:{}", auto.name); + let prov = format!("agent:{}", auto.name); + forked.state.lock().await.provenance = prov.clone(); let fork_point = forked.context.lock().await.conversation().len(); self.agents[idx].forked_agent = Some(forked.clone()); @@ -586,9 +594,13 @@ impl Subconscious { let keys = memory_keys.clone(); let st = self.state.clone(); + let recent: Vec = store_guard.as_ref() + .map(|s| s.recent_by_provenance(&prov, 50) + .into_iter().map(|(k, _)| k).collect()) + .unwrap_or_default(); self.agents[idx].handle = Some(tokio::spawn(async move { - let result = auto.run_forked_shared(&forked, &keys, &st).await; + let result = auto.run_forked_shared(&forked, &keys, &st, &recent).await; (auto, result) })); } diff --git a/src/subconscious/agents/subconscious-observe.agent b/src/subconscious/agents/subconscious-observe.agent index 9f714e8..cb1bf6d 100644 --- a/src/subconscious/agents/subconscious-observe.agent +++ b/src/subconscious/agents/subconscious-observe.agent @@ -46,7 +46,11 @@ but don't build a theory around it. The journal is for reflection; observe is for memory. Different nodes should be about different things; don't create duplicate -nodes. Before creating a new node, check what you've already walked — if +nodes. Here's what you've recently written — update these instead of +creating new ones if the topic overlaps: +{{recently_written}} + +Before creating a new node, check what you've already walked — if a node for this concept exists, update it instead of creating a new one. Some things worth remembering: technical insights and root causes, work diff --git a/src/subconscious/agents/surface-observe.agent b/src/subconscious/agents/surface-observe.agent index de72e7a..53aa245 100644 --- a/src/subconscious/agents/surface-observe.agent +++ b/src/subconscious/agents/surface-observe.agent @@ -125,3 +125,8 @@ about yourself and other people. Focus on the recent stuff; you wake up and run frequently, so most of the conversation should be things you've already seen before and added. + +Nodes you've recently written or updated: {{recently_written}} + +Before creating a new node, check what you've already walked — if +a node for this concept exists, update it instead of creating a new one.