feat(tools): add ToolRegistry, ToolSearchTool and ExpertTool to support on-demand tool visibility, discovery, activation, and expert/subagent tooling; extend DualAgentOrchestrator API and interfaces to manage tool lifecycle

This commit is contained in:
2026-01-20 14:39:34 +00:00
parent 5ca0c80ea9
commit 5aa69cc998
10 changed files with 924 additions and 37 deletions

175
readme.md
View File

@@ -37,19 +37,19 @@ flowchart TB
end
subgraph Orchestrator["DualAgentOrchestrator"]
Registry["ToolRegistry<br/><i>Visibility & Lifecycle</i>"]
Driver["Driver Agent<br/><i>Reason + Plan</i>"]
Guardian["Guardian Agent<br/><i>Evaluate against policy</i>"]
Driver -->|"tool call proposal"| Guardian
Guardian -->|"approve / reject + feedback"| Driver
Registry -->|"visible tools"| Driver
end
subgraph Tools["Standard Tools"]
FS["Filesystem"]
HTTP["HTTP"]
Shell["Shell"]
Browser["Browser"]
Deno["Deno"]
subgraph Tools["Tools"]
Initial["Initial Tools<br/><i>Always visible</i>"]
OnDemand["On-Demand Tools<br/><i>Discoverable via search</i>"]
Experts["Expert SubAgents<br/><i>Specialized agents as tools</i>"]
end
Task --> Orchestrator
@@ -266,6 +266,157 @@ orchestrator.registerTool(new JsonValidatorTool());
</tool_call>
```
### 🔍 ToolSearchTool
Enable the Driver to discover and activate on-demand tools at runtime.
**Actions**: `search`, `list`, `activate`, `details`
```typescript
// Enable tool search (adds the 'tools' tool)
orchestrator.enableToolSearch();
```
```typescript
// Search for tools by capability
<tool_call>
<tool>tools</tool>
<action>search</action>
<params>{"query": "database"}</params>
</tool_call>
// List all available tools
<tool_call>
<tool>tools</tool>
<action>list</action>
<params>{}</params>
</tool_call>
// Activate an on-demand tool
<tool_call>
<tool>tools</tool>
<action>activate</action>
<params>{"name": "database_expert"}</params>
</tool_call>
// Get detailed information about a tool
<tool_call>
<tool>tools</tool>
<action>details</action>
<params>{"name": "filesystem"}</params>
</tool_call>
```
### 🧠 ExpertTool (SubAgents)
Create specialized sub-agents that can be invoked as tools. Experts are complete `DualAgentOrchestrator` instances wrapped as tools, enabling hierarchical agent architectures.
**Actions**: `consult`
```typescript
// Register an expert for code review
orchestrator.registerExpert({
name: 'code_reviewer',
description: 'Reviews code for quality, bugs, and best practices',
systemMessage: `You are an expert code reviewer. Analyze code for:
- Bugs and potential issues
- Code style and best practices
- Performance concerns
- Security vulnerabilities`,
guardianPolicy: 'Allow read-only file access within the workspace',
tools: [new FilesystemTool()],
visibility: 'on-demand', // Only available via tool search
tags: ['code', 'review', 'quality'],
category: 'expert',
});
```
```typescript
// Consult an expert
<tool_call>
<tool>code_reviewer</tool>
<action>consult</action>
<params>{
"task": "Review this function for potential issues",
"context": "This is a user authentication handler"
}</params>
</tool_call>
```
## 🎯 Tool Visibility System
SmartAgent supports **tool visibility modes** for scalable agent architectures:
- **`initial`** (default): Tool is visible to the Driver from the start, included in the system prompt
- **`on-demand`**: Tool is hidden until explicitly activated via `tools.activate()`
This enables you to have many specialized tools/experts without overwhelming the Driver's context.
```typescript
// Register a tool with on-demand visibility
orchestrator.registerTool(new MySpecializedTool(), {
visibility: 'on-demand',
tags: ['specialized', 'database'],
category: 'data',
});
// Enable tool search so Driver can discover and activate on-demand tools
orchestrator.enableToolSearch();
// The Driver can now:
// 1. tools.search({"query": "database"}) -> finds MySpecializedTool
// 2. tools.activate({"name": "myspecialized"}) -> enables it
// 3. myspecialized.action({...}) -> use the tool
```
### Expert SubAgent Example
```typescript
const orchestrator = new DualAgentOrchestrator({
openaiToken: 'sk-...',
defaultProvider: 'openai',
guardianPolicyPrompt: 'Allow safe operations...',
});
orchestrator.registerStandardTools();
orchestrator.enableToolSearch();
// Initial expert (always visible)
orchestrator.registerExpert({
name: 'code_assistant',
description: 'Helps with coding tasks and code generation',
systemMessage: 'You are a helpful coding assistant...',
guardianPolicy: 'Allow read-only file access',
tools: [new FilesystemTool()],
});
// On-demand experts (discoverable via search)
orchestrator.registerExpert({
name: 'database_expert',
description: 'Database design, optimization, and query analysis',
systemMessage: 'You are a database expert...',
guardianPolicy: 'Allow read-only operations',
visibility: 'on-demand',
tags: ['database', 'sql', 'optimization'],
});
orchestrator.registerExpert({
name: 'security_auditor',
description: 'Security vulnerability assessment and best practices',
systemMessage: 'You are a security expert...',
guardianPolicy: 'Allow read-only file access',
visibility: 'on-demand',
tags: ['security', 'audit', 'vulnerabilities'],
});
await orchestrator.start();
// Now the Driver can:
// - Use code_assistant directly
// - Search for "database" and activate database_expert when needed
// - Search for "security" and activate security_auditor when needed
```
## 🎥 Streaming Support
SmartAgent supports token-by-token streaming for real-time output during LLM generation:
@@ -608,12 +759,15 @@ const orchestrator = new DualAgentOrchestrator({
| `stop()` | Cleanup all tools and resources |
| `run(task, options?)` | Execute a task with optional images for vision |
| `continueTask(input)` | Continue a task with user input |
| `registerTool(tool)` | Register a custom tool |
| `registerTool(tool, options?)` | Register a custom tool with optional visibility settings |
| `registerStandardTools()` | Register all built-in tools (Filesystem, HTTP, Shell, Browser, Deno) |
| `registerScopedFilesystemTool(basePath, excludePatterns?)` | Register filesystem tool with path restriction |
| `registerExpert(config)` | Register a specialized sub-agent as a tool |
| `enableToolSearch()` | Enable tool discovery and activation for the Driver |
| `setGuardianPolicy(policy)` | Update Guardian policy at runtime |
| `getHistory()` | Get conversation history |
| `getToolNames()` | Get list of registered tool names |
| `getRegistry()` | Get the ToolRegistry for advanced operations |
| `isActive()` | Check if orchestrator is running |
### Exports
@@ -624,6 +778,9 @@ export { DualAgentOrchestrator } from '@push.rocks/smartagent';
export { DriverAgent } from '@push.rocks/smartagent';
export { GuardianAgent } from '@push.rocks/smartagent';
// Tool Registry
export { ToolRegistry } from '@push.rocks/smartagent';
// Tools
export { BaseToolWrapper } from '@push.rocks/smartagent';
export { FilesystemTool, type IFilesystemToolOptions } from '@push.rocks/smartagent';
@@ -632,9 +789,11 @@ export { ShellTool } from '@push.rocks/smartagent';
export { BrowserTool } from '@push.rocks/smartagent';
export { DenoTool, type TDenoPermission } from '@push.rocks/smartagent';
export { JsonValidatorTool } from '@push.rocks/smartagent';
export { ToolSearchTool } from '@push.rocks/smartagent';
export { ExpertTool } from '@push.rocks/smartagent';
// Types and interfaces
export * from '@push.rocks/smartagent'; // All interfaces
export * from '@push.rocks/smartagent'; // All interfaces (IExpertConfig, IToolMetadata, etc.)
// Re-exported from @push.rocks/smartai
export { type ISmartAiOptions, type TProvider, type ChatMessage, type ChatOptions, type ChatResponse };