Skip to main content
Before running the agent, Magpie classifies each task to determine which blueprint path to execute. This ensures the right workflow runs for each type of work.

TaskComplexity Enum

pipeline.rs:90-102
/// How complex a task is — determines which blueprint path to use.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum TaskComplexity {
    /// Docs, typos, renames — fast single-shot agent call.
    Simple,
    /// Features, refactors, integrations — TDD plan→test→implement flow.
    Standard,
    /// Bug fixes — diagnostic investigate→plan→test→fix flow.
    BugFix,
}

Complexity to Blueprint Mapping

Simple

magpie-mainSingle-shot agent callDocs, typos, renames, formatting

Standard

magpie-tddTDD: plan → write tests → implementFeatures, refactors, integrations

BugFix

magpie-diagnosticInvestigate → plan → test → fixBugs, crashes, regressions

Classification Algorithm

pipeline.rs:166-230
pub async fn classify_task(
    task: &str,
    dry_run: bool,
    trace_dir: Option<&PathBuf>,
) -> TaskComplexity {
    let lower = task.to_lowercase();

    // Fast path: simple keywords (checked first — "fix typo" is Simple, not BugFix)
    if SIMPLE_KEYWORDS.iter().any(|kw| lower.contains(kw)) {
        info!(task, "classified as Simple (keyword match)");
        return TaskComplexity::Simple;
    }

    // Fast path: bugfix keywords
    if BUGFIX_KEYWORDS.iter().any(|kw| lower.contains(kw)) {
        info!(task, "classified as BugFix (keyword match)");
        return TaskComplexity::BugFix;
    }

    // Fast path: standard keywords
    if STANDARD_KEYWORDS.iter().any(|kw| lower.contains(kw)) {
        info!(task, "classified as Standard (keyword match)");
        return TaskComplexity::Standard;
    }

    // Ambiguous — use Claude to classify (or default to Simple in dry_run)
    if dry_run {
        info!(task, "ambiguous task in dry_run → defaulting to Simple");
        return TaskComplexity::Simple;
    }

    info!(task, "ambiguous task → asking Claude to classify");
    let prompt = format!(
        "Classify this task as either SIMPLE, STANDARD, or BUGFIX.\n\n\
         SIMPLE = documentation changes, typo fixes, renames, formatting, trivial edits.\n\
         STANDARD = new features, refactors, integrations, anything that needs tests.\n\
         BUGFIX = fixing bugs, crashes, errors, regressions, investigating broken behavior.\n\n\
         Task: {task}\n\n\
         Reply with ONLY the word SIMPLE, STANDARD, or BUGFIX, nothing else."
    );

    match claude_call(&prompt, "classify", trace_dir).await {
        Ok(response) => {
            let upper = response.trim().to_uppercase();
            if upper.contains("SIMPLE") {
                info!(task, "agent classified as Simple");
                TaskComplexity::Simple
            } else if upper.contains("BUGFIX") {
                info!(task, "agent classified as BugFix");
                TaskComplexity::BugFix
            } else {
                info!(task, "agent classified as Standard (default for ambiguous)");
                TaskComplexity::Standard
            }
        }
        Err(e) => {
            warn!(task, error = %e, "classification claude_call failed → defaulting to Standard");
            TaskComplexity::Standard
        }
    }
}

Keyword Lists

Simple Keywords

pipeline.rs:104-124
const SIMPLE_KEYWORDS: &[&str] = &[
    "fix typo",
    "fix the typo",
    "update readme",
    "update the readme",
    "fix docs",
    "fix the docs",
    "update docs",
    "update the docs",
    "update changelog",
    "update the changelog",
    "rename",
    "fix comment",
    "fix comments",
    "fix spelling",
    "fix whitespace",
    "fix formatting",
    "update license",
    "fix license",
];
Simple keywords are checked first so that "fix typo" is classified as Simple, not BugFix (even though it contains "fix").

BugFix Keywords

pipeline.rs:126-145
const BUGFIX_KEYWORDS: &[&str] = &[
    "fix bug",
    "fix the bug",
    "fix crash",
    "fix the crash",
    "fix error",
    "fix the error",
    "fix panic",
    "fix the panic",
    "broken",
    "not working",
    "regression",
    "debug",
    "investigate",
    "root cause",
    "diagnose",
];

Standard Keywords

pipeline.rs:147-164
const STANDARD_KEYWORDS: &[&str] = &[
    "add",
    "implement",
    "create",
    "build",
    "refactor",
    "migrate",
    "integrate",
    "introduce",
    "design",
    "architect",
    "extract",
    "replace",
    "rewrite",
    "optimize",
    "convert",
];

Classification Examples

# Keyword match: "fix typo"
@magpie fix typo in README.md
 TaskComplexity::Simple
 magpie-main blueprint

Tier 1 Classification

Ambiguous tasks use a Tier 1 Claude CLI call:
let prompt = format!(
    "Classify this task as either SIMPLE, STANDARD, or BUGFIX.\n\n\
     SIMPLE = documentation changes, typo fixes, renames, formatting, trivial edits.\n\
     STANDARD = new features, refactors, integrations, anything that needs tests.\n\
     BUGFIX = fixing bugs, crashes, errors, regressions, investigating broken behavior.\n\n\
     Task: {task}\n\n\
     Reply with ONLY the word SIMPLE, STANDARD, or BUGFIX, nothing else."
);

match claude_call(&prompt, "classify", trace_dir).await {
    Ok(response) => {
        let upper = response.trim().to_uppercase();
        if upper.contains("SIMPLE") {
            TaskComplexity::Simple
        } else if upper.contains("BUGFIX") {
            TaskComplexity::BugFix
        } else {
            TaskComplexity::Standard  // default for ambiguous
        }
    }
    Err(e) => TaskComplexity::Standard  // fallback on error
}
If the Claude call fails, the pipeline defaults to Standard (safest choice — runs full TDD flow).

Fallback Behavior

if dry_run {
    info!(task, "ambiguous task in dry_run → defaulting to Simple");
    return TaskComplexity::Simple;
}
In dry-run mode (testing), ambiguous tasks default to Simple without calling Claude.

Usage in Pipeline

pipeline.rs:960-1055
progress(platform, channel_id, "Analyzing task...").await;
let complexity = classify_task(task, config.dry_run, config.trace_dir.as_ref()).await;
info!(?complexity, "task classified");

match complexity {
    TaskComplexity::Standard => {
        progress(platform, channel_id, "Planning approach...").await;
        let (bp, ctx) = build_tdd_blueprint(&trigger, config, &working_dir)?;
        BlueprintRunner::new(ctx, &*sandbox).run(&bp).await?
    }
    TaskComplexity::BugFix => {
        progress(platform, channel_id, "Investigating bug...").await;
        let (bp, ctx) = build_diagnostic_blueprint(&trigger, config, &working_dir)?;
        BlueprintRunner::new(ctx, &*sandbox).run(&bp).await?
    }
    TaskComplexity::Simple => {
        progress(platform, channel_id, "Working on it...").await;
        let (bp, ctx) = build_main_blueprint(&trigger, config, &working_dir)?;
        BlueprintRunner::new(ctx, &*sandbox).run(&bp).await?
    }
}

Decision Tree

Best Practices

Use clear keywords to avoid ambiguous classification:
  • "add feature" → Standard
  • "fix bug" → BugFix
  • "fix typo" → Simple
"fix typo" is checked before "fix bug" to prevent false BugFix classification.
If no keywords match and Claude call fails, Standard is the safest choice (runs full TDD flow).
In dry-run mode, ambiguous tasks default to Simple to minimize overhead during testing.

Impact on Pipeline

ComplexityBlueprintStepsTest Strategy
Simplemagpie-main2None (docs-only)
Standardmagpie-tdd7Write tests first (TDD)
BugFixmagpie-diagnostic8Regression test after investigation
Classification happens after branch creation but before agent execution. This ensures the git branch is ready regardless of which blueprint runs.

Next Steps

Blueprints

See the full blueprint flows for each complexity level

Two-Tier Agent

Learn how Tier 1 Claude calls handle classification

Build docs developers (and LLMs) love