Skip to content

Drift Monitoring

Alessio Rocchi edited this page Jan 29, 2026 · 1 revision

Drift Monitoring

Patterns for detecting and preventing semantic drift in task hierarchies.


Overview

Semantic drift occurs when subtasks gradually deviate from the original task scope. This recipe covers patterns for monitoring and preventing drift.


Pattern 1: Proactive Drift Check

Check for drift before creating subtasks.

// Parent task: "Implement user authentication"
const parentTaskId = 'auth-task-uuid';

// Before creating subtask, check for drift
const driftCheck = await mcp.call('task_check_drift', {
  taskInput: 'Add shopping cart functionality',
  taskType: 'coder',
  parentTaskId: parentTaskId
});

if (driftCheck.result.isDrift) {
  console.log(`Drift detected! Similarity: ${driftCheck.result.highestSimilarity}`);
  console.log(`Most similar to: ${driftCheck.result.mostSimilarTaskInput}`);
  console.log(`Action: ${driftCheck.result.action}`);

  // Don't create the subtask - it's off-topic
  throw new Error('Task would drift from parent scope');
}

// Safe to create
await mcp.call('task_create', {
  agentType: 'coder',
  input: 'Add shopping cart functionality',
  parentTaskId: parentTaskId
});

Pattern 2: Drift Metrics Dashboard

Monitor drift trends across your system.

// Get drift metrics for the past week
const metrics = await mcp.call('task_drift_metrics', {
  since: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString()
});

console.log(`
Drift Detection Summary (7 days):
  Total Events: ${metrics.metrics.totalEvents}
  Allowed: ${metrics.metrics.allowedCount}
  Warned: ${metrics.metrics.warnedCount}
  Prevented: ${metrics.metrics.preventedCount}
  Avg Similarity: ${(metrics.metrics.averageSimilarity * 100).toFixed(1)}%
`);

// Alert if too many warnings
const warningRate = metrics.metrics.warnedCount / metrics.metrics.totalEvents;
if (warningRate > 0.2) {
  console.warn('High drift warning rate - review task decomposition');
}

Pattern 3: Task Hierarchy Visualization

Visualize task relationships to understand drift patterns.

async function buildTaskTree(taskId, depth = 0) {
  const relationships = await mcp.call('task_get_relationships', {
    taskId: taskId,
    direction: 'outgoing'
  });

  const task = await mcp.call('task_get', { taskId });
  const indent = '  '.repeat(depth);

  console.log(`${indent}- ${task.task.input?.substring(0, 50)}...`);

  // Get child tasks
  const children = relationships.relationships
    .filter(r => r.relationshipType === 'parent_of');

  for (const child of children) {
    await buildTaskTree(child.toTaskId, depth + 1);
  }
}

// Visualize from root task
await buildTaskTree('root-task-uuid');

Pattern 4: Drift Prevention Mode

Configure strict drift prevention for critical workflows.

{
  "driftDetection": {
    "enabled": true,
    "threshold": 0.90,
    "warningThreshold": 0.80,
    "ancestorDepth": 5,
    "behavior": "prevent"
  }
}
// With prevent mode, drifted tasks are blocked
const result = await mcp.call('task_create', {
  agentType: 'coder',
  input: 'Completely unrelated task',
  parentTaskId: 'focused-task-uuid'
});

if (!result.success && result.error?.includes('drift')) {
  console.log('Task blocked due to drift:', result.drift);
  // Handle by either:
  // 1. Creating as new root task (no parent)
  // 2. Rephrasing to be more relevant
  // 3. Finding the correct parent task
}

Pattern 5: Ancestor Chain Analysis

Analyze the full ancestor chain for drift patterns.

async function analyzeAncestorChain(taskId) {
  const relationships = await mcp.call('task_get_relationships', {
    taskId: taskId,
    direction: 'incoming'
  });

  const ancestors = relationships.relationships
    .filter(r => r.relationshipType === 'parent_of' || r.relationshipType === 'derived_from');

  const chain = [];

  for (const rel of ancestors) {
    const task = await mcp.call('task_get', { taskId: rel.fromTaskId });
    chain.push({
      id: rel.fromTaskId,
      input: task.task.input,
      type: task.task.agentType
    });
  }

  return chain;
}

// Check full ancestry
const ancestry = await analyzeAncestorChain('current-task-uuid');
console.log('Task Ancestry:');
ancestry.forEach((t, i) => {
  console.log(`  ${i + 1}. [${t.type}] ${t.input?.substring(0, 60)}...`);
});

Pattern 6: Recent Drift Events

Review recent drift events for patterns.

const metrics = await mcp.call('task_drift_metrics', {});

console.log('Recent Drift Events:');
for (const event of metrics.recentEvents) {
  const status = event.actionTaken === 'prevented' ? 'BLOCKED' :
                 event.actionTaken === 'warned' ? 'WARNING' : 'OK';

  console.log(`
  [${status}] ${event.taskType}
    Similarity: ${(event.similarityScore * 100).toFixed(1)}%
    Similar to: ${event.ancestorTaskId}
    Time: ${event.createdAt}
  `);
}

Configuration Tips

{
  "driftDetection": {
    "enabled": true,
    "threshold": 0.95,
    "warningThreshold": 0.85,
    "ancestorDepth": 3,
    "behavior": "warn",
    "asyncEmbedding": true
  }
}

Threshold Guidelines:

  • 0.95+: Very strict - only nearly identical tasks flagged
  • 0.90-0.95: Moderate - catches obvious drift
  • 0.85-0.90: Sensitive - catches subtle scope creep
  • < 0.85: Very sensitive - may have false positives

Related:

Clone this wiki locally