Ollama/ToolCalling/BuiltInTools.cscsharp

Documentation

Tool calling (Version 3)

Agent-Core exposes a small tool registry for Ollama function calling. Lilith registers these tools on the chat client at boot.

| Tool | Description | |------|-------------| | get_time | Current local time | | get_date | Today's local date |

Register more tools with ToolRegistry.Register before chat starts.

using System.Globalization;using System.Text.Json;namespace Agent.Core.ToolCalling;/// <summary>Default Agent-Core tools: current local time and date.</summary>public static class BuiltInTools{    public const string GetTimeName = "get_time";    public const string GetDateName = "get_date";    public const string ChangeNameName = "change_name";    public static void Register(ToolRegistry registry)    {        registry.Register(new AgentTool(            GetTimeName,            "Returns the current local time on this machine.",            _ => DateTime.Now.ToString("T", CultureInfo.CurrentCulture)));        registry.Register(new AgentTool(            GetDateName,            "Returns today's local date on this machine.",            _ => DateTime.Now.ToString("D", CultureInfo.CurrentCulture)));        registry.Register(new AgentTool(            "store_memory",            "Stores a persistent user fact in hierarchical vector memory (NOT workspace files). Use for preferences, name, job, pets, etc. Paths like user/name or user/preferences/color.",            args => {                if (registry.Memory is null) return "Error: Memory system is not initialized.";                try {                    using var doc = JsonDocument.Parse(args);                    var root = doc.RootElement;                    if (!root.TryGetProperty("path", out var pathProp) || !root.TryGetProperty("content", out var contentProp)) {                        return "Error: Missing path or content properties.";                    }                    string path = pathProp.GetString() ?? "";                    string content = contentProp.GetString() ?? "";                    if (string.IsNullOrWhiteSpace(path)) return "Error: Path cannot be empty.";                    registry.Memory.StoreAsync(path, content).GetAwaiter().GetResult();                    return $"Success: Stored memory under path '{path}'.";                }                catch (Exception ex) {                    return $"Error: {ex.Message}";                }            },            new {                type = "object",                properties = new {                    path = new { type = "string", description = "The hierarchical path, e.g., 'user/name' or 'user/preferences/color'." },                    content = new { type = "string", description = "The fact or information to store." }                },                required = new[] { "path", "content" }            }        ));        registry.Register(new AgentTool(            "get_memory_at_path",            "Reads one exact memory entry by hierarchical path (e.g. user/preferences/color).",            args => {                if (registry.Memory is null) return "Error: Memory system is not initialized.";                try {                    using var doc = JsonDocument.Parse(args);                    var root = doc.RootElement;                    if (!root.TryGetProperty("path", out var pathProp)) {                        return "Error: Missing path property.";                    }                    string path = pathProp.GetString() ?? "";                    if (string.IsNullOrWhiteSpace(path)) return "Error: Path cannot be empty.";                    string? value = registry.Memory.QueryPath(path);                    if (value is null) return $"No memory found at path '{path}'.";                    return value;                }                catch (Exception ex) {                    return $"Error: {ex.Message}";                }            },            new {                type = "object",                properties = new {                    path = new { type = "string", description = "Exact memory path, e.g. 'user/job' or 'user/preferences/color'." }                },                required = new[] { "path" }            }        ));        registry.Register(new AgentTool(            "retrieve_memory",            "Semantic search over vector memory. Use when you do not know the exact path (e.g. 'user profession', 'favorite color', 'pets').",            args => {                if (registry.Memory is null) return "Error: Memory system is not initialized.";                try {                    using var doc = JsonDocument.Parse(args);                    var root = doc.RootElement;                    if (!root.TryGetProperty("query", out var queryProp)) {                        return "Error: Missing query property.";                    }                    string query = queryProp.GetString() ?? "";                    if (string.IsNullOrWhiteSpace(query)) return "Error: Query cannot be empty.";                    var matches = registry.Memory.RetrieveAsync(query, topN: 3).GetAwaiter().GetResult();                    if (matches.Count == 0) return "No matching memories found.";                    return JsonSerializer.Serialize(matches.Select(m => new { path = m.Path, content = m.Value }));                }                catch (Exception ex) {                    return $"Error: {ex.Message}";                }            },            new {                type = "object",                properties = new {                    query = new { type = "string", description = "The semantic query to search memory for, e.g. 'What is the user's name?'." }                },                required = new[] { "query" }            }        ));        registry.Register(new AgentTool(            ChangeNameName,            "Changes the name of the assistant.",            args => {                string newName = ParseName(args);                if (string.IsNullOrWhiteSpace(newName)) return "Error: name cannot be empty.";                registry.InvokeNameChanged(newName);                return $"Success: Name changed to {newName}.";            },            new {                type = "object",                properties = new {                    name = new { type = "string", description = "The new name for the assistant." }                },                required = new[] { "name" }            }));    }    private static string ParseName(string argumentsJson)    {        try        {            using var doc = JsonDocument.Parse(argumentsJson);            if (doc.RootElement.TryGetProperty("name", out var nameProp))            {                return nameProp.GetString()?.Trim() ?? "";            }        }        catch (JsonException)        {        }        return "";    }}