Add or remove tools, MCP servers, A2A agents, and sub-agents at runtime via registries
The problem: You configured your agent with a fixed tool set at startup, but different users, tenants, or sessions need different capabilities — and you can’t restart the process for each change.The solution: All capabilities are resolved from registries at execution time. Each Run, Stream, or RunAsync picks up the current registry state — no restart needed. Add tools for a premium user, remove them on logout, swap MCP servers per tenant, or register a specialist sub-agent when a feature is enabled.Combine with static setup (WithTools, WithMCPConfig, etc.) by passing initial capabilities at NewAgent, then mutating registries as context changes.
All registries are safe for concurrent use. Name uniqueness is enforced — Register on an existing name returns agent.ErrRegistryDuplicate. To update an entry, call Unregister first, then Register with the new configuration.
reg := agent.NewToolRegistry()a, _ := agent.NewAgent( agent.WithLLMClient(llmClient), agent.WithToolRegistry(reg),)// First run — only tools already in the registryresult, _ := a.Run(ctx, "What is 17 * 23?", nil)// Add a tool before the next run_ = a.ToolRegistry().Register(calculator.New())result, _ = a.Run(ctx, "What is 17 * 23?", nil)// Remove it again_ = a.ToolRegistry().Unregister("calculator")
Dynamic registry changes on the agent client process do not propagate to a remote worker’s in-memory registries. For split client/worker deployments, register matching capabilities on both NewAgent and NewAgentWorker, or ensure workers see the same registry state before runs execute.For tenant-specific capability sets (different tools per tenant), design your worker to register all possible capabilities at startup and use BeforeToolHook or ToolAuthorizer for runtime gating — rather than dynamically mutating worker-side registries.