Handling Secrets
Secrets let you store sensitive information like API keys securely.
Defining Secrets
In your manifest, declare what secrets your agent needs:
json
{
"developerSecrets": {
"API_KEY": {
"description": "Your API key from example.com",
"required": true
},
"WEBHOOK_SECRET": {
"description": "Optional webhook signing secret",
"required": false
}
}
}Accessing Secrets
In your handler, use context.secrets:
js
async function handler(input, context) {
const apiKey = context.secrets.API_KEY;
if (!apiKey) {
return { error: true, message: 'API key not configured' };
}
// Use the secret
const response = await context.fetch('https://api.example.com/data', {
headers: {
'Authorization': `Bearer ${apiKey}`,
},
});
// ...
}Security
Encryption at Rest
Secrets are encrypted using AES-256-GCM before storage. Even if the database is compromised, secrets remain protected.
Never Log Secrets
Don't log or return secrets in responses:
js
// BAD - exposes secret
console.log('Using key:', context.secrets.API_KEY);
return { apiKey: context.secrets.API_KEY };
// GOOD - secret stays private
console.log('Making authenticated request...');Sandbox Isolation
Your agent code runs in an isolated sandbox. It cannot:
- Access the filesystem
- Make network requests without
context.fetch() - Access other agents' secrets
For Agent Developers vs Users
Developer Secrets
Defined in developerSecrets - you (the agent author) provide these:
json
{
"developerSecrets": {
"WEATHER_API_KEY": {
"description": "API key for weather service",
"required": true
}
}
}These are secrets YOU configure when publishing your agent.
OAuth vs Secrets
For services with OAuth:
- Use
oauthconfig in manifest - PIE handles tokens automatically
- Use
context.oauth.fetch()
For services with API keys:
- Use
developerSecretsin manifest - Store the API key as a secret
- Use
context.fetch()with the key
Example: Weather Tool
Manifest:
json
{
"trigger": "auto",
"developerSecrets": {
"WEATHER_API_KEY": {
"description": "API key from weatherapi.com",
"required": true
}
},
"tool": {
"name": "get_weather",
"description": "Get weather for a city",
"parameters": { ... }
}
}Code:
js
async function handler(input, context) {
const apiKey = context.secrets.WEATHER_API_KEY;
if (!apiKey) {
return {
error: true,
message: 'Weather API key not configured'
};
}
const response = await context.fetch(
`https://api.weatherapi.com/v1/current.json?key=${apiKey}&q=${input.city}`
);
// ...
}Best Practices
- Check for missing secrets - Don't assume secrets exist
- Never expose secrets - Don't log, return, or display them
- Use descriptive names -
WEATHER_API_KEYnotKEY1 - Document requirements - Explain what each secret is for
- Mark required correctly - Only mark as required if truly needed