Skip to main content

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 tool
  • Simple string or dict format

Quick Start

import asyncio
from droidrun import DroidAgent
from droidrun.config_manager import DroidrunConfig

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

    config = DroidrunConfig()

    agent = DroidAgent(
        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:
# 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
  1. Enable in config.yaml:
# config.yaml
credentials:
  enabled: true
  file_path: credentials.yaml
  1. Use in code:
from droidrun import DroidAgent
from droidrun.config_manager import DroidrunConfig

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

agent = DroidAgent(
    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

{
  "action": "type_secret",
  "secret_id": "MY_PASSWORD",
  "index": 5
}

CodeAct Mode

type_secret("MY_PASSWORD", index=5)
The agent never sees the actual value - only the secret ID.

Example: Login Automation

import asyncio
from droidrun import DroidAgent
from droidrun.config_manager import DroidrunConfig

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

    config = DroidrunConfig()

    agent = DroidAgent(
        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

FeatureCredentialsVariables
PurposePasswords, API keysNon-sensitive data
StorageYAML or in-memoryIn-memory only
LoggingNever loggedMay appear in logs
AccessVia type_secret toolIn shared state
SecurityProtectedNo protection
Example: Using Variables
variables = {
    "target_email": "john@example.com",
    "subject_line": "Monthly Report"
}

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

Troubleshooting

Error: Credential manager not initialized

Solution:
# config.yaml
credentials:
  enabled: true  # Must be true
  file_path: credentials.yaml
Or:
agent = DroidAgent(..., credentials={"PASSWORD": "secret"})

Error: Secret ‘X’ not found

Check available secrets:
from droidrun.credential_manager import CredentialManager

cm = CredentialManager(credentials_path="credentials.yaml")
print(cm.list_available_secrets())
Verify in YAML:
secrets:
  X:
    value: "your_value"
    enabled: true  # Must be true

See Configuration Guide for credential setup. See Custom Variables for non-sensitive data.
I