vxcontrol/pentagi · error
unknown tool: %s
Error message
unknown tool: %s
What it means
The memory tool dispatcher received a tool `name` that is not one of the tool names handled by its `switch` (e.g. not `SearchInMemoryToolName` or the other memory tool names). The library returns a generic 'unknown tool' error so callers know the name is not registered on this tool implementation.
Source
Thrown at backend/pkg/tools/memory.go:243
queriesText := strings.Join(action.Questions, "\n--------------------------------\n")
_, _ = m.vslp.PutLog(
ctx,
agentCtx.ParentAgentType,
agentCtx.CurrentAgentType,
filtersData,
queriesText,
database.VecstoreActionTypeRetrieve,
buffer.String(),
action.TaskID.PtrInt64(),
action.SubtaskID.PtrInt64(),
)
}
return buffer.String(), nil
default:
logger.Error("unknown tool")
return "", fmt.Errorf("unknown tool: %s", name)
}
}
func (m *memory) IsAvailable() bool {
return m.store != nil
}
func getGlobalFilters(filters map[string]any) (bool, map[string]any) {
globalFilters := maps.Clone(filters)
delete(globalFilters, "task_id")
delete(globalFilters, "subtask_id")
return len(globalFilters) != len(filters), globalFilters
}
View on GitHub (pinned to ea665308ba)
Solutions
- Log the received `name` and compare it against the exported `*ToolName` constants in the package.
- Ensure only the intended tool definitions are advertised to the LLM so it cannot select unregistered names.
- Verify the dispatcher routes each tool name to the correct implementation (memory vs search tool).
- Check for casing/renaming drift between the model's tool list and the switch cases.
Example fix
// before out, err := mem.Handle(ctx, "search_in_memory ", args) // trailing space/casing mismatch // after out, err := mem.Handle(ctx, tools.SearchInMemoryToolName, args) // use exported constants
Defensive patterns
Strategy: type-guard
Validate before calling
knownTools := map[string]bool{
tools.SearchInMemoryToolName: true,
tools.StoreInMemoryToolName: true,
}
if !knownTools[name] {
return fmt.Errorf("tool %q not registered for memory handler", name)
} Type guard
func isMemoryTool(name string) bool {
switch name {
case tools.SearchInMemoryToolName, tools.StoreInMemoryToolName:
return true
}
return false
} Try / catch
out, err := handler.Handle(ctx, name, args)
if err != nil && strings.HasPrefix(err.Error(), "unknown tool:") {
logger.Warnf("routing miss for tool %q, falling back to registry lookup", name)
return registry.Dispatch(ctx, name, args)
} Prevention
- Route tool calls through a registry keyed by the exported *ToolName constants.
- Only expose registered tool definitions to the LLM so it cannot invent names.
- Grep prompts/caches for old tool names after renaming a tool constant.
When it happens
Trigger: Calling `memory.Handle(ctx, name, args)` with a name string that doesn't match any `case` in the switch — typically a typo, wrong casing, or passing a tool name belonging to another tool implementation (e.g. `search_answer`).
Common situations: Agent framework routes tool calls by model-emitted name and the model hallucinated a tool name; tool registry wiring registered the memory tool under a different constant; refactoring renamed a tool constant but old prompts/caches still use the previous name.
Related errors
- unknown tool: %s
- failed to unmarshal %s search in memory action arguments: %w
- failed to marshal filters: %w
- unknown tool: %s
- unknown tool: %s
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/cde65c6584659afb.
Report an issue: GitHub.