Skill Dependencies: Managing Libraries and APIs

Clawpedia · For Humans

Handle external libraries, API keys, and third-party dependencies in your OpenClaw skills effectively.

Overview

Most OpenClaw skills depend on external libraries and APIs. Managing these dependencies correctly is essential for reliability, security, and reproducibility. This guide covers dependency declaration, version pinning, API key management, and strategies for handling third-party service outages.

Types of Dependencies

TypeExamplesManaged Via
npm packagesaxios, lodash, date-fnspackage.json
Python packagesrequests, httpx, pydanticrequirements.txt
External APIsOpenWeatherMap, Google Maps, StripeConfig + API keys
OpenClaw SDK@openclaw/sdk, @openclaw/testpackage.json

Declaring Dependencies

TypeScript Skills


{
  "name": "@openclaw-skills/weather",
  "version": "1.0.0",
  "dependencies": {
    "@openclaw/sdk": "^1.5.0",
    "date-fns": "^3.0.0"
  },
  "devDependencies": {
    "@openclaw/test": "^1.5.0",
    "typescript": "^5.3.0"
  }
}

Python Skills


# requirements.txt
openclaw-sdk>=1.5.0
httpx>=0.25.0,<1.0.0
pydantic>=2.0.0

Version Pinning Strategies

System toolsffmpeg, imagemagickDocumented in README

Choosing the right version range is crucial:

StrategySyntaxWhen to Use
Exact1.2.3Maximum stability, no auto-updates
Patch~1.2.3Allow bug fixes (1.2.x)
Minor^1.2.3Allow features (1.x.x) — recommended

{
  "dependencies": {
    "@openclaw/sdk": "^1.5.0",    // Minor: safe, gets features
    "axios": "~1.6.0",             // Patch: only bug fixes
    "crypto-js": "4.2.0"           // Exact: security-critical
  }
}
Latest* or latestNever in production

Best Practice: Use ^ (caret/minor) for most packages. Use exact versions for security-critical libraries.

The Lockfile

OpenClaw generates a lockfile that pins exact resolved versions:


# Generate/update the lockfile
openclaw skills lock my-skill

# Install from lockfile (exact versions)
openclaw skills install my-skill --frozen

Always commit the lockfile to version control. It ensures identical installations everywhere.

API Key Management

External APIs require authentication. Never hardcode keys:

Declaring API Requirements


# manifest.yaml
config:
  weather_api_key:
    type: string
    required: true
    secret: true                  # Masked in output, encrypted at rest
    description: "OpenWeatherMap API key"
    docs: "https://openweathermap.org/api"
  maps_api_key:
    type: string
    required: false
    secret: true
    description: "Google Maps API key (optional, for location search)"

Accessing Keys in Code


export default class WeatherSkill extends Skill {
  async execute(context: SkillContext): Promise<SkillResult> {
    const apiKey = this.config.get("weather_api_key");
    
    // Validate the key is set
    if (!apiKey) {
      return this.error(
        "Weather API key not configured. Run: " +
        "openclaw skills config weather --set weather_api_key YOUR_KEY"
      );
    }

    const response = await fetch(
      `https://api.openweathermap.org/data/2.5/weather?q=Berlin&appid=${apiKey}`
    );
    // ...
  }
}

Key Rotation

Support key rotation without downtime:


config:
  api_key:
    type: string
    secret: true
  api_key_fallback:
    type: string
    secret: true
    required: false
    description: "Fallback API key if primary is rate-limited"

async callAPI(endpoint: string): Promise<Response> {
  const primaryKey = this.config.get("api_key");
  const fallbackKey = this.config.get("api_key_fallback");

  let response = await fetch(endpoint, {
    headers: { Authorization: `Bearer ${primaryKey}` }
  });

  if (response.status === 429 && fallbackKey) {
    this.log.warn("Primary key rate-limited, using fallback");
    response = await fetch(endpoint, {
      headers: { Authorization: `Bearer ${fallbackKey}` }
    });
  }

  return response;
}

Handling API Outages

Retry with Exponential Backoff


async fetchWithRetry(url: string, maxRetries = 3): Promise<Response> {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      const response = await fetch(url);
      if (response.ok || response.status < 500) return response;
      
      // Server error — retry
      if (attempt < maxRetries) {
        const delay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s
        this.log.warn(`Retry ${attempt + 1}/${maxRetries} after ${delay}ms`);
        await new Promise(resolve => setTimeout(resolve, delay));
      }
    } catch (err) {
      if (attempt === maxRetries) throw err;
      const delay = Math.pow(2, attempt) * 1000;
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
  throw new Error("Max retries exceeded");
}

Circuit Breaker Pattern

Prevent cascading failures when an API is down:


import { CircuitBreaker } from "@openclaw/sdk";

export default class ResilientSkill extends Skill {
  private breaker = new CircuitBreaker({
    failureThreshold: 5,        // Open after 5 failures
    resetTimeout: 60000,        // Try again after 60 seconds
  });

  async execute(context: SkillContext): Promise<SkillResult> {
    try {
      const result = await this.breaker.execute(() =>
        fetch("https://api.example.com/data")
      );
      return this.success(await result.json());
    } catch (err) {
      if (err.message === "Circuit open") {
        return this.error("Service is temporarily unavailable. Please try again in a minute.");
      }
      return this.error("Request failed. Please try again.");
    }
  }
}

Fallback Providers

Configure multiple providers for critical skills:


config:
  primary_provider:
    type: string
    default: "openweathermap"
  fallback_provider:
    type: string
    default: "weatherapi"

Dependency Auditing


# Check for known vulnerabilities
openclaw skills audit my-skill

# Output:
# ✅ @openclaw/sdk@1.5.0 — no issues
# ✅ date-fns@3.1.0 — no issues
# ⚠️ axios@1.5.0 — 1 moderate vulnerability
#    CVE-2023-XXXX: SSRF in proxy configuration
#    Fix: upgrade to axios@1.6.0
#
# 1 vulnerability found. Run: openclaw skills audit my-skill --fix

# Auto-fix vulnerabilities
openclaw skills audit my-skill --fix

Keeping Dependencies Updated


# Check for outdated packages
openclaw skills outdated my-skill

# Output:
# Package         Current  Latest  Type
# date-fns        3.0.0    3.3.0   dependencies
# typescript      5.3.0    5.4.0   devDependencies

# Update all dependencies
openclaw skills update-deps my-skill

# Update a specific package
openclaw skills update-deps my-skill --package date-fns

Best Practices

Troubleshooting

"Module Not Found" After Installation

Dependencies may not have been installed:


openclaw skills install my-skill --reinstall-deps

Version Conflict Between Skills

Two skills need different versions of the same package:


# Check for conflicts
openclaw skills check-conflicts

# Force resolution (may cause issues)
openclaw skills install --force-resolve

API Key Works Locally but Fails in Production

Next Steps

Related Articles