Skip to main content
This example demonstrates a straightforward way to use the mobile-use SDK without builders or advanced configuration. It performs a real-world automation task.
This example is available on GitHub: simple_photo_organizer.py

What This Example Does

1

Opens the photo gallery

Navigates to the Photos/Gallery app
2

Finds photos from a specific date

Searches for photos taken yesterday
3

Creates an album

Creates a new album with a date-based name
4

Moves photos

Moves the found photos into the new album

Key Concepts

Simple Agent Creation

Uses default configuration with minimal setup

Structured Output

Returns typed Pydantic model for type-safe results

Direct run_task

No builders needed for simple tasks

Error Handling

Proper try/except/finally pattern

Complete Code

simple_photo_organizer.py
import asyncio
from datetime import date, timedelta
from pydantic import BaseModel, Field
from minitap.mobile_use.sdk import Agent


class PhotosResult(BaseModel):
    """Structured result from photo search."""

    found_photos: int = Field(..., description="Number of photos found")
    date_range: str = Field(..., description="Date range of photos found")
    album_created: bool = Field(..., description="Whether an album was created")
    album_name: str = Field(..., description="Name of the created album")
    photos_moved: int = Field(0, description="Number of photos moved to the album")


async def main() -> None:
    # Create a simple agent with default configuration
    agent = Agent()

    try:
        # Initialize agent (finds a device, starts required servers)
        agent.init()

        # Calculate yesterday's date for the example
        yesterday = date.today() - timedelta(days=1)
        formatted_date = yesterday.strftime("%B %d")  # e.g. "August 22"

        print(f"Looking for photos from {formatted_date}...")

        # First task: search for photos and organize them, with typed output
        result = await agent.run_task(
            goal=(
                f"Open the Photos/Gallery app. Find photos taken on {formatted_date}. "
                f"Create a new album named '{formatted_date} Memories' and "
                f"move those photos into it. Count how many photos were moved."
            ),
            output=PhotosResult,
            name="organize_photos",
        )

        # Handle and display the result
        if result:
            print("\n=== Photo Organization Complete ===")
            print(f"Found: {result.found_photos} photos from {result.date_range}")

            if result.album_created:
                print(f"Created album: '{result.album_name}'")
                print(f"Moved {result.photos_moved} photos to the album")
            else:
                print("No album was created")
        else:
            print("Failed to organize photos")

    except Exception as e:
        print(f"Error: {e}")
    finally:
        # Always clean up resources
        agent.clean()


if __name__ == "__main__":
    asyncio.run(main())

Code Breakdown

1. Define Output Structure

class PhotosResult(BaseModel):
    found_photos: int = Field(..., description="Number of photos found")
    date_range: str = Field(..., description="Date range of photos found")
    album_created: bool = Field(..., description="Whether an album was created")
    album_name: str = Field(..., description="Name of the created album")
    photos_moved: int = Field(0, description="Number of photos moved to the album")
Use detailed field descriptions to help the LLM extract accurate data.

2. Create Agent with Default Config

agent = Agent()
No configuration needed for simple use cases. The agent will use default settings.

3. Initialize the Agent

agent.init()
This connects to the first available device and starts required servers.

4. Run Task with Structured Output

result = await agent.run_task(
    goal="...",  # Natural language goal
    output=PhotosResult,  # Pydantic model for output
    name="organize_photos"  # Optional task name
)
The result is automatically validated and typed as PhotosResult | None.

5. Always Clean Up

finally:
    agent.clean()
Always call agent.clean() in a finally block to ensure resources are released.

Running the Example

1

Ensure Prerequisites

  • Device connected with USB debugging enabled
  • Maestro installed
  • Python 3.12+
2

Install SDK

pip install minitap-mobile-use
3

Set up LLM Config

Create llm-config.defaults.jsonc and .env file (see Installation)
4

Run the Script

python simple_photo_organizer.py

Expected Output

Looking for photos from October 08...

=== Photo Organization Complete ===
Found: 12 photos from October 08
Created album: 'October 08 Memories'
Moved 12 photos to the album

Customization Ideas

# Last week
week_ago = date.today() - timedelta(days=7)

# Specific date
specific_date = date(2024, 10, 1)
goal = (
    f"Find all selfie photos from {formatted_date} and "
    f"create an album called 'Selfies - {formatted_date}'"
)
# Run multiple tasks in sequence
for i in range(7):
    day = date.today() - timedelta(days=i)
    await agent.run_task(
        goal=f"Organize photos from {day.strftime('%B %d')}",
        output=PhotosResult
    )

What’s Next

⌘I