Files

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.