Task Execution
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
Option | Type | Description | Required |
---|---|---|---|
name | string | Task name | Yes |
description | string | Detailed description of the task | Yes |
input | object | Input data for the task | No |
dependsOn | string[] | IDs of tasks that must complete first | No |
maxRetries | number | Maximum retry attempts if task fails | No (default: 3) |
timeout | number | Time in milliseconds before task times out | No |
tags | string[] | Labels for categorizing tasks | No |
agentId | string | Agent ID for the task | No (uses manager default) |
sessionId | string | Session ID for the task | No (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:
- Dependencies are executed first in the correct order
- Results from dependencies are automatically passed to the dependent task
- 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
Option | Type | Description | Default |
---|---|---|---|
concurrency | number | Maximum concurrent tasks | 5 |
agentId | string | Default agent ID for tasks | undefined |
sessionId | string | Default session ID for tasks | undefined |
memory | MemoryInstance | Memory for task context storage | undefined |
database | DatabaseInstance | Database for task persistence | undefined |
providerModel | ProviderModel | Model for task execution | undefined |
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
- Automatic Tables: Trust the automatic table creation - no need for manual schema setup
- Clear Dependencies: Define clear task dependencies to avoid circular references
- Meaningful Names: Use descriptive names and descriptions for tasks
- Error Handling: Implement proper error handling and retry logic
- Resource Management: Set appropriate concurrency limits based on system resources
- Task Granularity: Break complex operations into smaller, manageable tasks
- Input Validation: Validate task inputs before execution
- 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
andtaskManager.createTask
create tables automatically - Error Handling: Improved error handling and retry mechanisms
How is this guide?