| layout | default |
|---|---|
| title | Chapter 3: Task Planning & Goal Setting |
| parent | AgentGPT Tutorial |
| nav_order | 3 |
Welcome to Chapter 3: Task Planning & Goal Setting. In this part of AgentGPT Tutorial: Building Autonomous AI Agents, you will build an intuitive mental model first, then move into concrete implementation details and practical production tradeoffs.
This chapter covers how AgentGPT agents plan and execute complex tasks by breaking them down into manageable steps and setting achievable goals.
// Break complex goals into manageable tasks
class GoalDecomposer {
async decompose(goal: string): Promise<Task[]> {
const analysis = await this.analyzeGoal(goal)
const subtasks = await this.createSubtasks(analysis)
const dependencies = await this.identifyDependencies(subtasks)
return this.optimizeTaskOrder(subtasks, dependencies)
}
private async analyzeGoal(goal: string) {
// Analyze goal complexity and requirements
return {
complexity: this.assessComplexity(goal),
requirements: await this.extractRequirements(goal),
constraints: this.identifyConstraints(goal)
}
}
}// Implement SMART goals for agents
interface SmartGoal {
specific: string // Clear and specific objective
measurable: string // Quantifiable criteria
achievable: string // Realistic and attainable
relevant: string // Aligned with overall objectives
timeBound: string // Time constraints and deadlines
}
const smartGoalExample: SmartGoal = {
specific: "Research and summarize the latest developments in quantum computing",
measurable: "Produce a 1000-word summary with 5 key findings",
achievable: "Using available research tools and 2 hours of research time",
relevant: "Supports the team's technology roadmap planning",
timeBound: "Complete within 24 hours"
}// Hierarchical planning approach
class HierarchicalPlanner {
async createPlan(goal: string): Promise<TaskPlan> {
const mainTask = await this.createMainTask(goal)
const subtasks = await this.decomposeTask(mainTask)
const schedule = await this.createSchedule(subtasks)
return {
goal,
mainTask,
subtasks,
schedule,
estimatedDuration: this.calculateDuration(subtasks)
}
}
private async decomposeTask(task: Task): Promise<Task[]> {
if (task.complexity < 3) {
return [task] // Simple task, no decomposition needed
}
const subtasks = []
const decomposition = await this.generateDecomposition(task)
for (const subtask of decomposition) {
subtasks.push(...await this.decomposeTask(subtask))
}
return subtasks
}
}// Manage task dependencies
class DependencyManager {
private dependencies: Map<string, string[]> = new Map()
addDependency(taskId: string, dependsOn: string[]) {
this.dependencies.set(taskId, dependsOn)
}
getExecutionOrder(tasks: Task[]): Task[] {
const visited = new Set<string>()
const order: Task[] = []
const visit = (task: Task) => {
if (visited.has(task.id)) return
// Visit dependencies first
const deps = this.dependencies.get(task.id) || []
for (const depId of deps) {
const depTask = tasks.find(t => t.id === depId)
if (depTask) visit(depTask)
}
visited.add(task.id)
order.push(task)
}
tasks.forEach(visit)
return order
}
}// A* algorithm for optimal planning
class AStarPlanner {
async findOptimalPlan(start: State, goal: State): Promise<Action[]> {
const openSet = new PriorityQueue()
const cameFrom = new Map()
const gScore = new Map()
const fScore = new Map()
openSet.add(start, 0)
gScore.set(start.id, 0)
fScore.set(start.id, this.heuristic(start, goal))
while (!openSet.isEmpty()) {
const current = openSet.poll()
if (this.isGoal(current, goal)) {
return this.reconstructPath(cameFrom, current)
}
for (const neighbor of this.getNeighbors(current)) {
const tentativeGScore = gScore.get(current.id) + this.getCost(current, neighbor)
if (tentativeGScore < (gScore.get(neighbor.id) || Infinity)) {
cameFrom.set(neighbor.id, current)
gScore.set(neighbor.id, tentativeGScore)
fScore.set(neighbor.id, tentativeGScore + this.heuristic(neighbor, goal))
if (!openSet.contains(neighbor)) {
openSet.add(neighbor, fScore.get(neighbor.id))
}
}
}
}
throw new Error('No path found')
}
private heuristic(state: State, goal: State): number {
// Estimate cost from state to goal
return this.calculateDistance(state, goal)
}
}// Monte Carlo Tree Search for planning
class MCTSPlanner {
private root: MCTSNode
async search(initialState: State, iterations: number = 1000): Promise<Action[]> {
this.root = new MCTSNode(initialState)
for (let i = 0; i < iterations; i++) {
const node = this.select(this.root)
const result = await this.simulate(node)
this.backpropagate(node, result)
}
return this.getBestPath(this.root)
}
private select(node: MCTSNode): MCTSNode {
while (!node.isLeaf()) {
if (!node.isFullyExpanded()) {
return this.expand(node)
}
node = this.bestChild(node)
}
return node
}
private async simulate(node: MCTSNode): Promise<number> {
let state = node.state
let depth = 0
while (!this.isTerminal(state) && depth < this.maxDepth) {
const action = this.randomAction(state)
state = this.applyAction(state, action)
depth++
}
return this.evaluateState(state)
}
}// Track task execution progress
class TaskMonitor {
private tasks = new Map<string, TaskProgress>()
startTask(taskId: string, task: Task) {
this.tasks.set(taskId, {
id: taskId,
name: task.name,
status: 'running',
progress: 0,
startTime: Date.now(),
subtasks: task.subtasks?.map(st => ({ ...st, status: 'pending' }))
})
}
updateProgress(taskId: string, progress: number, status?: string) {
const task = this.tasks.get(taskId)
if (task) {
task.progress = progress
if (status) task.status = status
}
}
getProgress(taskId: string): TaskProgress | undefined {
return this.tasks.get(taskId)
}
getAllProgress(): TaskProgress[] {
return Array.from(this.tasks.values())
}
}// Track planning and execution performance
const performanceMetrics = {
planning: {
averageTime: 0,
successRate: 0,
planQuality: 0
},
execution: {
averageTime: 0,
successRate: 0,
taskCompletion: 0
},
updatePlanningMetrics(planTime: number, success: boolean, quality: number) {
this.planning.averageTime = (this.planning.averageTime + planTime) / 2
this.planning.successRate = success ?
(this.planning.successRate + 1) / 2 :
this.planning.successRate / 2
this.planning.planQuality = (this.planning.planQuality + quality) / 2
}
}// Adapt plans based on execution feedback
class AdaptivePlanner {
async replan(originalPlan: TaskPlan, feedback: ExecutionFeedback): Promise<TaskPlan> {
const issues = this.analyzeFeedback(feedback)
const adjustments = await this.generateAdjustments(issues)
return {
...originalPlan,
adjustments,
updatedAt: new Date(),
version: originalPlan.version + 1
}
}
private analyzeFeedback(feedback: ExecutionFeedback) {
const issues = []
if (feedback.executionTime > feedback.expectedTime * 1.5) {
issues.push({ type: 'performance', severity: 'high' })
}
if (feedback.errorRate > 0.1) {
issues.push({ type: 'reliability', severity: 'medium' })
}
return issues
}
private async generateAdjustments(issues: any[]) {
const adjustments = []
for (const issue of issues) {
const adjustment = await this.createAdjustment(issue)
adjustments.push(adjustment)
}
return adjustments
}
}// Learn from past planning experiences
class PlanningLearner {
private experiences: PlanningExperience[] = []
recordExperience(experience: PlanningExperience) {
this.experiences.push(experience)
// Keep only recent experiences
if (this.experiences.length > 1000) {
this.experiences.shift()
}
}
async learnFromExperiences() {
// Analyze patterns in successful vs failed plans
const patterns = this.extractPatterns(this.experiences)
// Update planning strategies
await this.updateStrategies(patterns)
// Improve future planning
this.refinePlanningAlgorithm(patterns)
}
private extractPatterns(experiences: PlanningExperience[]) {
// Extract common patterns and correlations
return {
successfulPatterns: this.findSuccessfulPatterns(experiences),
failurePatterns: this.findFailurePatterns(experiences),
optimizationOpportunities: this.findOptimizationOpportunities(experiences)
}
}
}// Coordinate planning across multiple agents
class MultiAgentPlanner {
private agents: Agent[] = []
async createCollaborativePlan(goal: string): Promise<CollaborativePlan> {
const agentPlans = await Promise.all(
this.agents.map(agent => agent.createPlan(goal))
)
const conflicts = this.identifyConflicts(agentPlans)
const resolutions = await this.resolveConflicts(conflicts)
return {
goal,
agentPlans,
conflicts,
resolutions,
coordinationStrategy: this.createCoordinationStrategy(resolutions)
}
}
private identifyConflicts(plans: TaskPlan[]): Conflict[] {
const conflicts = []
for (let i = 0; i < plans.length; i++) {
for (let j = i + 1; j < plans.length; j++) {
const conflict = this.checkPlanConflict(plans[i], plans[j])
if (conflict) conflicts.push(conflict)
}
}
return conflicts
}
}// Handle uncertainty in planning
class ProbabilisticPlanner {
async createProbabilisticPlan(goal: string, uncertainty: number): Promise<ProbabilisticPlan> {
const scenarios = await this.generateScenarios(goal, uncertainty)
const plans = await Promise.all(
scenarios.map(scenario => this.createScenarioPlan(scenario))
)
return {
goal,
scenarios,
plans,
probabilities: this.calculateProbabilities(scenarios),
expectedUtility: this.calculateExpectedUtility(plans)
}
}
private async generateScenarios(goal: string, uncertainty: number): Promise<Scenario[]> {
// Generate different possible scenarios based on uncertainty
const scenarios = []
const numScenarios = Math.max(10, Math.floor(uncertainty * 50))
for (let i = 0; i < numScenarios; i++) {
scenarios.push(await this.createScenario(goal, uncertainty))
}
return scenarios
}
}- ✅ Learned goal decomposition techniques
- ✅ Implemented hierarchical task planning
- ✅ Used A* and Monte Carlo Tree Search algorithms
- ✅ Set up progress tracking and monitoring
- ✅ Created adaptive planning systems
- ✅ Built multi-agent and probabilistic planning
Key Takeaways:
- Complex goals need systematic decomposition
- Dependencies must be carefully managed
- Different planning algorithms suit different scenarios
- Progress tracking enables better control
- Adaptive planning handles changing conditions
- Learning from experience improves future planning
Most teams struggle here because the hard part is not writing more code, but deciding clear boundaries for goal, task, planning so behavior stays predictable as complexity grows.
In practical terms, this chapter helps you avoid three common failures:
- coupling core logic too tightly to one implementation path
- missing the handoff boundaries between setup, execution, and validation
- shipping changes without clear rollback or observability strategy
After working through this chapter, you should be able to reason about Chapter 3: Task Planning & Goal Setting as an operating subsystem inside AgentGPT Tutorial: Building Autonomous AI Agents, with explicit contracts for inputs, state transitions, and outputs.
Use the implementation notes around Promise, subtasks, node as your checklist when adapting these patterns to your own repository.
Under the hood, Chapter 3: Task Planning & Goal Setting usually follows a repeatable control path:
- Context bootstrap: initialize runtime config and prerequisites for
goal. - Input normalization: shape incoming data so
taskreceives stable contracts. - Core execution: run the main logic branch and propagate intermediate state through
planning. - Policy and safety checks: enforce limits, auth scopes, and failure boundaries.
- Output composition: return canonical result payloads for downstream consumers.
- Operational telemetry: emit logs/metrics needed for debugging and performance tuning.
When debugging, walk this sequence in order and confirm each stage has explicit success/failure conditions.
Use the following upstream sources to verify implementation details while reading this chapter:
- View Repo
Why it matters: authoritative reference on
View Repo(github.com).
Suggested trace strategy:
- search upstream code for
goalandtaskto map concrete implementation paths - compare docs claims against actual runtime/config code before reusing patterns in production