feat(memory): inject KG hint into memory_search results and improve KG tool prompting

- Add hasKG flag to MemorySearchTool, inject hint in results when KG is enabled
- Wire SetHasKG(true) in gateway when KG store is available
- Improve knowledge_graph_search tool description with concrete use cases
- Update system prompt KG guidance to be more actionable
This commit is contained in:
viettranx committed 2026-03-13 13:33:18 +07:00
1 parent 558bdd6d5c
commit 7f4f4a238e
4 files changed
+23 -7

No files matched your search

+7 -1
View File
@@ -242,13 +242,19 @@ func wireExtras(
slog.Info("memory layering enabled (Postgres)")
}
// Wire knowledge graph store on KG tool
// Wire knowledge graph store on KG tool + hint in memory_search results
if stores.KnowledgeGraph != nil {
if kgTool, ok := toolsReg.Get("knowledge_graph_search"); ok {
if kgt, ok := kgTool.(*tools.KnowledgeGraphSearchTool); ok {
kgt.SetKGStore(stores.KnowledgeGraph)
}
}
// Enable KG hint in memory_search results
if searchTool, ok := toolsReg.Get("memory_search"); ok {
if mst, ok := searchTool.(*tools.MemorySearchTool); ok {
mst.SetHasKG(true)
}
}
slog.Info("knowledge graph tool wired (Postgres)")
}
+3 -3
View File
@@ -82,7 +82,7 @@ var coreToolSummaries = map[string]string{
"read_document": "Analyze documents (PDF, DOCX, etc.) attached to the conversation. Call this when you see <media:document> tags. If this tool fails, use a relevant skill instead (e.g. pdf skill with exec tool). The path attribute in <media:document path=\"...\"> is a directly accessible file in your workspace — use it directly, no need to copy",
"create_image": "Generate images from text descriptions using AI",
"create_audio": "Generate music or sound effects from text descriptions using AI",
"knowledge_graph_search": "Search entities and traverse relationships in the knowledge graph",
"knowledge_graph_search": "Find people, projects, and their connections — use for relationship questions (who works with whom, project dependencies) that memory_search may miss",
"handoff": "Transfer conversation to another agent (ONLY when user explicitly asks to switch agents — NOT for task delegation)",
"evaluate_loop": "Run a generate→evaluate→revise loop between two agents for quality-critical tasks",
"delegate_search": "Search for agents by expertise to find the right delegation target",
@@ -244,7 +244,7 @@ func BuildSystemPrompt(cfg SystemPromptConfig) string {
if !isMinimal && cfg.HasMemory {
memReminder := "Reminder: Before answering questions about prior work, decisions, or preferences, always run memory_search first."
if cfg.HasKnowledgeGraph {
memReminder += " When the question involves people, relationships, or how things connect, run knowledge_graph_search to find entities and multi-hop connections that memory_search alone may miss."
memReminder += " Also run knowledge_graph_search when the question involves people, teams, projects, or connections — it finds relationship paths that memory_search misses."
}
lines = append(lines, memReminder, "")
}
@@ -413,7 +413,7 @@ func buildMemoryRecallSection(hasKG bool) []string {
}
if hasKG {
lines = append(lines,
"When the question involves people, relationships, or how things connect, also run `knowledge_graph_search` — it finds entities and multi-hop connections (e.g. \"who does X work with?\", \"what projects is Y involved in?\") that memory_search alone may miss.",
"Also run `knowledge_graph_search` alongside memory_search when the question involves people, teams, projects, or connections between things. KG search is faster for relationship questions (e.g. \"who works with Minh?\", \"what projects is team X involved in?\", \"what depends on GoClaw?\") — it finds multi-hop connections that memory_search alone may miss.",
"",
)
}
+1 -1
View File
@@ -28,7 +28,7 @@ func (t *KnowledgeGraphSearchTool) SetKGStore(ks store.KnowledgeGraphStore) {
func (t *KnowledgeGraphSearchTool) Name() string { return "knowledge_graph_search" }
func (t *KnowledgeGraphSearchTool) Description() string {
return "Search the knowledge graph for entities and their relationships. Use specific names or keywords (e.g. a person's name, project name) — not generic words like 'entities' or 'all'. Use query='*' to list all entities. Supports graph traversal via entity_id to discover multi-hop relationships."
return "Search the knowledge graph to find people, projects, organizations, and how they connect. Better than memory_search when you need: who works with whom, what projects someone is involved in, dependencies between tasks, or any multi-hop relationship question. Use specific names (e.g. 'Minh', 'GoClaw') — not generic words. Use query='*' to list all known entities. Use entity_id to traverse connections from a specific entity."
}
func (t *KnowledgeGraphSearchTool) Parameters() map[string]any {
+12 -2
View File
@@ -14,6 +14,7 @@ import (
// MemorySearchTool implements the memory_search tool for hybrid semantic + FTS search.
type MemorySearchTool struct {
memStore store.MemoryStore // Postgres-backed
hasKG bool // knowledge_graph_search tool is available
}
func NewMemorySearchTool() *MemorySearchTool {
@@ -25,6 +26,11 @@ func (t *MemorySearchTool) SetMemoryStore(ms store.MemoryStore) {
t.memStore = ms
}
// SetHasKG enables the KG hint in search results.
func (t *MemorySearchTool) SetHasKG(has bool) {
t.hasKG = has
}
func (t *MemorySearchTool) Name() string { return "memory_search" }
func (t *MemorySearchTool) Description() string {
@@ -100,10 +106,14 @@ func (t *MemorySearchTool) Execute(ctx context.Context, args map[string]any) *Re
return NewResult("No memory results found for query: " + query)
}
data, _ := json.MarshalIndent(map[string]any{
output := map[string]any{
"results": results,
"count": len(results),
}, "", " ")
}
if t.hasKG {
output["hint"] = "Also run knowledge_graph_search if the query involves people, teams, projects, or connections between entities."
}
data, _ := json.MarshalIndent(output, "", " ")
return NewResult(string(data))
}