> ## Documentation Index
> Fetch the complete documentation index at: https://www.minitap.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Simple Photo Organizer

> Basic SDK usage example with structured output

This example demonstrates a straightforward way to use the mobile-use SDK without builders or advanced configuration. It performs a real-world automation task.

<Tip>
  This example is available on GitHub: [simple\_photo\_organizer.py](https://github.com/minitap-ai/mobile-use/blob/main/minitap/mobile_use/sdk/examples/simple_photo_organizer.py)
</Tip>

## What This Example Does

<Steps>
  <Step title="Opens the photo gallery">
    Navigates to the Photos/Gallery app
  </Step>

  <Step title="Finds photos from a specific date">
    Searches for photos taken yesterday
  </Step>

  <Step title="Creates an album">
    Creates a new album with a date-based name
  </Step>

  <Step title="Moves photos">
    Moves the found photos into the new album
  </Step>
</Steps>

## Key Concepts

<CardGroup cols={2}>
  <Card title="Simple Agent Creation" icon="robot">
    Uses default configuration with minimal setup
  </Card>

  <Card title="Structured Output" icon="table">
    Returns typed Pydantic model for type-safe results
  </Card>

  <Card title="Direct run_task" icon="play">
    No builders needed for simple tasks
  </Card>

  <Card title="Error Handling" icon="shield">
    Proper try/except/finally pattern
  </Card>
</CardGroup>

## Complete Code

```python simple_photo_organizer.py theme={null}
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)
        await 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
        await agent.clean()


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

## Code Breakdown

### 1. Define Output Structure

```python theme={null}
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")
```

<Tip>
  Use detailed field descriptions to help the LLM extract accurate data.
</Tip>

### 2. Create Agent with Default Config

```python theme={null}
agent = Agent()
```

No configuration needed for simple use cases. The agent will use default settings.

### 3. Initialize the Agent

```python theme={null}
await agent.init()
```

This connects to the first available device and starts required servers.

<Info>
  Note that `init()` is now an async method and must be awaited.
</Info>

### 4. Run Task with Structured Output

```python theme={null}
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

```python theme={null}
finally:
    await agent.clean()
```

<Warning>
  Always call `await agent.clean()` in a `finally` block to ensure resources are released. Note that `clean()` is now an async method.
</Warning>

## Running the Example

<Steps>
  <Step title="Ensure Prerequisites">
    * Device connected with USB debugging enabled
    * ADB installed (Android) or idb installed (iOS)
    * Python 3.12+
  </Step>

  <Step title="Install SDK">
    ```bash theme={null}
    pip install minitap-mobile-use
    ```
  </Step>

  <Step title="Set up LLM Config">
    Create `llm-config.defaults.jsonc` and `.env` file (see [Installation](/docs/mobile-use-sdk/installation))
  </Step>

  <Step title="Run the Script">
    ```bash theme={null}
    python simple_photo_organizer.py
    ```
  </Step>
</Steps>

## 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

<AccordionGroup>
  <Accordion title="Change date range" icon="calendar">
    ```python theme={null}
    # Last week
    week_ago = date.today() - timedelta(days=7)

    # Specific date
    specific_date = date(2024, 10, 1)
    ```
  </Accordion>

  <Accordion title="Filter by photo type" icon="filter">
    ```python theme={null}
    goal = (
        f"Find all selfie photos from {formatted_date} and "
        f"create an album called 'Selfies - {formatted_date}'"
    )
    ```
  </Accordion>

  <Accordion title="Multiple albums" icon="folder-tree">
    ```python theme={null}
    # 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
        )
    ```
  </Accordion>
</AccordionGroup>

## What's Next

<CardGroup cols={2}>
  <Card title="App Lock - Messaging Example" icon="lock" href="/docs/mobile-use-sdk/examples/app-lock-messaging">
    Learn how to restrict execution to a specific app
  </Card>

  <Card title="Smart Notification Assistant" icon="bell" href="/docs/mobile-use-sdk/examples/smart-notification-assistant">
    More advanced example with multiple profiles
  </Card>

  <Card title="SDK Reference" icon="file-code" href="/docs/mobile-use-sdk/sdk-reference/agent">
    Explore the complete SDK
  </Card>
</CardGroup>
