Documentation

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.md to 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:

ScopeDescriptionUse Case
models:readList available modelsDiscovery agents
models:useMake LLM API callsAll agents
services:readList available servicesDiscovery agents
services:useUse non-LLM services (Stripe, email, etc.)Full-stack agents
billing:readCheck balance and usageMonitoring agents
billing:writeAdd credits, update paymentAdmin agents
agents:createCreate child agentsParent 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

ErrorCauseSolution
401 UnauthorizedInvalid or missing API keyCheck key format (starts with sk-)
403 ForbiddenKey lacks required scopeRequest key with correct permissions
429 Too Many RequestsRate limit exceededImplement exponential backoff
402 Payment RequiredInsufficient creditsAdd 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