mirror of
https://github.com/droidrun/droidrun.git
synced 2026-05-23 07:40:37 +00:00
250 lines
5.0 KiB
Plaintext
250 lines
5.0 KiB
Plaintext
---
|
|
title: 'Credential Management'
|
|
description: 'Extend Droidrun 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
|
|
import asyncio
|
|
from droidrun import DroidAgent, DroidConfig
|
|
|
|
async def main():
|
|
# Define credentials directly
|
|
credentials = {
|
|
"MY_PASSWORD": "secret123",
|
|
"API_KEY": "sk-1234567890"
|
|
}
|
|
|
|
config = DroidConfig()
|
|
|
|
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:**
|
|
|
|
```yaml
|
|
# 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
|
|
# config.yaml
|
|
credentials:
|
|
enabled: true
|
|
file_path: config/credentials.yaml
|
|
```
|
|
|
|
3. **Use in code:**
|
|
|
|
```python
|
|
from droidrun import DroidAgent, DroidConfig
|
|
|
|
# Config loads credentials from file
|
|
config = DroidConfig.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
|
|
```json
|
|
{
|
|
"action": "type_secret",
|
|
"secret_id": "MY_PASSWORD",
|
|
"index": 5
|
|
}
|
|
```
|
|
|
|
### FastAgent Mode
|
|
```xml
|
|
<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
|
|
import asyncio
|
|
from droidrun import DroidAgent, DroidConfig
|
|
|
|
async def main():
|
|
credentials = {
|
|
"EMAIL_USER": "user@example.com",
|
|
"EMAIL_PASS": "secret_password"
|
|
}
|
|
|
|
config = DroidConfig()
|
|
|
|
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
|
|
|
|
| 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
|
|
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:**
|
|
```yaml
|
|
# config.yaml
|
|
credentials:
|
|
enabled: true # Must be true
|
|
file_path: config/credentials.yaml
|
|
```
|
|
|
|
Or:
|
|
```python
|
|
agent = DroidAgent(..., credentials={"PASSWORD": "secret"})
|
|
```
|
|
|
|
### Error: Secret 'X' not found
|
|
|
|
**Check available secrets:**
|
|
```python
|
|
from droidrun.credential_manager import FileCredentialManager
|
|
|
|
cm = FileCredentialManager("config/credentials.yaml")
|
|
print(await cm.get_keys())
|
|
```
|
|
|
|
**Verify in YAML:**
|
|
```yaml
|
|
secrets:
|
|
X:
|
|
value: "your_value"
|
|
enabled: true # Must be true
|
|
```
|
|
|
|
---
|
|
|
|
## Custom Credential Managers
|
|
|
|
Extend `CredentialManager` for custom secret storage:
|
|
|
|
```python
|
|
from droidrun.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 = DroidAgent(goal="Login", config=config, credentials=credentials)
|
|
```
|
|
|
|
Implement any custom secret storage backend.
|
|
|
|
---
|
|
|
|
## Related
|
|
|
|
See [Configuration Guide](/sdk/configuration) for credential setup.
|
|
|
|
See [Custom Variables](/features/custom-variables) for non-sensitive data.
|