Task Orchestration
KaibanJS provides flexible task orchestration capabilities to control how tasks are executed within a team workflow. These execution patterns determine the order and manner in which tasks are processed, enabling you to create workflows that match your specific needs.
Deterministic Execution
The deterministic execution pattern ensures tasks are executed in a predictable and controlled manner. It supports three main approaches:
- Sequential Execution: Tasks execute one after another in a defined order
- Dependency-based Execution: Tasks execute based on their dependencies
- Parallel Execution: Multiple tasks execute simultaneously when possible
Each pattern serves different needs and can be combined to create sophisticated workflows.
Sequential Execution
Sequential execution is the simplest pattern, where tasks execute one after another in the order they are defined. This is useful when:
- Tasks naturally follow a linear sequence
- Each task builds upon the results of the previous task
- You need predictable, step-by-step execution
- Order of execution is more important than execution speed
To achieve sequential execution:
- Define tasks without any dependencies
- List tasks in the desired execution order
- Do not set
allowParallelExecution
on any task
Here's an example of a trip planning workflow with sequential execution:
const plannerAgent = new Agent({
name: 'TravelPlanner',
role: 'Travel Planning Specialist',
goal: 'Create comprehensive travel plans'
});
const team = new Team({
name: 'Trip Planning Team',
agents: [plannerAgent],
tasks: [
new Task({
referenceId: 'research',
description: 'Research potential destinations',
agent: plannerAgent
}),
new Task({
referenceId: 'selectDates',
description: 'Select optimal travel dates',
agent: plannerAgent
}),
new Task({
referenceId: 'bookFlights',
description: 'Book flights for selected dates',
agent: plannerAgent
}),
new Task({
referenceId: 'bookHotel',
description: 'Reserve hotel accommodation',
agent: plannerAgent
}),
new Task({
referenceId: 'planActivities',
description: 'Create daily activity schedule',
agent: plannerAgent
})
]
});
Here's a visualization of the sequential flow:
[research] → [selectDates] → [bookFlights] → [bookHotel] → [planActivities]
In this workflow:
- Tasks execute strictly in the order they appear in the array
- Each task starts only after the previous task completes
- The execution is predictable and linear
- No parallel execution occurs
Key points about sequential execution:
- Simplest execution pattern to understand and implement
- Guarantees tasks execute in the exact order specified
- Useful for workflows where order is critical
- May not be the most efficient for independent tasks
Dependency-based Execution
Dependencies between tasks allow you to create sophisticated workflows where the execution order is determined by logical relationships rather than a simple sequence. A task will only start when all tasks it depends on have completed, enabling you to:
- Build data processing pipelines where each step requires output from previous steps
- Implement approval workflows where certain actions need sign-off before proceeding
- Create deployment processes that ensure proper testing and validation before releases
- Manage document workflows where reviews and edits must happen in a specific order
- Coordinate multi-agent tasks where some agents need input from others to proceed
To achieve dependency-based execution:
- Define explicit dependencies between tasks using the
dependencies
array - List tasks in any order (execution order is determined by dependencies)
Here's a simple example of a software release workflow:
const developerAgent = new Agent({
name: 'Dev',
role: 'Developer',
goal: 'Ensure code quality and successful deployment'
});
const qaAgent = new Agent({
name: 'QA',
role: 'Quality Assurance',
goal: 'Verify application functionality'
});
const team = new Team({
name: 'Release Team',
agents: [developerAgent, qaAgent],
tasks: [
new Task({
referenceId: 'runTests',
description: 'Run the automated test suite',
agent: developerAgent
}),
new Task({
referenceId: 'updateVersion',
description: 'Update version numbers in package files',
agent: developerAgent,
dependencies: ['runTests'] // Can only update version after tests pass
}),
new Task({
referenceId: 'manualQA',
description: 'Perform manual QA checks',
agent: qaAgent,
dependencies: ['runTests'] // QA starts after tests pass
}),
new Task({
referenceId: 'createRelease',
description: 'Create release package',
agent: developerAgent,
dependencies: ['updateVersion', 'manualQA'] // Release requires both version update and QA approval
}),
new Task({
referenceId: 'deploy',
description: 'Deploy to production',
agent: developerAgent,
dependencies: ['createRelease'] // Can only deploy after release is created
})
]
});
This workflow demonstrates how dependencies control task execution:
runTests
executes first (no dependencies)- After tests pass:
updateVersion
can startmanualQA
can also start
createRelease
waits for bothupdateVersion
andmanualQA
to complete- Finally,
deploy
executes aftercreateRelease
finishes
Here's a visualization of the dependencies:
[runTests]
↓
┌───────┴───────┐
↓ ↓
[updateVersion] [manualQA]
↓ ↓
└───────┬───────┘
↓
[createRelease]
↓
[deploy]
This example shows how dependencies ensure tasks execute in the correct order, regardless of their position in the tasks array. The execution engine will automatically determine the proper sequence based on the dependency relationships.
Parallel Tasks
KaibanJS allows tasks to run concurrently when they are independent of each other or when their dependencies are met. This is particularly useful for:
- Reducing overall execution time by running independent tasks simultaneously
- Maximizing resource utilization across different agents
- Processing multiple independent data streams
- Handling concurrent operations like parallel API calls or data processing
To enable parallel execution:
- Define dependencies between tasks using the
dependencies
array (if any) - Set
allowParallelExecution: true
on tasks that can run concurrently
Here's an example of a data processing workflow that uses parallel execution:
const dataAgent = new Agent({
name: 'DataProcessor',
role: 'Data Processing Specialist',
goal: 'Process and analyze data efficiently'
});
const team = new Team({
name: 'Data Processing Team',
agents: [dataAgent],
tasks: [
new Task({
referenceId: 'loadData',
description: 'Load the raw dataset from storage',
agent: dataAgent
}),
new Task({
referenceId: 'validateA',
description: 'Validate dataset A integrity',
agent: dataAgent,
dependencies: ['loadData'],
allowParallelExecution: true
}),
new Task({
referenceId: 'validateB',
description: 'Validate dataset B integrity',
agent: dataAgent,
dependencies: ['loadData'],
allowParallelExecution: true
}),
new Task({
referenceId: 'validateC',
description: 'Validate dataset C integrity',
agent: dataAgent,
dependencies: ['loadData'],
allowParallelExecution: true
}),
new Task({
referenceId: 'processA',
description: 'Process validated dataset A',
agent: dataAgent,
dependencies: ['validateA'],
allowParallelExecution: true
}),
new Task({
referenceId: 'processB',
description: 'Process validated dataset B',
agent: dataAgent,
dependencies: ['validateB'],
allowParallelExecution: true
}),
new Task({
referenceId: 'processC',
description: 'Process validated dataset C',
agent: dataAgent,
dependencies: ['validateC'],
allowParallelExecution: true
}),
new Task({
referenceId: 'mergeSets',
description: 'Merge all processed datasets',
agent: dataAgent,
dependencies: ['processA', 'processB', 'processC']
})
]
});
Here's a visualization of the parallel execution flow:
[loadData]
↓
┌──────────┼──────────┐
↓ ↓ ↓
[validateA]* [validateB]* [validateC]*
↓ ↓ ↓
[processA]* [processB]* [processC]*
↓ ↓ ↓
└──────────┼──────────┘
↓
[mergeSets]
* Tasks marked with asterisk (*) can run in parallel
In this workflow:
loadData
runs first- After data is loaded:
- All three validation tasks can run in parallel
- As each validation completes:
- Its corresponding processing task can start
- Processing tasks can run in parallel with other validations/processing
- After all processing completes:
mergeSets
combines the results
Key points about parallel execution:
- Tasks marked with
allowParallelExecution: true
can run simultaneously when their dependencies are met - The execution engine automatically manages concurrent task execution
- Parallel tasks can significantly reduce total execution time
- The final task waits for all parallel branches to complete before executing
Key Features
- Predictable Execution: Tasks always execute in a deterministic order based on their dependencies and position in the task list.
- Dependency Resolution: Automatically handles complex dependency chains and ensures prerequisites are met.
- Parallel Task Support: Allows concurrent execution of independent tasks when marked with
allowParallelExecution: true
. - Error Handling: Gracefully handles task failures and maintains workflow state consistency.
- Pause/Resume Support: Supports pausing and resuming workflow execution while maintaining task state and dependencies.
Best Practices
- Define Clear Dependencies: Always explicitly define task dependencies to ensure proper execution order.
- Use Parallel Execution Wisely: Only mark tasks as parallel when they are truly independent and can run concurrently.
- Avoid Circular Dependencies: Ensure your task dependencies form a directed acyclic graph (DAG).
- Consider Resource Constraints: When using parallel execution, consider the available computational resources and agent availability.
- Monitor Task Status: Use the workflow logs to monitor task execution status and debug execution order issues.
- Design for Flexibility: Structure your tasks to allow for maximum parallelization where possible, but maintain clear dependencies where necessary.
Combining Execution Patterns
In real-world scenarios, you often need to combine different execution patterns to create efficient workflows. Here's an example of an event planning system that uses all three patterns:
- Sequential: Initial planning tasks that must happen in order
- Dependencies: Tasks that require input from previous tasks
- Parallel: Independent tasks that can run simultaneously
const eventManagerAgent = new Agent({
name: 'Peter Atlas',
role: 'Oversees event planning and ensures smooth execution.',
goal: 'Coordinate tasks and ensure timely execution.'
});
const venueAgent = new Agent({
name: 'Sophia Lore',
role: 'Manages venue logistics.',
goal: 'Confirm venue availability, arrange setup, and handle issues.'
});
const cateringAgent = new Agent({
name: 'Maxwell Journey',
role: 'Organizes food and beverages for the event',
goal: 'Deliver a catering plan and coordinate with vendors'
});
const marketingAgent = new Agent({
name: 'Riley Morgan',
role: 'Promotes the event and handles attendee registrations',
goal: 'Drive attendance and manage guest lists'
});
const team = new Team({
name: 'Event Planning Team',
agents: [eventManagerAgent, venueAgent, cateringAgent, marketingAgent],
tasks: [
new Task({
referenceId: 'pickDate',
description: 'Select optimal event date based on stakeholder availability',
agent: eventManagerAgent
}),
new Task({
referenceId: 'bookVenue',
description: 'Book and confirm venue for the selected date',
agent: venueAgent,
dependencies: ['pickDate']
}),
new Task({
referenceId: 'guestList',
description: 'Compile guest list and handle RSVPs',
agent: marketingAgent,
dependencies: ['pickDate'],
allowParallelExecution: true
}),
new Task({
referenceId: 'budget',
description: 'Create detailed event budget',
agent: eventManagerAgent,
dependencies: ['pickDate']
}),
new Task({
referenceId: 'catering',
description: 'Plan menu and select vendors',
agent: cateringAgent,
dependencies: ['guestList']
}),
new Task({
referenceId: 'marketing',
description: 'Develop marketing campaign',
agent: marketingAgent,
dependencies: ['pickDate', 'bookVenue'],
allowParallelExecution: true
}),
new Task({
referenceId: 'setup',
description: 'Coordinate venue setup',
agent: venueAgent,
dependencies: ['bookVenue', 'catering']
}),
new Task({
referenceId: 'promote',
description: 'Execute marketing campaign',
agent: marketingAgent,
dependencies: ['marketing'],
allowParallelExecution: true
}),
new Task({
referenceId: 'approve',
description: 'Final inspection and approval',
agent: eventManagerAgent,
dependencies: ['setup', 'promote']
})
]
});
Here's a visualization of how these patterns work together:
[pickDate]
↓
┌──────────┼──────────┐
↓ ↓ ↓
[bookVenue] [guestList]* [budget]
↓ ↓
↓ ↓
[marketing]* [catering]
↓ ↓
↓ ↓
[promote]* [setup]
↓ ↓
└──────────┴────┐
↓
[approve]
* Tasks marked with asterisk (*) can run in parallel
This workflow demonstrates:
-
Sequential Pattern
pickDate
must complete firstbudget
must wait tobookVenue
finishesapprove
must be the last task
-
Dependency Pattern
bookVenue
depends on date selectioncatering
depends on guest listsetup
depends on both venue booking and catering plan
-
Parallel Pattern
guestList
,budget
can run in parallel after date selectionmarketing
can run in parallel with other taskspromote
can run in parallel with setup tasks
The execution sequence unfolds as follows:
-
Initial Phase:
pickDate
executes first as it has no dependencies
-
Planning Phase (after date selection):
bookVenue
starts (depends on pickDate)guestList
starts in parallel (depends on pickDate, allows parallel execution)
-
Preparation Phase:
- Once
bookVenue
completes:marketing
can begin (depends on pickDate and bookVenue)budget
begins (depends on pickDate, but must wait for bookVenue as it's not be executed in parallel)
- Once
guestList
completes:catering
begins (depends on guestList)
- Once
-
Implementation Phase:
- When
marketing
completes:promote
starts (depends on marketing)
- When both
bookVenue
andcatering
complete:setup
begins (depends on both tasks)
- When
-
Final Phase:
- Only when both
setup
andpromote
complete:approve
executes as the final task
- Only when both
This sequence demonstrates how the execution engine:
- Starts independent tasks as soon as their dependencies are met
- Runs parallel tasks whenever possible
- Maintains critical sequential dependencies
- Coordinates multiple agents working simultaneously
- Ensures all necessary prerequisites are completed before dependent tasks begin.
Non-deterministic Execution
Non-deterministic execution patterns allow for more dynamic and adaptive task execution. Unlike deterministic patterns where the execution flow is pre-defined, non-deterministic approaches can adjust the workflow in real-time based on task outcomes, resource availability, and emerging requirements.
Manager LLM
Coming Soon
The Manager LLM feature will introduce intelligent task orchestration capabilities:
- Dynamic task prioritization and scheduling
- Adaptive workflow modifications based on task outcomes
- Intelligent resource allocation across agents
- Real-time decision making for optimal task execution
- Automated dependency management and conflict resolution