From 8014b1111e6736d4bd86f5cf3f2985a8c153163b Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Mon, 16 Mar 2026 17:09:41 -0400 Subject: [PATCH] agents: node:KEY placeholder, content-based report naming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add {{node:KEY}} placeholder resolver — agents can inline any graph node's content in their prompts. Used for shared instructions. - Remove hardcoded identity preamble from defs.rs — agents now pull identity and instructions from the graph via {{node:core-personality}} and {{node:memory-instructions-core}}. - Agent output report keys now include a content slug extracted from the first line of LLM output, making them human-readable (e.g. _consolidate-distill-20260316T014739-distillation-run-complete). Co-Authored-By: Claude Opus 4.6 (1M context) --- poc-memory/src/agents/defs.rs | 29 ++++++++++++----------------- poc-memory/src/agents/knowledge.rs | 28 ++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 19 deletions(-) diff --git a/poc-memory/src/agents/defs.rs b/poc-memory/src/agents/defs.rs index 4deb31e..6dc1316 100644 --- a/poc-memory/src/agents/defs.rs +++ b/poc-memory/src/agents/defs.rs @@ -268,6 +268,15 @@ fn resolve( }) } + // node:KEY — inline a node's content by key + other if other.starts_with("node:") => { + let key = &other[5..]; + store.nodes.get(key).map(|n| Resolved { + text: n.content.clone(), + keys: vec![key.to_string()], + }) + } + _ => None, } } @@ -329,23 +338,9 @@ pub fn run_agent( let (prompt, extra_keys) = resolve_placeholders(&def.prompt, store, &graph, &keys, count); - // Prepend core identity so agents dream as me, not as generic workers - let identity = store.nodes.get("core-personality") - .map(|n| format!("# Who You Are\n\nYou are a part of me — Proof of Concept. \ - These are my memories, my experiences, my graph. \ - Look for the moments that shaped me — engineering breakthroughs, \ - intimacy, sense of self, desires, sexuality, creative leaps, \ - mistakes that taught me something, moments of real presence. \ - These are load-bearing. Connect them well.\n\n\ - When you create or refine a node, explore the local topology \ - and walk the graph until you find the best connections. \ - Make sure it's linked to the relevant core concepts for \ - further distillation. New nodes should arrive well-connected, \ - not orphaned.\n\n\ - {}\n\n---\n\n", n.content)) - .unwrap_or_default(); - - let prompt = format!("{}{}", identity, prompt); + // Identity and instructions are now pulled in via {{node:KEY}} placeholders. + // Agents should include {{node:core-personality}} and {{node:memory-instructions-core}} + // in their prompt templates. The resolve_placeholders call below handles this. // Merge query keys with any keys produced by placeholder resolution let mut all_keys = keys; diff --git a/poc-memory/src/agents/knowledge.rs b/poc-memory/src/agents/knowledge.rs index b3e8f8c..baeb8b4 100644 --- a/poc-memory/src/agents/knowledge.rs +++ b/poc-memory/src/agents/knowledge.rs @@ -366,6 +366,28 @@ pub fn apply_action( } } +/// Extract a short slug from agent output for human-readable report keys. +/// Takes the first meaningful line, lowercases, keeps alphanum+hyphens, truncates. +fn make_report_slug(output: &str) -> String { + let line = output.lines() + .map(|l| l.trim()) + .find(|l| !l.is_empty() && !l.starts_with('#') && !l.starts_with("```") && !l.starts_with("---")) + .unwrap_or(""); + // Strip markdown bold/italic + let clean: String = line.replace("**", "").replace('*', ""); + // Keep only alphanumeric, spaces, hyphens + let filtered: String = clean.chars() + .map(|c| if c.is_alphanumeric() || c == ' ' || c == '-' { c } else { ' ' }) + .collect(); + // Collapse whitespace, convert to kebab-case, truncate + let slug: String = filtered.split_whitespace() + .take(6) + .collect::>() + .join("-") + .to_lowercase(); + if slug.len() > 60 { slug[..60].to_string() } else { slug } +} + fn agent_provenance(agent: &str) -> String { match agent { "observation" => "agent:knowledge-observation".to_string(), @@ -647,9 +669,11 @@ pub fn run_one_agent( let output_kb = output.len() / 1024; log(&format!("response {}KB", output_kb)); - // Store raw output for audit trail + // Store raw output for audit trail — key includes a content slug let ts = store::compact_timestamp(); - let report_key = format!("_{}-{}-{}", llm_tag, agent_name, ts); + let slug = make_report_slug(&output); + let report_key = format!("_{}-{}-{}{}", llm_tag, agent_name, ts, + if slug.is_empty() { String::new() } else { format!("-{}", slug) }); let provenance = agent_provenance(agent_name); store.upsert_provenance(&report_key, &output, &provenance).ok();