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

# Local Quickstart

> Build your first mobile automation with local LLM configuration

This guide covers **local development** where you configure LLMs via config files and have full control over the execution environment.

<Note>
  **Want a faster setup?** Check out the [Platform Quickstart](/docs/mobile-use-sdk/platform-quickstart) - no LLM config files needed and built-in observability!
</Note>

<Info>
  Make sure you've completed the [Installation](/docs/mobile-use-sdk/installation) steps before proceeding.
</Info>

## Configure LLM Settings

### 1. Create LLM Config File

Create a `llm-config.override.jsonc` file to configure your LLM models. This file will override the [default configuration](https://github.com/minitap-ai/mobile-use/blob/main/llm-config.defaults.jsonc).

```jsonc llm-config.override.jsonc theme={null}
// Your custom LLM configuration
{
  "planner": {
    "provider": "openai",
    "model": "gpt-5-nano"
  },
  "orchestrator": {
    "provider": "openai",
    "model": "gpt-5-nano"
  },
  "contextor": {
    // Optional: Only needed if using app lock feature
    "provider": "openai",
    "model": "gpt-5-nano",
    "fallback": {
      "provider": "openai",
      "model": "gpt-5-mini"
    }
  },
  "cortex": {
    // IMPORTANT: Needs vision capabilities!
    // Recommended: gpt-4o, gpt-5, or equivalent vision-capable model
    "provider": "openai",
    "model": "gpt-4o",
    "fallback": {
      "provider": "openai",
      "model": "gpt-5"
    }
  },
  "executor": {
    "provider": "openai",
    "model": "gpt-5-nano"
  },
  "utils": {
    "hopper": {
      // Needs at least a 256k context window
      "provider": "openai",
      "model": "gpt-5-nano"
    },
    "outputter": {
      "provider": "openai",
      "model": "gpt-5-nano"
    }
  }
}
```

### 2. Configure Environment Variables

Create a `.env` file in your project root with necessary API keys:

```bash .env theme={null}
# LLM API Keys (only include the ones you need)
OPENAI_API_KEY=your_key_here
XAI_API_KEY=your_key_here
OPEN_ROUTER_API_KEY=your_key_here
GOOGLE_API_KEY=your_key_here

# Optional: For local LLMs or custom OpenAI-compatible endpoints
# OPENAI_BASE_URL=http://localhost:1234/v1
```

<Warning>
  Never commit your `.env` file to version control. Add it to your `.gitignore`.
</Warning>

***

## Creating Your First Automation

Let's write a simple script that opens a calculator app and performs a basic calculation.

<Tip>
  For more examples, check out the [mobile-use SDK examples directory](https://github.com/minitap-ai/mobile-use/tree/main/minitap/mobile_use/sdk/examples) on GitHub.
</Tip>

```python calculator_demo.py theme={null}
import asyncio
from minitap.mobile_use.sdk import Agent
from minitap.mobile_use.sdk.types import AgentProfile
from minitap.mobile_use.sdk.builders import Builders

async def main():
    # Create an agent profile
    default_profile = AgentProfile(
        name="default",
        from_file="llm-config.override.jsonc"
    )

    # Configure the agent
    agent_config = Builders.AgentConfig.with_default_profile(default_profile).build()
    agent = Agent(config=agent_config)

    try:
        # Initialize the agent (connect to the first available device)
        await agent.init()

        # Define a simple task goal
        result = await agent.run_task(
            goal="Open the calculator app, calculate 123 * 456, and tell me the result",
            name="calculator_demo"
        )

        # Print the result
        print(f"Result: {result}")

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

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

### Run the script

```bash theme={null}
python calculator_demo.py
```

<Steps>
  <Step title="Initialize the Agent">
    The agent connects to your device and starts required servers.
  </Step>

  <Step title="Execute the Task">
    The agent interprets your goal, navigates the UI, and performs the calculation.
  </Step>

  <Step title="Clean Up">
    Resources are properly released.
  </Step>
</Steps>

## Getting Structured Output

Mobile-use SDK can return structured data using Pydantic models:

```python structured_output.py theme={null}
import asyncio
from pydantic import BaseModel, Field
from minitap.mobile_use.sdk import Agent
from minitap.mobile_use.sdk.types import AgentProfile
from minitap.mobile_use.sdk.builders import Builders

# Define a model for structured output
class CalculationResult(BaseModel):
    expression: str = Field(..., description="The mathematical expression calculated")
    result: float = Field(..., description="The result of the calculation")
    app_used: str = Field(..., description="The name of the calculator app used")

async def main():
    # Create an agent
    default_profile = AgentProfile(
        name="default",
        from_file="llm-config.override.jsonc"
    )
    agent_config = Builders.AgentConfig.with_default_profile(default_profile).build()
    agent = Agent(config=agent_config)

    try:
        await agent.init()

        # Request structured output using Pydantic model
        result = await agent.run_task(
            goal="Open the calculator app, calculate 123 * 456, and tell me the result",
            output=CalculationResult,
            name="structured_calculator"
        )

        if result:
            print(f"Expression: {result.expression}")
            print(f"Result: {result.result}")
            print(f"App used: {result.app_used}")

    finally:
        await agent.clean()

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

<Tip>
  Using Pydantic models ensures type-safe, validated output from your automation tasks.
</Tip>

## Understanding the Code

### Agent Profile

```python theme={null}
default_profile = AgentProfile(
    name="default", 
    from_file="llm-config.override.jsonc"
)
```

The `AgentProfile` defines which LLM models power different components of the agent.

### Agent Configuration

```python theme={null}
agent_config = Builders.AgentConfig.with_default_profile(default_profile).build()
```

The `Builders.AgentConfig` provides a fluent API to configure your agent.

### Running Tasks

```python theme={null}
result = await agent.run_task(
    goal="Your instruction here",
    output=YourPydanticModel,  # Optional
    name="task_name"  # Optional
)
```

Tasks are executed asynchronously and can return structured output.

## Comparing Local vs Platform

<CardGroup cols={2}>
  <Card title="✅ When to Use Local" icon="laptop">
    * Full control over LLM providers
    * Custom infrastructure requirements
    * Offline or air-gapped environments
    * Development and testing
  </Card>

  <Card title="🚀 When to Use Platform" icon="cloud" href="/docs/mobile-use-sdk/platform-quickstart">
    * Centralized configuration and management
    * Built-in cost monitoring and observability
    * Update tasks without code changes
  </Card>
</CardGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Core Concepts" icon="book" href="/docs/mobile-use-sdk/core-concepts/overview">
    Understand the architecture and components
  </Card>

  <Card title="Examples" icon="code" href="/docs/mobile-use-sdk/examples/simple-photo-organizer">
    Explore more practical examples
  </Card>

  <Card title="SDK Reference" icon="file-code" href="/docs/mobile-use-sdk/sdk-reference/agent">
    Detailed SDK documentation
  </Card>

  <Card title="Troubleshooting" icon="wrench" href="/docs/mobile-use-sdk/troubleshooting">
    Common issues and solutions
  </Card>
</CardGroup>
