Skip to main content
TestDriver is designed from the ground up to be used by AI agents, enabling autonomous test creation, execution, and debugging.

AI Agent Support

Complete guide for AI agents with autonomous operation patterns:

agents.md - AI Agent Guide

Comprehensive documentation specifically for AI agents, including:
  • Quick setup and authentication
  • Provision methods (chrome, vscode, electron)
  • Core API methods with examples
  • Sandbox reconnection patterns
  • Debugging failed finds
  • Iterative selector refinement
  • Best practices for autonomous operation
// AI agents can autonomously write and run tests
import { test } from 'vitest';
import { chrome } from 'testdriverai/presets';

test('ai-generated test', async (context) => {
  const { testdriver } = await chrome(context, {
    url: 'https://example.com'
  });

  await testdriver.find('More information link').click();
  await testdriver.assert('IANA page is visible');
});

Natural Language Everything

AI-powered element location, assertions, and instructions:
  • Element Location
  • Assertions
  • Instructions
// Describe elements naturally
await testdriver.find('submit button');
await testdriver.find('email input in the login form');
await testdriver.find('delete button in the top right corner');
await testdriver.find('first product card in the grid');

Iterative Selector Refinement

AI agents can iteratively refine selectors when initial attempts fail:
test('iterative debugging', async (context) => {
  const testdriver = new TestDriver({
    apiKey: process.env.TD_API_KEY
  });

  const instance = await testdriver.connect();
  const sandboxId = instance.instanceId;

  // Try multiple selector variations
  const selectors = [
    'submit button',
    'blue submit button',
    'submit button in bottom right',
    'button with "Submit" text',
    'primary action button'
  ];

  for (const selector of selectors) {
    try {
      console.log(`Trying: ${selector}`);
      const element = await testdriver.find(selector);
      console.log(`✓ Found with: ${selector}`);
      await element.click();
      break; // Success!
    } catch (error) {
      console.log(`✗ Failed with: ${selector}`);
      console.log(`  Similarity: ${error.similarity}`);
      console.log(`  Confidence: ${error.confidence}`);
    }
  }

  await testdriver.disconnect();
});
AI agents can analyze error similarity scores to refine subsequent selector attempts intelligently.

Sandbox Reconnection

AI agents can reconnect to sandboxes for debugging:
// Initial test attempt
test('initial attempt', async () => {
  const testdriver = new TestDriver({
    apiKey: process.env.TD_API_KEY
  });

  const instance = await testdriver.connect();
  console.log('Sandbox ID:', instance.instanceId);
  // Save this ID for reconnection

  try {
    await testdriver.find('difficult selector').click();
  } catch (error) {
    console.error('Failed:', error);
    // Keep sandbox alive for debugging
  }
});

// Reconnect to same sandbox
test('reconnect attempt', async () => {
  const testdriver = new TestDriver({
    apiKey: process.env.TD_API_KEY
  });

  // Read last sandbox ID
  const lastSandboxId = testdriver.getLastSandboxId();

  // Reconnect
  await testdriver.connect({
    sandboxId: lastSandboxId,
    newSandbox: false
  });

  // Try alternative selector
  await testdriver.find('alternative selector').click();

  await testdriver.disconnect();
});

Automatic Sandbox Tracking

TestDriver saves the last sandbox ID to .testdriver/last-sandbox automatically. AI agents can read this file to reconnect without manual ID tracking.

Error Analysis

Rich error information for AI agents to analyze and adapt:
try {
  await testdriver.find('non-existent button').click();
} catch (error) {
  // Rich error information for AI analysis
  console.log('Error type:', error.name); // 'ElementNotFoundError'
  console.log('Message:', error.message);
  console.log('Similarity score:', error.similarity); // 0.72
  console.log('Confidence:', error.confidence); // 0.81
  console.log('Debug screenshot:', error.debugScreenshot); // Base64
  console.log('Cache info:', error.cacheInfo);
  console.log('Attempted prompt:', error.prompt);

  // AI can analyze and adapt
  if (error.similarity > 0.7) {
    // Close match, try more specific selector
    await testdriver.find('blue submit button in bottom right').click();
  } else {
    // No close match, try completely different approach
    await testdriver.find('primary action button').click();
  }
}

Autonomous Test Generation

AI agents can generate entire test suites:
// AI agent generates tests from requirements
const requirements = `
  Test the login flow:
  1. Navigate to login page
  2. Enter valid credentials
  3. Click submit
  4. Verify dashboard appears
`;

// Agent generates:
test('user can login', async (context) => {
  const { testdriver } = await chrome(context, {
    url: 'https://myapp.com/login'
  });

  await testdriver.find('email input').type('[email protected]');
  await testdriver.find('password input').type('password', { secret: true });
  await testdriver.find('Login button').click();

  await testdriver.assert('Dashboard is visible');
});

MCP Integration (Coming Soon)

Query test infrastructure using natural language:
// Future MCP interactivity
await testdriver.mcp.query("What is the CPU usage of my app?");
await testdriver.mcp.query("Show me memory leaks in the last test run");
await testdriver.mcp.query("What tests are flakiest this week?");
await testdriver.mcp.query("Compare performance between branches");
MCP (Model Context Protocol) integration is planned for Q1 2025.

AI-Powered Debugging

TestDriver provides intelligent debugging assistance:
// AI analyzes how close the match was
try {
  await testdriver.find('submit button');
} catch (error) {
  if (error.similarity > 0.8) {
    console.log('Very close match - likely wrong selector specificity');
  } else if (error.similarity > 0.5) {
    console.log('Partial match - element might be present but different');
  } else {
    console.log('No match - element likely not on screen');
  }
}
// Get debug screenshot for AI analysis
try {
  await testdriver.find('button');
} catch (error) {
  // AI can analyze the debug screenshot
  const screenshot = error.debugScreenshot; // Base64 image
  // Send to vision model for analysis
  const analysis = await visionModel.analyze(screenshot,
    "Why can't we find the submit button?"
  );
}
// Understand cache behavior
try {
  await testdriver.find('element');
} catch (error) {
  console.log('Cache info:', error.cacheInfo);
  // {
  //   cacheKey: 'abc123',
  //   cacheHit: false,
  //   similarEntries: 3,
  //   bestSimilarity: 0.87,
  //   reason: 'threshold_not_met'
  // }
}

Programmatic Control

AI agents have full programmatic control:
// Dynamic test generation
const testCases = [
  { email: '[email protected]', password: 'pass1', shouldSucceed: true },
  { email: 'invalid', password: 'pass2', shouldSucceed: false },
  { email: '[email protected]', password: 'wrong', shouldSucceed: false },
];

for (const testCase of testCases) {
  test(`login with ${testCase.email}`, async (context) => {
    const { testdriver } = await chrome(context, { url });

    await testdriver.find('email input').type(testCase.email);
    await testdriver.find('password input').type(testCase.password, { secret: true });
    await testdriver.find('submit').click();

    if (testCase.shouldSucceed) {
      await testdriver.assert('dashboard is visible');
    } else {
      await testdriver.assert('error message is displayed');
    }
  });
}

Learning & Adaptation

TestDriver learns from test executions:

AI Understanding of Your App

The cache system builds a visual understanding over time:
  • Element location patterns
  • UI component relationships
  • Common interaction flows
  • Stability characteristics
  • Performance baselines
This enables:
  • Faster subsequent executions
  • Better error messages
  • Intelligent suggestions
  • Anomaly detection

Best Practices for AI Agents

// ✅ Good - specific and contextual
await testdriver.find('blue submit button below the login form');

// ❌ Bad - too vague
await testdriver.find('button');
// ✅ Protected from logging
await testdriver.type('MyPassword123', { secret: true });

// ❌ Password will be logged
await testdriver.type('MyPassword123');
// ✅ Try alternative approaches
try {
  await testdriver.find('optional element').click();
} catch (error) {
  console.log('Element not found, trying alternative...');
  await testdriver.find('alternative element').click();
}
// ✅ Enable reconnection
const instance = await testdriver.connect();
console.log('Sandbox ID:', instance.instanceId);
// Save for debugging later

Learn More