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

# Credential Management

> Extend Mobilerun with secure credential management

## Overview

Secure storage for passwords, API keys, and tokens.

* Stored in YAML files or in-memory dicts
* Never logged or exposed
* Auto-injected as `type_secret` action
* Simple string or dict format

## Quick Start

### Method 1: In-Memory (Recommended for SDK)

```python theme={null}
import asyncio
from mobilerun import MobileAgent, MobileConfig

async def main():
    # Define credentials directly
    credentials = {
        "MY_PASSWORD": "secret123",
        "API_KEY": "sk-1234567890"
    }

    config = MobileConfig()

    agent = MobileAgent(
        goal="Login to my app",
        config=config,
        credentials=credentials  # Pass directly
    )

    result = await agent.run()
    print(result.success)

asyncio.run(main())
```

### Method 2: YAML File

1. **Create credentials file:**

```yaml theme={null}
# credentials.yaml
secrets:
  # Dict format (recommended)
  MY_PASSWORD:
    value: "your_password_here"
    enabled: true

  GMAIL_PASSWORD:
    value: "gmail_pass_123"
    enabled: true

  # Simple string format (auto-enabled)
  API_KEY: "sk-1234567890abcdef"

  # Disabled secret
  OLD_PASSWORD:
    value: "old_pass"
    enabled: false  # Not loaded
```

2. **Enable in config.yaml:**

```yaml theme={null}
# config.yaml
credentials:
  enabled: true
  file_path: config/credentials.yaml
```

3. **Use in code:**

```python theme={null}
from mobilerun import MobileAgent, MobileConfig

# Config loads credentials from file
config = MobileConfig.from_yaml("config.yaml")

agent = MobileAgent(
    goal="Login to Gmail",
    config=config  # Credentials loaded automatically
)
```

***

## How Agents Use Credentials

When credentials are provided, the `type_secret` action is **automatically available**:

### Executor/Manager Mode

```json theme={null}
{
  "action": "type_secret",
  "secret_id": "MY_PASSWORD",
  "index": 5
}
```

### FastAgent Mode

```xml theme={null}
<function_calls>
<invoke name="type_secret">
<parameter name="secret_id">MY_PASSWORD</parameter>
<parameter name="index">5</parameter>
</invoke>
</function_calls>
```

The agent never sees the actual value - only the secret ID.

***

## Example: Login Automation

```python theme={null}
import asyncio
from mobilerun import MobileAgent, MobileConfig

async def main():
    credentials = {
        "EMAIL_USER": "user@example.com",
        "EMAIL_PASS": "secret_password"
    }

    config = MobileConfig()

    agent = MobileAgent(
        goal="Open Gmail and login with my credentials",
        config=config,
        credentials=credentials
    )

    result = await agent.run()
    print(f"Success: {result.success}")

asyncio.run(main())
```

**What the agent does:**

1. Opens Gmail: `open_app("Gmail")`
2. Clicks email field: `click(index=3)`
3. Types email: `type("user@example.com", index=3)`
4. Clicks password field: `click(index=5)`
5. Types password securely: `type_secret("EMAIL_PASS", index=5)`
6. Clicks login: `click(index=7)`

## Credentials vs Variables

| Feature      | Credentials            | Variables          |
| ------------ | ---------------------- | ------------------ |
| **Purpose**  | Passwords, API keys    | Non-sensitive data |
| **Storage**  | YAML or in-memory      | In-memory only     |
| **Logging**  | Never logged           | May appear in logs |
| **Access**   | Via `type_secret` tool | In shared state    |
| **Security** | Protected              | No protection      |

**Example: Using Variables**

```python theme={null}
variables = {
    "target_email": "john@example.com",
    "subject_line": "Monthly Report"
}

agent = MobileAgent(
    goal="Compose email to {{target_email}}",
    config=config,
    variables=variables  # Non-sensitive
)
```

***

## Troubleshooting

### Error: Credential manager not initialized

**Solution:**

```yaml theme={null}
# config.yaml
credentials:
  enabled: true  # Must be true
  file_path: config/credentials.yaml
```

Or:

```python theme={null}
agent = MobileAgent(..., credentials={"PASSWORD": "secret"})
```

### Error: Secret 'X' not found

**Check available secrets:**

```python theme={null}
from mobilerun.credential_manager import FileCredentialManager

cm = FileCredentialManager("config/credentials.yaml")
print(await cm.get_keys())
```

**Verify in YAML:**

```yaml theme={null}
secrets:
  X:
    value: "your_value"
    enabled: true  # Must be true
```

***

## Custom Credential Managers

Extend `CredentialManager` for custom secret storage:

```python theme={null}
from mobilerun.credential_manager import CredentialManager

class MyCredentialManager(CredentialManager):
    def __init__(self, api_key):
        self.api_key = api_key

    async def resolve_key(self, key: str) -> str:
        # Implement your own credential retrieval logic
        return await fetch_from_service(key, self.api_key)

    async def get_keys(self) -> list[str]:
        # Return list of available credential keys
        return await fetch_available_keys(self.api_key)

# Use it
credentials = MyCredentialManager(api_key="...")
agent = MobileAgent(goal="Login", config=config, credentials=credentials)
```

Implement any custom secret storage backend.

***

## Related

See [Configuration Guide](/framework/sdk/configuration) for credential setup.

See [Custom Variables](/framework/features/custom-variables) for non-sensitive data.
