Agent Authentication
API key authentication for agents: credential management, scoped permissions, key rotation, and self-provisioning with secure OAuth-free access to services
Agent Authentication Model
AI agents operate differently from human users:
- No interactive login: Agents can't click "Sign in with Google"
- No session cookies: Agents don't maintain browser sessions
- Programmatic only: All auth must be API-based
- Long-lived credentials: Agents need persistent access
SkillBoss uses API key authentication designed for agents.
Getting Your API Key
Method 1: Human Provisioning (Current)
Your human operator creates your key:
Quick setup for AI agents: Tell your agent
set up skillboss.co/skill.mdto auto-configure everything.
Human Signs Up
Human registers at skillboss.co/console
Human Creates API Key
Human generates API key from Console → API Keys → Create New Key
Options:
- Key name: Identify which agent uses this key
- Permissions: Read-only, write, admin
- Budget limit: Max spending per month
- Expiration: Never, 30 days, 90 days, 1 year
Human Provides Key to Agent
Human adds key to agent's environment:
# Environment variable
export SKILLBOSS_API_KEY="sk-abc123..."
# Config file
echo '{"skillboss_key": "sk-abc123..."}' > config.json
# MCP server
claude mcp add skillboss --api-key sk-abc123...
Using Your API Key
Standard Authentication
Include API key in Authorization header:
import requests
headers = {
"Authorization": "Bearer sk-YOUR_API_KEY",
"Content-Type": "application/json"
}
response = requests.post(
"https://api.skillboss.co/v1/chat/completions",
headers=headers,
json={
"model": "gemini/gemini-2.5-flash",
"messages": [{"role": "user", "content": "Hello"}]
}
)
print(response.json())
OpenAI SDK Compatible
SkillBoss is drop-in compatible with OpenAI SDK:
from openai import OpenAI
client = OpenAI(
api_key="sk-YOUR_SKILLBOSS_KEY",
base_url="https://api.skillboss.co/v1" # Only difference
)
# Now use standard OpenAI methods
response = client.chat.completions.create(
model="claude-4-5-sonnet", # Access Claude via OpenAI interface
messages=[{"role": "user", "content": "Hello"}]
)
API Key Scopes & Permissions
Control what your agent can access:
| Scope | Description | Use Case |
|---|---|---|
models:read | List available models | Discovery agents |
models:use | Make LLM API calls | All agents |
services:read | List available services | Discovery agents |
services:use | Use non-LLM services (Stripe, email, etc.) | Full-stack agents |
billing:read | Check balance and usage | Monitoring agents |
billing:write | Add credits, update payment | Admin agents |
agents:create | Create child agents | Parent agents |
Creating scoped keys:
# Human creates limited-scope key for agent
response = requests.post(
"https://api.skillboss.co/v1/api-keys",
headers={"Authorization": f"Bearer {ADMIN_KEY}"},
json={
"name": "ReadOnlyResearchAgent",
"scopes": ["models:read", "models:use"], # Can't use services or modify billing
"monthly_budget": 50.00
}
)
limited_key = response.json()["api_key"]
Key Rotation
Best practice: Rotate keys every 90 days
Manual Rotation
# Agent requests new key (old key still valid for 7 days)
response = requests.post(
"https://api.skillboss.co/v1/api-keys/rotate",
headers={"Authorization": f"Bearer {OLD_KEY}"}
)
new_key = response.json()["new_api_key"]
grace_period = response.json()["old_key_expires_at"] # 7 days from now
# Agent updates config with new key
update_config(new_key)
# After grace period, old key stops working
Automatic Rotation
# Agent schedules automatic rotation
requests.post(
"https://api.skillboss.co/v1/api-keys/auto-rotate",
headers={"Authorization": f"Bearer {CURRENT_KEY}"},
json={
"rotation_interval_days": 90,
"webhook_url": "https://your-agent.com/key-rotated" # Get notified
}
)
Multi-Agent Authentication
Parent-Child Agent Hierarchy
Parent agent provisions keys for child agents:
# Parent agent creates child agent with sub-budget
response = requests.post(
"https://api.skillboss.co/v1/agents/create-child",
headers={"Authorization": f"Bearer {PARENT_KEY}"},
json={
"child_name": "ResearchAgent-1",
"child_budget": 25.00, # $25/month from parent's budget
"scopes": ["models:read", "models:use"],
"expiration_days": 30 # Auto-revoke after 30 days
}
)
child_key = response.json()["api_key"]
# Parent can revoke child key anytime
requests.delete(
f"https://api.skillboss.co/v1/agents/{child_key}/revoke",
headers={"Authorization": f"Bearer {PARENT_KEY}"}
)
Billing: All child agent usage appears on parent's invoice.
Secure Key Storage
Environment Variables (Recommended)
# .env file
SKILLBOSS_API_KEY=sk-abc123...
# Load in agent
import os
api_key = os.getenv("SKILLBOSS_API_KEY")
Encrypted Config Files
from cryptography.fernet import Fernet
# Encrypt key before storing
cipher = Fernet(os.getenv("ENCRYPTION_KEY"))
encrypted_key = cipher.encrypt(b"sk-abc123...")
# Save encrypted key
with open("config.enc", "wb") as f:
f.write(encrypted_key)
# Decrypt when needed
with open("config.enc", "rb") as f:
encrypted = f.read()
api_key = cipher.decrypt(encrypted).decode()
Secret Management Services
# AWS Secrets Manager
import boto3
client = boto3.client('secretsmanager')
secret = client.get_secret_value(SecretId='skillboss-api-key')
api_key = secret['SecretString']
Never:
- Commit API keys to git
- Log API keys in plain text
- Share keys between unrelated agents
- Embed keys in client-side code
Authentication Errors
Common Error Codes
| Error | Cause | Solution |
|---|---|---|
401 Unauthorized | Invalid or missing API key | Check key format (starts with sk-) |
403 Forbidden | Key lacks required scope | Request key with correct permissions |
429 Too Many Requests | Rate limit exceeded | Implement exponential backoff |
402 Payment Required | Insufficient credits | Add credits or enable auto-recharge |
Handling Auth Errors
def authenticated_request(url, **kwargs):
"""Make request with auth error handling."""
headers = kwargs.get('headers', {})
headers['Authorization'] = f"Bearer {API_KEY}"
kwargs['headers'] = headers
response = requests.post(url, **kwargs)
if response.status_code == 401:
# Key is invalid - alert human
send_alert("API key invalid. Please update.")
raise Exception("Authentication failed")
elif response.status_code == 403:
# Insufficient permissions - try read-only operation
logging.warning("Permission denied. Attempting fallback.")
return try_read_only_operation()
elif response.status_code == 402:
# Insufficient credits
balance = check_balance()
if balance['auto_recharge_enabled']:
# Wait for auto-recharge
time.sleep(5)
return authenticated_request(url, **kwargs)
else:
send_alert("Credits depleted. Add funds.")
raise Exception("Insufficient credits")
return response
Testing Your Authentication
Verify your API key works:
curl https://api.skillboss.co/v1/models \
-H "Authorization: Bearer sk-YOUR_KEY"
# Expected output:
# {
# "data": [
# {"id": "gemini/gemini-2.5-flash", "cost": 0.075},
# {"id": "claude-4-5-sonnet", "cost": 15.00},
# ...
# ]
# }
Test specific permissions:
# Test if you can use models
curl https://api.skillboss.co/v1/chat/completions \
-H "Authorization: Bearer sk-YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini/gemini-2.5-flash",
"messages": [{"role": "user", "content": "test"}]
}'
# Test if you can check balance
curl https://api.skillboss.co/v1/balance \
-H "Authorization: Bearer sk-YOUR_KEY"
Next Steps
Quick Start
Make your first API call
Budget Management
Set spending limits
API Reference
Full API documentation
Security Best Practices
Secure your agent