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

# Tasks and Task Requests

> Goal-based automation workflows with structured output

Tasks represent automation workflows to be executed on a mobile device. They are defined using natural language goals and can return structured, type-safe results.

<Tabs>
  <Tab title="Platform (Recommended)">
    With the platform, tasks are **configured on [platform.mobile-use.ai](https://platform.mobile-use.ai/tasks)** and executed using `PlatformTaskRequest`.

    * Define tasks once on the platform
    * Update prompts without code changes
    * Built-in observability and cost tracking
  </Tab>

  <Tab title="Local Development">
    For local development, tasks are defined **directly in code** with natural language goals.

    * Full control over task configuration
    * Define goals and outputs in your codebase
  </Tab>
</Tabs>

## Task Characteristics

<CardGroup cols={3}>
  <Card title="Goal-based" icon="bullseye">
    Define what you want using natural language
  </Card>

  <Card title="Traceable" icon="route">
    Record execution for debugging and visualization
  </Card>

  <Card title="Structured Output" icon="table">
    Return typed Pydantic models
  </Card>
</CardGroup>

## Platform Tasks

<Note>
  **Using the platform?** Create tasks on [platform.mobile-use.ai/tasks](https://platform.mobile-use.ai/tasks) and execute them with `PlatformTaskRequest`.
</Note>

### Creating Platform Tasks

1. Go to [**Tasks**](https://platform.mobile-use.ai/tasks) on the platform
2. Click **Create Task**
3. Configure task details:
   * **Name**: Unique identifier (e.g., `check-notifications`)
   * **Agent Prompt**: Detailed instructions
   * **Output Description**: Optional structured output format
   * **Locked App Package**: Optional app package to restrict execution (e.g., `com.whatsapp`)
4. Use in your code:

```python theme={null}
from minitap.mobile_use.sdk.types import PlatformTaskRequest

result = await agent.run_task(
    request=PlatformTaskRequest(task="check-notifications")
)
```

### Platform Task with Structured Output

```python theme={null}
from pydantic import BaseModel, Field
from minitap.mobile_use.sdk.types import PlatformTaskRequest

class NotificationSummary(BaseModel):
    total: int = Field(..., description="Total notifications")
    unread: int = Field(..., description="Unread count")

result = await agent.run_task(
    request=PlatformTaskRequest[NotificationSummary](
        task="check-notifications",
        profile="fast"  # Optional: use specific platform profile
    )
)

if result:
    print(f"Total: {result.total}, Unread: {result.unread}")
```

### Platform Task with Locked App Package

When creating a task on the platform, you can specify a **Locked App Package** to restrict the agent to a specific app:

```
Name: send-whatsapp-message
Agent Prompt: Send the message "<message>" to <contact> on WhatsApp
Locked App Package: com.whatsapp
```

The task will be displayed with a 🔒 indicator showing the locked package.

**Using the `<locked-app-package>` placeholder:**

You can reference the locked app package in your agent prompt using the `<locked-app-package>` placeholder:

```
Open <locked-app-package> and navigate to settings
```

This placeholder will be automatically replaced with the configured package name at execution time.

### Platform Task Benefits

<CardGroup cols={2}>
  <Card title="Centralized Management" icon="cloud">
    Update task prompts on the platform without redeploying code
  </Card>

  <Card title="Built-in Observability" icon="chart-line">
    View execution details, costs, and agent thoughts on the platform
  </Card>

  <Card title="Team Collaboration" icon="users">
    Share tasks across your organization
  </Card>

  <Card title="Version Control" icon="clock-rotate-left">
    Track changes to task configurations over time
  </Card>
</CardGroup>

***

## Local Tasks

For local development, define tasks directly in code:

### Simple String Output

The most basic way to run a local task:

```python theme={null}
result = await agent.run_task(
    goal="Open settings and enable dark mode"
)
print(result)  # String output
```

### Structured Output with Pydantic

Get type-safe, validated output:

```python theme={null}
from pydantic import BaseModel, Field

class ThemeSettings(BaseModel):
    dark_mode_enabled: bool = Field(..., description="Whether dark mode is enabled")
    theme_name: str = Field(..., description="Name of the current theme")

result = await agent.run_task(
    goal="Check the current theme settings",
    output=ThemeSettings
)

print(f"Dark mode: {result.dark_mode_enabled}")
print(f"Theme: {result.theme_name}")
```

### With Output Description

Provide guidance for unstructured output:

```python theme={null}
result = await agent.run_task(
    goal="Find all my unread emails",
    output="A comma-separated list of email subjects"
)
```

## Task Options

### Naming Tasks

Give your tasks descriptive names for logging:

```python theme={null}
await agent.run_task(
    goal="Send a message to John",
    name="send_message_john"
)
```

### Using Different Profiles

Switch agent profiles for specific tasks:

```python theme={null}
await agent.run_task(
    goal="Analyze this complex form",
    profile="detail_oriented"  # Uses a different LLM configuration
)
```

### Maximum Steps

Control how many actions the agent can take:

```python theme={null}
task = (
    agent.new_task("Complete checkout process")
    .with_max_steps(500)  # Default is 400
    .build()
)

await agent.run_task(request=task)
```

### App Lock

Restrict task execution to a specific app:

```python theme={null}
task = (
    agent.new_task("Send a message to Alice")
    .with_locked_app_package("com.whatsapp")  # Android package or iOS bundle ID
    .build()
)

await agent.run_task(request=task)
```

When app lock is enabled, the agent will:

* Verify the app is open before starting
* Attempt to launch it if not in foreground
* Monitor app changes during execution
* Automatically relaunch if needed

## Task Builder Pattern

For advanced configuration, use the builder pattern:

```python theme={null}
task_request = (
    agent.new_task("Open settings and check notifications")
    .with_name("check_notification_settings")
    .with_max_steps(300)
    .with_output_description("Summary of notification settings")
    .with_locked_app_package("com.android.settings")
    .with_trace_recording(enabled=True)
    .build()
)

result = await agent.run_task(request=task_request)
```

## Tracing and Debugging

Enable trace recording to capture screenshots and execution steps:

```python theme={null}
from pathlib import Path

task = (
    agent.new_task("Navigate to profile settings")
    .with_trace_recording(
        enabled=True,
        path=Path("/tmp/my-traces")
    )
    .build()
)

await agent.run_task(request=task)
```

<Info>
  Traces include screenshots at each step, making it easy to debug failed tasks.
</Info>

## Saving Output

### Save LLM Output

Save the final LLM response to a file:

```python theme={null}
task = (
    agent.new_task("Extract product information")
    .with_llm_output_saving(path="/tmp/llm_output.json")
    .build()
)
```

### Save Agent Thoughts

Capture the agent's reasoning process:

```python theme={null}
task = (
    agent.new_task("Book a restaurant reservation")
    .with_thoughts_output_saving(path="/tmp/agent_thoughts.txt")
    .build()
)
```

## Complex Output Structures

Define complex, nested output structures:

```python theme={null}
from pydantic import BaseModel, Field
from typing import List

class Email(BaseModel):
    sender: str
    subject: str
    preview: str
    is_unread: bool

class InboxSummary(BaseModel):
    total_emails: int = Field(..., description="Total number of emails")
    unread_count: int = Field(..., description="Number of unread emails")
    emails: List[Email] = Field(..., description="List of recent emails")

result = await agent.run_task(
    goal="Open Gmail and analyze my inbox",
    output=InboxSummary
)

for email in result.emails:
    if email.is_unread:
        print(f"Unread: {email.subject} from {email.sender}")
```

## Task Execution Flow

<Steps>
  <Step title="Goal Analysis">
    LLM analyzes the goal and creates a plan
  </Step>

  <Step title="Screen Observation">
    Agent captures current screen state
  </Step>

  <Step title="Action Decision">
    LLM decides next action based on goal and screen
  </Step>

  <Step title="Action Execution">
    Hardware bridge performs the action
  </Step>

  <Step title="Verification">
    Agent checks if goal is achieved
  </Step>

  <Step title="Output Extraction">
    If specified, extract structured output
  </Step>
</Steps>

## Best Practices

<AccordionGroup>
  <Accordion title="Be specific in your goals" icon="bullseye">
    ```python theme={null}
    # ✅ Good - specific
    goal="Open Weather app, check temperature for New York, and tell me if it will rain tomorrow"

    # ❌ Bad - vague
    goal="Check weather"
    ```
  </Accordion>

  <Accordion title="Use Pydantic for structured output" icon="check">
    Define clear field descriptions to help the LLM understand what to extract

    ```python theme={null}
    class WeatherInfo(BaseModel):
        temperature: float = Field(..., description="Current temperature in Celsius")
        will_rain_tomorrow: bool = Field(..., description="Whether rain is forecast for tomorrow")
    ```
  </Accordion>

  <Accordion title="Break complex tasks into simpler ones" icon="list">
    Instead of one complex task, run multiple simpler tasks in sequence

    ```python theme={null}
    # Step 1: Navigate
    await agent.run_task(goal="Open banking app and go to transactions")

    # Step 2: Extract data
    transactions = await agent.run_task(
        goal="Get the last 5 transactions",
        output=TransactionList
    )
    ```
  </Accordion>

  <Accordion title="Enable tracing for debugging" icon="bug">
    Always enable tracing when developing or debugging tasks

    ```python theme={null}
    task = agent.new_task(goal).with_trace_recording(enabled=True).build()
    ```
  </Accordion>
</AccordionGroup>

## Example: Multi-Step Workflow

<Tabs>
  <Tab title="Platform">
    ```python theme={null}
    import asyncio
    from pydantic import BaseModel, Field
    from typing import List
    from minitap.mobile_use.sdk import Agent
    from minitap.mobile_use.sdk.types import PlatformTaskRequest

    class Product(BaseModel):
        name: str
        price: float
        in_stock: bool

    class ShoppingResults(BaseModel):
        products: List[Product]
        total_found: int

    async def shop_online():
        agent = Agent()
        agent.init()
        
        try:
            # Step 1: Search (task configured on platform)
            await agent.run_task(
                request=PlatformTaskRequest(task="search-products")
            )
            
            # Step 2: Extract results (task configured on platform)
            results = await agent.run_task(
                request=PlatformTaskRequest[ShoppingResults](
                    task="extract-product-results"
                )
            )
            
            # Step 3: Filter and act
            for product in results.products:
                if product.in_stock and product.price < 50:
                    print(f"Good deal: {product.name} - ${product.price}")
            
        finally:
            agent.clean()
    ```
  </Tab>

  <Tab title="Local">
    ```python theme={null}
    import asyncio
    from pydantic import BaseModel, Field
    from typing import List
    from minitap.mobile_use.sdk import Agent

    class Product(BaseModel):
        name: str
        price: float
        in_stock: bool

    class ShoppingResults(BaseModel):
        products: List[Product]
        total_found: int

    async def shop_online():
        agent = Agent(...)  # Configure with local profile
        agent.init()
        
        try:
            # Step 1: Search
            await agent.run_task(
                goal="Open Amazon app and search for 'bluetooth headphones'",
                name="search_products"
            )
            
            # Step 2: Extract results
            results = await agent.run_task(
                goal="Get the first 5 product results with names, prices, and availability",
                output=ShoppingResults,
                name="extract_products"
            )
            
            # Step 3: Filter and act
            for product in results.products:
                if product.in_stock and product.price < 50:
                    print(f"Good deal: {product.name} - ${product.price}")
            
        finally:
            agent.clean()
    ```
  </Tab>
</Tabs>

## Next Steps

<CardGroup cols={2}>
  <Card title="Profiles" icon="user-gear" href="/docs/mobile-use-sdk/core-concepts/profiles">
    Customize agent behavior
  </Card>

  <Card title="Task Builder SDK" icon="file-code" href="/docs/mobile-use-sdk/sdk-reference/task-request-builder">
    Detailed task configuration SDK
  </Card>
</CardGroup>
