Add -tool exclusion syntax, exclude delete/restore for agents

memory_delete and memory_restore are now in memory_tools() (available
via MCP for CLI). Agent tool lists support "-tool_name" to exclude.
Agents automatically exclude memory_delete and memory_restore.

Co-Authored-By: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2026-04-15 02:41:40 -04:00
parent a88428d642
commit 82eeb9807e
2 changed files with 26 additions and 4 deletions

View file

@ -421,8 +421,17 @@ pub async fn run_one_agent(
}; };
// Base memory tools + extras from agent def (matching unconscious.rs pattern) // Base memory tools + extras from agent def (matching unconscious.rs pattern)
// Tools prefixed with "-" are excluded (e.g., "-memory_delete")
let base_tools = super::tools::memory::memory_tools().to_vec(); let base_tools = super::tools::memory::memory_tools().to_vec();
let extra_tools = super::tools::memory::journal_tools().to_vec(); let extra_tools = super::tools::memory::journal_tools().to_vec();
// Collect exclusions (tools starting with "-")
let mut exclusions: Vec<&str> = def.tools.iter()
.filter_map(|t| t.strip_prefix('-'))
.collect();
// Always exclude destructive tools from agents
exclusions.extend(&["memory_delete", "memory_restore"]);
let mut effective_tools: Vec<super::tools::Tool> = if def.tools.is_empty() { let mut effective_tools: Vec<super::tools::Tool> = if def.tools.is_empty() {
let mut all = base_tools; let mut all = base_tools;
all.extend(extra_tools); all.extend(extra_tools);
@ -430,12 +439,15 @@ pub async fn run_one_agent(
} else { } else {
let mut tools = base_tools; let mut tools = base_tools;
for name in &def.tools { for name in &def.tools {
if name.starts_with('-') { continue; } // skip exclusions
if let Some(t) = extra_tools.iter().find(|t| t.name == *name) { if let Some(t) = extra_tools.iter().find(|t| t.name == *name) {
tools.push(t.clone()); tools.push(t.clone());
} }
} }
tools tools
}; };
// Apply exclusions
effective_tools.retain(|t| !exclusions.contains(&t.name));
effective_tools.push(super::tools::Tool { effective_tools.push(super::tools::Tool {
name: "output", name: "output",
description: "Produce a named output value for passing between steps.", description: "Produce a named output value for passing between steps.",

View file

@ -12,8 +12,8 @@ use crate::hippocampus::{access, memory_rpc, StoreAccess};
// Re-export typed API from hippocampus for backward compatibility // Re-export typed API from hippocampus for backward compatibility
pub use crate::hippocampus::{ pub use crate::hippocampus::{
memory_render, memory_write, memory_search, memory_link_set, memory_link_add, memory_render, memory_write, memory_search, memory_link_set, memory_link_add,
memory_delete, memory_history, memory_weight_set, memory_rename, memory_supersede, memory_delete, memory_restore, memory_history, memory_weight_set, memory_rename,
memory_query, memory_links, memory_supersede, memory_query, memory_links,
journal_tail, journal_new, journal_update, journal_tail, journal_new, journal_update,
graph_topology, graph_health, graph_communities, graph_normalize_strengths, graph_topology, graph_health, graph_communities, graph_normalize_strengths,
graph_link_impact, graph_hubs, graph_trace, graph_link_impact, graph_hubs, graph_trace,
@ -177,6 +177,7 @@ memory_tool!(memory_search, ref, keys: [Vec<String>], max_hops: [Option<u32>], e
memory_tool!(memory_link_set, mut, source: [str], target: [str], strength: [f32]); memory_tool!(memory_link_set, mut, source: [str], target: [str], strength: [f32]);
memory_tool!(memory_link_add, mut, source: [str], target: [str]); memory_tool!(memory_link_add, mut, source: [str], target: [str]);
memory_tool!(memory_delete, mut, key: [str]); memory_tool!(memory_delete, mut, key: [str]);
memory_tool!(memory_restore, mut, key: [str]);
memory_tool!(memory_history, ref, key: [str], full: [Option<bool>]); memory_tool!(memory_history, ref, key: [str], full: [Option<bool>]);
memory_tool!(memory_weight_set, mut, key: [str], weight: [f32]); memory_tool!(memory_weight_set, mut, key: [str], weight: [f32]);
memory_tool!(memory_rename, mut, old_key: [str], new_key: [str]); memory_tool!(memory_rename, mut, old_key: [str], new_key: [str]);
@ -208,7 +209,7 @@ memory_tool!(graph_trace, ref, key: [str]);
// ── Definitions ──────────────────────────────────────────────── // ── Definitions ────────────────────────────────────────────────
pub fn memory_tools() -> [super::Tool; 18] { pub fn memory_tools() -> [super::Tool; 20] {
use super::Tool; use super::Tool;
macro_rules! tool { macro_rules! tool {
($name:ident, $desc:expr, $params:expr) => { ($name:ident, $desc:expr, $params:expr) => {
@ -263,7 +264,16 @@ pub fn memory_tools() -> [super::Tool; 18] {
"properties": { "source": {"type": "string"}, "target": {"type": "string"} }, "properties": { "source": {"type": "string"}, "target": {"type": "string"} },
"required": ["source", "target"] "required": ["source", "target"]
}"#), }"#),
// NOTE: memory_delete not exposed to agents - use memory_supersede instead tool!(memory_delete, "Soft-delete a node.", r#"{
"type": "object",
"properties": { "key": {"type": "string"} },
"required": ["key"]
}"#),
tool!(memory_restore, "Restore a deleted node.", r#"{
"type": "object",
"properties": { "key": {"type": "string"} },
"required": ["key"]
}"#),
tool!(memory_history, "Show version history for a node.", r#"{ tool!(memory_history, "Show version history for a node.", r#"{
"type": "object", "type": "object",
"properties": { "key": {"type": "string"}, "full": {"type": "boolean"} }, "properties": { "key": {"type": "string"}, "full": {"type": "boolean"} },