Astreus - Docs

Task Execution

Tasks

Task Execution enables agents to break down complex problems into manageable sub-tasks with intelligent orchestration, dependency management, and structured workflows. The system uses a TaskExecutor for advanced task coordination.

Task Execution Architecture

The Task Execution system consists of:

  • Task Definitions: Specifications of work to be done
  • Task Executor: Intelligent orchestration with dependency management (formerly TaskManager)
  • Task Results: Structured outputs from completed tasks
  • Task Dependencies: Define execution order and data flow with dependsOn support
  • Automatic Table Creation: Tasks table created when first task is created
  • Concurrency Control: Configurable parallel task execution
  • Retry Logic: Automatic retry on task failures

Creating Tasks

Tasks are created through the TaskExecutor (createTaskManager creates a TaskExecutor) and automatically create their database table:

import { createAgent, createTaskManager, createTask } from '@astreus-ai/astreus';

// Create an agent
const agent = await createAgent({ /* configuration */ });

// Create a task executor
const taskExecutor = createTaskManager({
  agentId: agent.id,
  memory: agent.config.memory,
  database: agent.config.database,
  personality: agent.getPersonality(), // Tasks inherit agent's personality
  concurrency: 5,  // Run up to 5 tasks in parallel
  maxRetries: 3    // Retry failed tasks up to 3 times
});

// Create a research task (automatically creates tasks table on first use)
const researchTask = await taskExecutor.createTask({
  name: "Research Trip",
  description: "Find information about tourist attractions in Tokyo",
  input: {
    destination: "Tokyo",
    interests: ["history", "food", "technology"]
  }
});

console.log(`Task created with ID: ${researchTask.id}`);

// Alternative: Use createTask directly (also creates table automatically)
const directTask = await createTask({
  name: "Process Data",
  description: "Process and analyze the data set",
  input: { dataFile: "sales_2023.csv" }
});

Direct Agent Task Creation

For simplified task creation, agents can create and execute tasks directly with automatic personality integration:

// Create tasks directly through agent (recommended for most use cases)
const researchTask = await agent.createTask({
  name: "Research Topic",
  description: "Research information about quantum computing"
});

const summaryTask = await agent.createTask({
  name: "Create Summary", 
  description: "Summarize the research findings",
  dependsOn: [researchTask.id]  // This task depends on research task
});

// Execute tasks (agent's personality is automatically used)
const researchResult = await agent.executeTask(researchTask.id);
const summaryResult = await agent.executeTask(summaryTask.id);

Task Configuration Options

OptionTypeDescriptionRequired
namestringTask nameYes
descriptionstringDetailed description of the taskYes
inputobjectInput data for the taskNo
dependsOnstring[]IDs of tasks that must complete firstNo
maxRetriesnumberMaximum retry attempts if task failsNo (default: 3)
timeoutnumberTime in milliseconds before task times outNo
tagsstring[]Labels for categorizing tasksNo
agentIdstringAgent ID for the taskNo (uses manager default)
sessionIdstringSession ID for the taskNo (uses manager default)

Database Table Creation

The tasks table is automatically created when the first task is created. The table includes:

-- Tasks table schema (created automatically)
CREATE TABLE tasks (
  id VARCHAR PRIMARY KEY,
  name VARCHAR NOT NULL,
  description TEXT NOT NULL,
  status VARCHAR NOT NULL,
  retries INTEGER DEFAULT 0,
  plugins JSON,
  input JSON,
  dependencies JSON,
  result JSON,
  createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  startedAt TIMESTAMP,
  completedAt TIMESTAMP,
  agentId VARCHAR,
  sessionId VARCHAR,
  metadata JSON
);

-- Indexes for performance
CREATE INDEX tasks_status_idx ON tasks(status);
CREATE INDEX tasks_agentId_idx ON tasks(agentId);
CREATE INDEX tasks_sessionId_idx ON tasks(sessionId);

Running Tasks

Execute tasks using the TaskManager's run method:

// Run a single task
const results = await taskManager.run([researchTask.id]);

// Get the result of the task
const taskResult = results.get(researchTask.id);

if (taskResult.success) {
  console.log("Task output:", taskResult.output);
} else {
  console.error("Task failed:", taskResult.error);
}

Working with Task Dependencies

Tasks can depend on other tasks, creating workflows:

// Create an initial research task
const researchTask = await taskManager.createTask({
  name: "Research Options",
  description: "Find top restaurants in Paris",
  input: { 
    city: "Paris", 
    cuisine: "French" 
  }
});

// Create a dependent task that uses the output of the research task
const planningTask = await taskManager.createTask({
  name: "Create Dinner Plan",
  description: "Create a dinner plan based on research results",
  dependsOn: [researchTask.id],  // This task depends on researchTask
  input: { 
    budget: "200 EUR",
    date: "2023-12-25"
  }
});

// Create a third task that depends on planning
const reservationTask = await taskManager.createTask({
  name: "Make Reservation",
  description: "Make restaurant reservation based on dinner plan",
  dependsOn: [planningTask.id]
});

// Run all tasks in the correct order
const results = await taskManager.run([
  researchTask.id, 
  planningTask.id,
  reservationTask.id
]);

When a task has dependencies:

  1. Dependencies are executed first in the correct order
  2. Results from dependencies are automatically passed to the dependent task
  3. Task execution is skipped if any dependency fails

Accessing Task Outputs

Task results are structured to provide detailed information:

// Get results of all tasks
const results = await taskManager.run([taskA.id, taskB.id]);

// Access individual task results
const resultA = results.get(taskA.id);
const resultB = results.get(taskB.id);

// Each result has these properties:
console.log(`Task ID: ${resultA.taskId}`);
console.log(`Success: ${resultA.success}`);
console.log(`Output: ${JSON.stringify(resultA.output)}`);
console.log(`Error: ${resultA.error || 'None'}`);
console.log(`Start Time: ${resultA.startTime}`);
console.log(`End Time: ${resultA.endTime}`);
console.log(`Duration: ${resultA.duration}ms`);

Managing Tasks

You can retrieve and manage tasks:

// Get all tasks from the task manager
const allTasks = taskManager.getAllTasks();

// Get tasks for a specific agent
const agentTasks = taskManager.getTasksByAgent(agent.id);

// Get tasks for a specific session
const sessionTasks = taskManager.getTasksBySession("session123");

// Get a specific task by ID
const task = taskManager.getTask("task-uuid");

// Cancel a task
const canceled = taskManager.cancelTask("task-uuid");

Task Manager Configuration

Configure the task manager when creating it:

import { createTaskManager } from '@astreus-ai/astreus';

// Basic task manager
const basicTaskManager = createTaskManager({
  concurrency: 3,  // Run up to 3 tasks concurrently
  agentId: agent.id,
  sessionId: "session-123"
});

// Advanced task manager with memory and database (tables created automatically)
const advancedTaskManager = createTaskManager({
  concurrency: 5,
  agentId: agent.id,
  sessionId: "session-123",
  memory: agent.config.memory,
  database: agent.config.database,
  providerModel: agent.getModel()
});

Task Manager Configuration Options

OptionTypeDescriptionDefault
concurrencynumberMaximum concurrent tasks5
agentIdstringDefault agent ID for tasksundefined
sessionIdstringDefault session ID for tasksundefined
memoryMemoryInstanceMemory for task context storageundefined
databaseDatabaseInstanceDatabase for task persistenceundefined
providerModelProviderModelModel for task executionundefined

Error Handling and Retries

Tasks include error handling and retry mechanisms:

// Create a task with custom retry settings
const dataProcessingTask = await taskManager.createTask({
  name: "Process Data",
  description: "Process and analyze the data set",
  input: { dataFile: "sales_2023.csv" },
  maxRetries: 5,  // Retry up to 5 times
  timeout: 300000  // Timeout after 5 minutes (300,000 ms)
});

// Run task with error handling
try {
  const results = await taskManager.run([dataProcessingTask.id]);
  const taskResult = results.get(dataProcessingTask.id);
  
  if (taskResult.success) {
    console.log("Task completed successfully!");
  } else {
    console.log("Task failed after retries");
    console.log("Error:", taskResult.error);
    console.log("Attempts:", taskResult.attempts);
  }
} catch (error) {
  console.error("Error executing tasks:", error);
}

Advanced Task Patterns

Sequential Task Chain

Create a chain of dependent tasks:

async function createTaskChain() {
  const tasks = [];
  
  // Step 1: Data collection
  const collectTask = await taskManager.createTask({
    name: "Collect Data",
    description: "Gather data from various sources",
    input: { sources: ["api", "database", "files"] }
  });
  tasks.push(collectTask);
  
  // Step 2: Data processing (depends on collection)
  const processTask = await taskManager.createTask({
    name: "Process Data",
    description: "Clean and transform collected data",
    dependsOn: [collectTask.id]
  });
  tasks.push(processTask);
  
  // Step 3: Analysis (depends on processing)
  const analyzeTask = await taskManager.createTask({
    name: "Analyze Data",
    description: "Perform statistical analysis",
    dependsOn: [processTask.id]
  });
  tasks.push(analyzeTask);
  
  // Step 4: Report generation (depends on analysis)
  const reportTask = await taskManager.createTask({
    name: "Generate Report",
    description: "Create final analysis report",
    dependsOn: [analyzeTask.id]
  });
  tasks.push(reportTask);
  
  return tasks;
}

// Execute the entire chain
const taskChain = await createTaskChain();
const results = await taskManager.run(taskChain.map(t => t.id));

Parallel Task Execution

Execute independent tasks in parallel:

async function createParallelTasks() {
  // These tasks can run in parallel
  const task1 = await taskManager.createTask({
    name: "Fetch User Data",
    description: "Get user information from API",
    input: { userId: "123" }
  });
  
  const task2 = await taskManager.createTask({
    name: "Fetch Product Data",
    description: "Get product information from database",
    input: { productId: "456" }
  });
  
  const task3 = await taskManager.createTask({
    name: "Fetch Analytics Data",
    description: "Get analytics from third-party service",
    input: { timeRange: "last_30_days" }
  });
  
  // Combine results task (depends on all parallel tasks)
  const combineTask = await taskManager.createTask({
    name: "Combine Results",
    description: "Merge all data sources into final result",
    dependsOn: [task1.id, task2.id, task3.id]
  });
  
  return [task1, task2, task3, combineTask];
}

// Execute parallel tasks
const parallelTasks = await createParallelTasks();
const results = await taskManager.run(parallelTasks.map(t => t.id));

Integration with Agents

Task managers work seamlessly with agents and automatically create required tables:

import { createAgent, createProvider, createMemory, createDatabase, createTaskManager } from '@astreus-ai/astreus';

async function createAgentWithTasks() {
  const db = await createDatabase();
  const memory = await createMemory({ database: db }); // Creates memories table
  const provider = createProvider({ type: 'openai', model: 'gpt-4o-mini' });
  
  const agent = await createAgent({
    name: 'TaskAgent',
    provider: provider,
    memory: memory,
    database: db,
    systemPrompt: "You are a helpful assistant that can execute complex tasks."
  }); // Creates agents table when saved
  
  // Create task manager for this agent (will create tasks table when first task is created)
  const taskManager = createTaskManager({
    agentId: agent.id,
    memory: memory,
    database: db,
    providerModel: agent.getModel()
  });
  
  return { agent, taskManager };
}

// Use agent with tasks
const { agent, taskManager } = await createAgentWithTasks();

// Create a task that uses the agent's capabilities (creates tasks table)
const analysisTask = await taskManager.createTask({
  name: "Market Analysis",
  description: "Analyze market trends and provide insights",
  input: {
    market: "technology",
    timeframe: "Q1 2024"
  }
});

// Execute the task
const results = await taskManager.run([analysisTask.id]);

Direct Task Creation

You can also create tasks directly without a task manager:

import { createTask } from '@astreus-ai/astreus';

// Create task directly (creates tasks table automatically)
const task = await createTask({
  name: "Direct Task",
  description: "A task created directly",
  input: { data: "example" }
});

// Execute the task
const result = await task.execute();
console.log('Task result:', result);

Best Practices

  1. Automatic Tables: Trust the automatic table creation - no need for manual schema setup
  2. Clear Dependencies: Define clear task dependencies to avoid circular references
  3. Meaningful Names: Use descriptive names and descriptions for tasks
  4. Error Handling: Implement proper error handling and retry logic
  5. Resource Management: Set appropriate concurrency limits based on system resources
  6. Task Granularity: Break complex operations into smaller, manageable tasks
  7. Input Validation: Validate task inputs before execution
  8. Progress Tracking: Use task status and results for progress monitoring

Migration Notes

The task system has been enhanced with automatic table creation and better integration:

  • Automatic Tables: Tasks table is created automatically when first task is created
  • Simplified Setup: No need for manual database schema initialization
  • Better Integration: Enhanced integration with agents, memory, and database systems
  • Task Creation: Both createTask and taskManager.createTask create tables automatically
  • Error Handling: Improved error handling and retry mechanisms

How is this guide?