Skip to content

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 oauth config in manifest
  • PIE handles tokens automatically
  • Use context.oauth.fetch()

For services with API keys:

  • Use developerSecrets in 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

  1. Check for missing secrets - Don't assume secrets exist
  2. Never expose secrets - Don't log, return, or display them
  3. Use descriptive names - WEATHER_API_KEY not KEY1
  4. Document requirements - Explain what each secret is for
  5. Mark required correctly - Only mark as required if truly needed

Built with VitePress