Skip to main content
Beta Feature — Mobile automation is currently in beta. Please report any issues to founders@morphllm.com.
While we recommend direct execution for better control and trace access, you can also use mobile tasks as agent tools in your AI applications.

Quick Start

import Anthropic from '@anthropic-ai/sdk';
import { createMobileTool } from '@morphllm/morphsdk/tools/mobile/anthropic';

const anthropic = new Anthropic();
const { tool, execute } = createMobileTool({
  apiKey: "YOUR_API_KEY",
  defaultAppUrl: "bs://your-app-hash",
  defaultDevice: { name: "iPhone 16 Pro", version: "18" }
});

const response = await anthropic.messages.create({
  model: "claude-sonnet-4-5-20250929",
  max_tokens: 12000,
  tools: [tool],
  messages: [{
    role: "user",
    content: "Test the login flow in our iOS app"
  }]
});

// Handle tool calls
const toolUse = response.content.find(b => b.type === 'tool_use');
if (toolUse) {
  const result = await execute(toolUse.input);
  console.log(result.result);
  console.log('Trace:', result.trace_url);
}

Tradeoffs

Agent tools (simpler integration):
  • ✅ Easy to add to existing agent workflows
  • ✅ Let the LLM decide when to use mobile testing
  • ❌ No live session monitoring
  • ❌ Adds extra LLM call overhead
  • ❌ Limited debugging capabilities
Direct execution (recommended):
  • ✅ Full control over device and app configuration
  • ✅ Access to BrowserStack session URLs
  • ✅ GIF trace recordings
  • ✅ Better error handling
  • ❌ Requires explicit calls (not agent-driven)
For most use cases, we recommend direct execution for better control and debugging capabilities.

Tool Configuration

All tool adapters support the same configuration options:
import { createMobileTool } from '@morphllm/morphsdk/tools/mobile/anthropic';

const { tool, execute } = createMobileTool({
  apiKey: "YOUR_API_KEY",
  apiUrl: 'https://mobile.morphllm.com',  // Override API URL

  // Default device configuration
  defaultPlatform: 'ios',
  defaultDevice: {
    name: 'iPhone 16 Pro',
    version: '18'
  },

  // Default app (can be overridden per-call)
  defaultAppUrl: 'bs://your-app-hash',

  // Execution defaults
  defaultMaxSteps: 30,
  defaultRecordTrace: true
});

Example: Multi-tool Agent

Combine mobile automation with other tools:
import Anthropic from '@anthropic-ai/sdk';
import { createMobileTool } from '@morphllm/morphsdk/tools/mobile/anthropic';
import { createBrowserTool } from '@morphllm/morphsdk/tools/browser/anthropic';

const anthropic = new Anthropic();

const { tool: mobileTool, execute: executeMobile } = createMobileTool({
  defaultAppUrl: 'bs://your-app-hash'
});

const { tool: browserTool, execute: executeBrowser } = createBrowserTool();

const tools = [mobileTool, browserTool];

const response = await anthropic.messages.create({
  model: "claude-sonnet-4-5-20250929",
  max_tokens: 12000,
  tools,
  messages: [{
    role: "user",
    content: "Test the signup flow in our iOS app, then verify the web dashboard shows the new user"
  }]
});

// Handle tool calls
for (const block of response.content) {
  if (block.type === 'tool_use') {
    if (block.name === 'mobile_task') {
      const result = await executeMobile(block.input);
      console.log('Mobile result:', result.result);
    } else if (block.name === 'browser_task') {
      const result = await executeBrowser(block.input);
      console.log('Browser result:', result.result);
    }
  }
}

Tool Schema

The mobile tool accepts the following parameters:
{
  // Required
  task: string,              // Natural language task description

  // Optional - override defaults
  platform?: 'ios' | 'android',
  device_name?: string,
  platform_version?: string,
  app_url?: string,          // Override default app
  max_steps?: number,
  record_trace?: boolean
}

Formatting Results

The tool adapters return concise results suitable for agent consumption:
import { createMobileTool, formatResult } from '@morphllm/morphsdk/tools/mobile/anthropic';

const { tool, execute } = createMobileTool();

// Custom execution with full data
const fullResult = await execute(input, { returnFullResponse: true });

// Format for agent consumption
const formattedResult = formatResult(fullResult);
console.log(formattedResult); // Concise summary

// Access full data if needed
console.log('Trace:', fullResult.trace_url);
console.log('Steps:', fullResult.steps_taken);
console.log('Session:', fullResult.browserstack_session_url);

Migration from Direct Execution

If you’re currently using direct execution and want to try tools: Before (direct execution):
import { MobileClient } from '@morphllm/morphsdk/tools/mobile';

const mobile = new MobileClient({ apiKey: "YOUR_API_KEY" });

const result = await mobile.execute({
  task: "Test login flow",
  platform: "ios",
  app_url: "bs://your-app-hash",
  device_name: "iPhone 16 Pro",
  platform_version: "18"
});
After (as tool):
import { createMobileTool } from '@morphllm/morphsdk/tools/mobile/anthropic';

const { tool, execute } = createMobileTool({
  apiKey: "YOUR_API_KEY",
  defaultAppUrl: "bs://your-app-hash",
  defaultDevice: { name: "iPhone 16 Pro", version: "18" }
});

// Add to your agent's tools array
tools: [tool, /* other tools */]

// Agent will call when needed

See Also