Skip to main content
The mobile-use SDK provides builder classes that offer a fluent, type-safe way to configure agents and tasks. Builders make complex configurations more readable and help prevent errors.

Why Use Builders?

Readable

Chain methods for clear, self-documenting code

Type-Safe

Catch configuration errors at development time

Flexible

Easy to adjust configurations without rewriting code

Discoverable

IDE autocomplete shows all available options

Builders Overview

The SDK provides access to builders through the Builders object:
from minitap.mobile_use.sdk.builders import Builders

# Agent configuration
agent_config = Builders.AgentConfig...

# Task defaults
task_defaults = Builders.TaskDefaults...

Agent Config Builder

Configure how the agent connects to devices and servers:

Basic Usage

from minitap.mobile_use.sdk.builders import Builders
from minitap.mobile_use.sdk.types import AgentProfile

profile = AgentProfile(name="default", from_file="llm-config.defaults.jsonc")

config = (
    Builders.AgentConfig
    .with_default_profile(profile)
    .build()
)

agent = Agent(config=config)

Available Methods

Set the default agent profile for tasks
config = (
    Builders.AgentConfig
    .with_default_profile(profile)
    .build()
)
Register additional profiles
config = (
    Builders.AgentConfig
    .add_profiles([fast_profile, accurate_profile])
    .with_default_profile(fast_profile)
    .build()
)
Target a specific device instead of auto-detection
from minitap.mobile_use.sdk.types import DevicePlatform

config = (
    Builders.AgentConfig
    .for_device(
        platform=DevicePlatform.ANDROID,
        device_id="emulator-5554"
    )
    .build()
)
Configure Hardware Bridge server URL
config = (
    Builders.AgentConfig
    .with_hw_bridge(url="http://localhost:8001")
    .build()
)
Configure Screen API server URL
config = (
    Builders.AgentConfig
    .with_screen_api(url="http://localhost:8000")
    .build()
)
Configure ADB server connection
config = (
    Builders.AgentConfig
    .with_adb_server(host="localhost", port=5037)
    .build()
)
Set default configuration for all tasks
task_defaults = (
    Builders.TaskDefaults
    .with_max_steps(500)
    .build()
)

config = (
    Builders.AgentConfig
    .with_default_task_config(task_defaults)
    .build()
)

Complete Example

from minitap.mobile_use.sdk.builders import Builders
from minitap.mobile_use.sdk.types import AgentProfile, DevicePlatform

# Create profiles
fast_profile = AgentProfile(name="fast", from_file="fast-config.jsonc")
accurate_profile = AgentProfile(name="accurate", from_file="accurate-config.jsonc")

# Configure task defaults
task_defaults = (
    Builders.TaskDefaults
    .with_max_steps(500)
    .build()
)

# Build comprehensive agent configuration
config = (
    Builders.AgentConfig
    .for_device(platform=DevicePlatform.ANDROID, device_id="emulator-5554")
    .add_profiles([fast_profile, accurate_profile])
    .with_default_profile(fast_profile)
    .with_adb_server(host="localhost", port=5037)
    .with_default_task_config(task_defaults)
    .build()
)

agent = Agent(config=config)

Task Request Builder

Create detailed task configurations:

Basic Usage

task = (
    agent.new_task("Open settings and check notifications")
    .with_name("check_notifications")
    .build()
)

result = await agent.run_task(request=task)

Available Methods

Set a descriptive name for logging
task = agent.new_task(goal).with_name("my_task").build()
Limit the number of actions
task = agent.new_task(goal).with_max_steps(300).build()
Specify Pydantic model for output
task = (
    agent.new_task(goal)
    .with_output_format(MyModel)
    .build()
)
Describe expected output format
task = (
    agent.new_task(goal)
    .with_output_description("A comma-separated list")
    .build()
)
Use a specific agent profile
task = (
    agent.new_task(goal)
    .using_profile("accurate")
    .build()
)
Enable execution tracing
from pathlib import Path

task = (
    agent.new_task(goal)
    .with_trace_recording(enabled=True, path=Path("/tmp/traces"))
    .build()
)
Save final LLM output to file
task = (
    agent.new_task(goal)
    .with_llm_output_saving(path="/tmp/output.json")
    .build()
)
Save agent reasoning to file
task = (
    agent.new_task(goal)
    .with_thoughts_output_saving(path="/tmp/thoughts.txt")
    .build()
)

Complete Example

from pathlib import Path
from pydantic import BaseModel, Field

class EmailSummary(BaseModel):
    total: int = Field(..., description="Total number of emails")
    unread: int = Field(..., description="Number of unread emails")

task = (
    agent.new_task("Open Gmail and analyze my inbox")
    .with_name("gmail_analysis")
    .with_max_steps(400)
    .with_output_format(EmailSummary)
    .using_profile("accurate")
    .with_trace_recording(enabled=True, path=Path("/tmp/gmail-trace"))
    .with_llm_output_saving(path="/tmp/gmail-output.json")
    .with_thoughts_output_saving(path="/tmp/gmail-thoughts.txt")
    .build()
)

result = await agent.run_task(request=task)

Task Defaults Builder

Set defaults that apply to all tasks:
from minitap.mobile_use.sdk.builders import Builders

# Configure defaults
defaults = (
    Builders.TaskDefaults
    .with_max_steps(500)
    .with_trace_recording(enabled=True)
    .build()
)

# Apply to agent
config = (
    Builders.AgentConfig
    .with_default_task_config(defaults)
    .build()
)

agent = Agent(config=config)

# All tasks will inherit these defaults
await agent.run_task(goal="Any task here")

Method Chaining

Builders use method chaining for fluent configuration:
# Each method returns the builder instance
result = (
    agent.new_task("My goal")
    .with_name("task_1")          # Returns TaskRequestBuilder
    .with_max_steps(300)          # Returns TaskRequestBuilder
    .with_trace_recording(True)   # Returns TaskRequestBuilder
    .build()                      # Returns TaskRequest
)
Use parentheses and line breaks for readability when chaining many methods.

Type Safety

Builders provide compile-time type checking:
from pydantic import BaseModel

class MyOutput(BaseModel):
    value: str

# Type-safe: MyOutput or None
task = agent.new_task(goal).with_output_format(MyOutput).build()
result: MyOutput | None = await agent.run_task(request=task)

# Can safely access fields
if result:
    print(result.value)  # IDE knows 'value' exists

Comparison: With vs Without Builders

Best Practices

Use builders for complex configs

Builders shine when you need multiple configuration options

Simple tasks can use direct calls

For basic tasks, agent.run_task(goal="...") is fine

Create reusable configurations

Build common configs once and reuse them

Leverage IDE autocomplete

Let your IDE suggest available builder methods

Next Steps

I