Skip to Content
Extensibility

Extensibility

AITOS is designed with extensibility at its core, allowing developers to add new capabilities through modules and organize agent configurations with blueprints. This page explains how to extend AITOS functionality and follow the development standards.

Modules

Modules are the primary way to add new capabilities to an AITOS agent. Each module encapsulates a specific functionality that can be enabled on an agent instance.

Module Structure

A typical AITOS module consists of:

  1. Setup Function: The entry point that enables the module on an agent
  2. Event Listeners: Functions that respond to specific events
  3. Task Definitions: Logic to be executed in response to events
  4. Resource Cleanup: Functions to properly release resources when the module is disabled

Creating a Custom Module

Here’s a step-by-step guide to creating a custom module:

  1. Create a Module Directory:

Create a new directory under src/modules/ with your module name:

src/modules/myCustomModule/
  1. Create the Main Module File:

Create an index.ts file with your module’s main code:

import { Agent } from "@/src/agent"; import { AgentEvent } from "@/src/agent/core/EventTypes"; // Module configuration options interface MyModuleOptions { interval: number; detailed?: boolean; } /** * Enable the custom module on an agent */ export function enableMyCustomModule(agent: Agent, options: MyModuleOptions) { const { interval, detailed = false } = options; // Set up interval for periodic tasks const intervalId = setInterval(() => { if (detailed) { console.log("Running periodic task..."); } // Emit an event from this module agent.sensing.emitEvent({ type: "MY_MODULE_PERIODIC_EVENT", description: "Periodic event from custom module", payload: { timestamp: Date.now() }, timestamp: Date.now(), }); }, interval); // Set up event listeners const offCustomEventListener = agent.sensing.registerListener((evt: AgentEvent) => { if (evt.type === "CUSTOM_REQUEST_EVENT") { if (detailed) { console.log("Received custom request event. Creating task..."); } // Create a task in response to the event agent.taskManager.createTask({ type: "CUSTOM_TASK", description: "Process custom request", payload: evt.payload, callback: async (payload) => { try { // Task implementation const result = await processCustomRequest(payload); // Emit a success event agent.sensing.emitEvent({ type: "CUSTOM_TASK_COMPLETED", description: "Custom task completed successfully", payload: { result }, timestamp: Date.now(), }); return result; } catch (error) { // Emit an error event agent.sensing.emitEvent({ type: "CUSTOM_TASK_FAILED", description: "Custom task failed", payload: { error }, timestamp: Date.now(), }); throw error; } }, }); } }); // Implementation of custom processing function async function processCustomRequest(payload: any) { // Your implementation here return { processed: true, data: payload }; } // Return a cleanup function to disable the module return function disableMyCustomModule() { clearInterval(intervalId); offCustomEventListener(); }; }
  1. Export Module from Directory:

Create or update a barrel export in your module directory:

// src/modules/myCustomModule/index.ts export * from './myCustomModule';
  1. Register in Module Index:

Add your module to the main modules index for easy importing:

// src/modules/index.ts export * from './core'; export * from './myCustomModule'; // Other module exports...

Using Your Module

Once created, you can enable your module on any agent:

import { Agent } from "@/src/agent"; import { enableMyCustomModule } from "@/src/modules/myCustomModule"; const agent = new Agent({ agentId: "custom-module-agent" }); // Enable the custom module const disableMyModule = enableMyCustomModule(agent, { interval: 5000, // Run every 5 seconds detailed: true // Enable detailed logging }); // Later, disable the module if needed disableMyModule();

Blueprints

Blueprints provide a way to bundle multiple modules and configurations together for reuse. They define a template for agent setup that can be applied to any agent instance.

Blueprint Structure

A blueprint is essentially a function that:

  1. Takes an agent instance
  2. Enables multiple modules with specific configurations
  3. Returns a cleanup function that disables all modules

Creating a Custom Blueprint

Here’s how to create a custom blueprint:

  1. Create a Blueprint File:
// src/blueprints/MyCustomBlueprint.ts import { Agent } from "@/src/agent"; import { enableMyCustomModule } from "@/src/modules/myCustomModule"; import { enableNetworkModule } from "@/src/modules/network"; export function MyCustomBlueprint(agent: Agent) { // Enable required modules const disableMyModule = enableMyCustomModule(agent, { interval: 10000, detailed: false, }); const disableNetworkModule = enableNetworkModule(agent, { endpoints: ["https://api.example.com/v1"], timeoutMs: 5000, }); // Return a composite cleanup function return function disableMyCustomBlueprint() { disableMyModule(); disableNetworkModule(); }; }
  1. Export from Blueprints Directory:
// src/blueprints/index.ts export * from './BasicBlueprint'; export * from './MyCustomBlueprint'; // Other blueprint exports...

Using Your Blueprint

Apply your custom blueprint to an agent:

import { Agent } from "@/src/agent"; import { MyCustomBlueprint } from "@/src/blueprints"; const agent = new Agent({ agentId: "blueprint-agent", blueprint: MyCustomBlueprint, }); // The agent now has all capabilities defined in the blueprint

Best Practices

  1. Single Responsibility: Each module should focus on a specific capability
  2. Resource Cleanup: Always return a cleanup function that removes all listeners and intervals
  3. Event Naming: Use consistent naming patterns for events (e.g., MODULE_ACTION_EVENT)
  4. Configuration: Make modules configurable through options
  5. Error Handling: Include proper error handling in task callbacks
  6. Documentation: Document the events your module emits and listens for

Next Steps

Last updated on