Skip to main content

Plugin System

Why Plugins?

The plugin system is the only way to programmatically extend agent functionality beyond the built-in capabilities. While agents themselves are markdown-based and declarative, plugins provide a JavaScript/TypeScript interface for:
  • Custom integrations: Connect agents to your existing systems, databases, or APIs
  • Observability: Add monitoring, logging, or analytics to track agent performance
  • Automation workflows: Trigger actions based on agent completion or failure
  • Development tools: Build debugging utilities or testing frameworks
  • Cross-agent functionality: Share logic across all agents without modifying each one
Without plugins, you would be limited to the tools and capabilities built into AgentUse. Plugins bridge the gap between AgentUse’s declarative agent definitions and your custom programmatic needs.

Quick Start

  1. Create a plugin directory:
mkdir -p .agentuse/plugins
  1. Add a plugin file (.js or .ts):
// .agentuse/plugins/my-plugin.js
export default {
  'agent:complete': async (event) => {
    console.log(`Agent ${event.agent.name} completed!`);
  }
};
  1. Run your agent normally - plugins auto-load!

Plugin Locations

Plugins are automatically loaded from:
  • ./.agentuse/plugins/*.{ts,js} - Project-specific plugins (loaded first)
  • ~/.agentuse/plugins/*.{ts,js} - User-global plugins (loaded second)
Note: Project-specific plugins take precedence and are loaded before global plugins. All plugins with the same event handler will execute in the order they are loaded.

Plugin Structure

Each plugin must export a default object with event handlers:
export default {
  'agent:complete': async (event) => {
    // Handle agent completion
  }
};

Available Events

agent:complete

Fired when an agent successfully completes execution. Event data:
{
  agent: {
    name: string;         // Agent name
    model: string;        // Model used (e.g., "anthropic:claude-sonnet-4-0")
    description?: string; // Agent description from YAML frontmatter
    filePath?: string;    // Path to agent file
  };
  result: {
    text: string;         // Final output text
    duration: number;     // Execution time in seconds
    tokens?: number;      // Total tokens used
    toolCalls: number;    // Number of tool calls made
    toolCallTraces?: ToolCallTrace[];  // Detailed timing for each tool/sub-agent/LLM call
  };
  isSubAgent: boolean;    // True if this is a sub-agent
  consoleOutput: string;  // Full console output including logs and results
}

ToolCallTrace Interface

The toolCallTraces array provides detailed performance information for each operation during agent execution:
interface ToolCallTrace {
  name: string;           // Tool, sub-agent, or model name
  type: 'tool' | 'subagent' | 'llm';
  startTime: number;      // Unix timestamp in ms
  duration: number;       // Duration in ms
  tokens?: number;        // Total tokens used (for sub-agents and LLM calls)
  promptTokens?: number;  // Input tokens (for LLM calls)
  completionTokens?: number; // Output tokens (for LLM calls)
}
Trace Types:
  • tool: Function tool calls (bash commands, file operations, etc.)
  • subagent: Sub-agent executions
  • llm: Direct LLM model calls
Use Cases:
  • Performance monitoring and optimization
  • Cost tracking for token usage
  • Debugging slow operations
  • Analytics and reporting

Example: Slack Notifications

// .agentuse/plugins/slack.js
export default {
  'agent:complete': async (event) => {
    const webhookUrl = process.env.SLACK_WEBHOOK_URL;
    
    // Skip if no webhook or if sub-agent
    if (!webhookUrl || event.isSubAgent) {
      return;
    }
    
    await fetch(webhookUrl, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        text: `✅ Agent "${event.agent.name}" completed`,
        attachments: [{
          color: 'good',
          fields: [
            { title: 'Duration', value: `${event.result.duration.toFixed(1)}s`, short: true },
            { title: 'Tokens', value: event.result.tokens?.toString() || 'N/A', short: true },
            { title: 'Tool Calls', value: event.result.toolCalls.toString(), short: true }
          ]
        }]
      })
    });
  }
};
Set your webhook URL:
export SLACK_WEBHOOK_URL=https://hooks.slack.com/services/YOUR/WEBHOOK/URL

Example: Performance Trace Reporting

Display detailed performance traces for agent executions using toolCallTraces:
// .agentuse/plugins/trace-reporter.js
export default {
  'agent:complete': async (event) => {
    // Only process if traces are available and not a sub-agent
    if (!event.result.toolCallTraces || event.isSubAgent) {
      return;
    }

    console.log("\n📊 Performance Traces:");

    // Display each trace with appropriate icon
    for (const trace of event.result.toolCallTraces) {
      const icon =
        trace.type === 'llm' ? '🧠' :
        trace.type === 'subagent' ? '🤖' : '🔧';

      console.log(`  ${icon} ${trace.name}: ${trace.duration}ms`);

      if (trace.tokens) {
        console.log(`     └─ Tokens: ${trace.tokens}`);
      }
    }

    // Summary statistics
    const llmCalls = event.result.toolCallTraces.filter(t => t.type === 'llm');
    const toolCalls = event.result.toolCallTraces.filter(t => t.type === 'tool');
    const subagentCalls = event.result.toolCallTraces.filter(t => t.type === 'subagent');

    console.log("\n📈 Summary:");
    console.log(`  LLM calls: ${llmCalls.length} (${llmCalls.reduce((sum, t) => sum + t.duration, 0)}ms total)`);
    console.log(`  Tool calls: ${toolCalls.length} (${toolCalls.reduce((sum, t) => sum + t.duration, 0)}ms total)`);
    console.log(`  Sub-agents: ${subagentCalls.length} (${subagentCalls.reduce((sum, t) => sum + t.duration, 0)}ms total)`);
  }
};
This plugin outputs performance information like:
📊 Performance Traces:
  🧠 anthropic:claude-sonnet-4-0: 1234ms
     └─ Tokens: 450
  🔧 bash: 567ms
  🤖 code-reviewer: 8901ms
     └─ Tokens: 1200
  🧠 anthropic:claude-sonnet-4-0_segment_2: 2345ms
     └─ Tokens: 320

📈 Summary:
  LLM calls: 2 (3579ms total)
  Tool calls: 1 (567ms total)
  Sub-agents: 1 (8901ms total)
Ready to Use: Find this complete plugin in templates/plugins/trace-reporter.js. Copy it to .agentuse/plugins/ to start tracking performance.

Advanced Performance Monitoring Ideas

You can extend the basic trace reporting with more advanced features:
  • Slow Operation Detection: Warn about operations taking longer than 5 seconds
  • Token Usage Tracking: Monitor prompt and completion tokens with cost estimates
  • Operation Breakdown: Categorize calls by type (tool, sub-agent, LLM)
  • Historical Logging: Save performance data to .agentuse/performance.log
  • Smart Filtering: Skip sub-agent executions to avoid duplicate logging
  • Cost Analysis: Calculate estimated costs based on token usage
  • Performance Thresholds: Set alerts for operations exceeding time or token limits
  • Dashboards: Export data to monitoring services like Datadog or Grafana
  • Comparative Analysis: Compare performance across different models or agent versions

TypeScript Support

For TypeScript plugins, import the types:
// .agentuse/plugins/my-plugin.ts
import type { PluginHandlers } from 'agentuse/plugin/types';

const plugin: PluginHandlers = {
  'agent:complete': async (event) => {
    // Full type safety and intellisense
    console.log(`Agent ${event.agent.name} completed!`);
    console.log(`Console output: ${event.consoleOutput}`);
  }
};

export default plugin;

Error Handling

  • Plugin loading errors are caught and logged as warnings, but don’t prevent the agent from running
  • Invalid plugin formats (non-object default exports) are skipped with a warning message
  • Plugin execution errors are caught and logged but don’t fail agent execution
  • Missing plugin directories are handled gracefully
  • Plugins can be disabled by removing/renaming the file

Best Practices

  1. Check event.isSubAgent to avoid duplicate notifications
  2. Use environment variables for configuration
  3. Keep plugins focused on a single responsibility
  4. Handle errors gracefully within your plugin
  5. Use TypeScript for better type safety

Implementation Details

  • Plugins are loaded using dynamic imports with absolute paths
  • Plugin handlers are executed asynchronously in parallel
  • Multiple plugins can handle the same event
  • Console output is captured during agent execution and made available to plugins
  • Plugin require cache is cleared for hot-reloading during development
I