using System.Reflection;using System.Runtime.Loader;using System.Text;namespace Lilith.Agent.SelfImprovement;/// <summary>Loads the built sandbox Lilith assembly and invokes a generated tool by name.</summary>internal static class SandboxToolInvoker{ public static string Invoke(SelfImprovementPaths paths, string toolName, string argumentsJson = "{}") { if (string.IsNullOrWhiteSpace(toolName)) return "Error: tool_name is required."; string binDir = Path.Combine(paths.Sandbox, "Lilith", "bin", "Release", "net8.0"); string lilithDll = Path.Combine(binDir, "Lilith.dll"); string agentCoreDll = Path.Combine(binDir, "Agent-Core.dll"); if (!File.Exists(lilithDll)) return $"Error: sandbox Lilith.dll not found at {lilithDll}. Call self_improve_build_sandbox first."; if (!File.Exists(agentCoreDll)) return $"Error: sandbox Agent-Core.dll not found at {agentCoreDll}."; try { var loadContext = new SandboxAssemblyLoadContext(binDir); Assembly agentCoreAsm = loadContext.LoadFromAssemblyPath(agentCoreDll); Assembly lilithAsm = loadContext.LoadFromAssemblyPath(lilithDll); string className = ToPascalCase(toolName) + "Tool"; string fullName = $"Lilith.Agent.Tools.Generated.{className}"; Type? toolType = lilithAsm.GetType(fullName, throwOnError: false, ignoreCase: false); if (toolType is null) return $"Error: generated type {fullName} was not found in sandbox assembly."; Type registryType = agentCoreAsm.GetType("Agent.Core.ToolCalling.ToolRegistry", throwOnError: true)!; object registry = Activator.CreateInstance(registryType)!; MethodInfo? register = toolType.GetMethod("Register", BindingFlags.Public | BindingFlags.Static); if (register is null) return $"Error: {className}.Register was not found."; register.Invoke(null, [registry]); MethodInfo tryInvoke = registryType.GetMethod("TryInvoke", BindingFlags.Public | BindingFlags.Instance)!; object?[] invokeArgs = [toolName, argumentsJson, null]; bool ok = (bool)tryInvoke.Invoke(registry, invokeArgs)!; string result = (string)invokeArgs[2]!; return ok ? result : result; } catch (Exception ex) { return $"Error invoking sandbox tool '{toolName}': {ex.Message}"; } } private sealed class SandboxAssemblyLoadContext(string binDir) : AssemblyLoadContext(isCollectible: true) { protected override Assembly? Load(AssemblyName assemblyName) { string? path = ResolveAssemblyPath(assemblyName.Name); return path is not null ? LoadFromAssemblyPath(path) : null; } private string? ResolveAssemblyPath(string? simpleName) { if (string.IsNullOrWhiteSpace(simpleName)) return null; string candidate = Path.Combine(binDir, simpleName + ".dll"); return File.Exists(candidate) ? candidate : null; } } private static string ToPascalCase(string snake) { var parts = snake.Split('_', StringSplitOptions.RemoveEmptyEntries); var sb = new StringBuilder(); foreach (string part in parts) { if (part.Length == 0) continue; sb.Append(char.ToUpperInvariant(part[0])); if (part.Length > 1) sb.Append(part[1..]); } return sb.ToString(); }}
Documentation
Lilith self-improvement (Version 7+)
Lilith can extend herself only by creating tools in three categories:
| Category | Location | Examples | |----------|----------|----------| | Core | Agent-Core | Memory, time (rare; system-level) | | Addon | Agent-Addons | Weather, C# projects, apps | | Self | Lilith | Workspace files, self-improvement |
Layout
ShippedSource/— copy ofsrc/Version7next to the built app (MSBuildCopyShippedSource){workspace}/output/self-improvement/live— current editable source{workspace}/output/self-improvement/sandbox— clone for edits and builds{workspace}/output/self-improvement/backups/{timestamp}— backups before promote
Tools
1. self_improve_get_source_layout 2. self_improve_generate_tool 3. self_improve_backup_live 4. self_improve_create_sandbox 5. self_improve_build_sandbox 6. self_improve_verify_sandbox_tool 7. self_improve_promote_sandbox — copies sandbox → live, builds, restarts
Set GENESIS_REPO_ROOT to the repo root when developing from source instead of ShippedSource.