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
| Type | Examples | Managed Via |
|---|
| npm packages | axios, lodash, date-fns | package.json |
|---|
| Python packages | requests, httpx, pydantic | requirements.txt |
|---|
| External APIs | OpenWeatherMap, Google Maps, Stripe | Config + API keys |
|---|
| OpenClaw SDK | @openclaw/sdk, @openclaw/test | package.json |
|---|
| System tools | ffmpeg, imagemagick | Documented in README |
|---|
Choosing the right version range is crucial:
| Strategy | Syntax | When to Use |
|---|
| Exact | 1.2.3 | Maximum stability, no auto-updates |
|---|
| Patch | ~1.2.3 | Allow bug fixes (1.2.x) |
|---|
| Minor | ^1.2.3 | Allow features (1.x.x) — recommended |
|---|
| Latest | * or latest | Never 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
- Pin critical dependencies to exact versions.
- Audit regularly for security vulnerabilities.
- Never hardcode API keys — always use the config system.
- Implement retry logic for all external API calls.
- Add fallback providers for critical functionality.
- Document external requirements (API keys, system tools) in README.
- Test with mocked dependencies — don't rely on live APIs in tests.
- Keep dependencies minimal — fewer packages means fewer attack surfaces.
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
- Check the key is set on the production machine:
openclaw skills config my-skill --list. - Some API keys are IP-restricted — check provider settings.
- Check for rate limits being hit in production.
Next Steps
- Write effective skill prompts: Using Prompts Inside Skills: Tips and Techniques.
- Build complex workflows: Multi-Step Skills: Orchestrating Complex Actions.
- Publish your skill: Publishing Your Skill to the Community Skill Registry.
Related Articles
- Skill File Structure: Organizing an OpenClaw Skill — Understand the standard file and folder structure for well-organized, maintainable OpenClaw skills.
- Using Tools in Prompts with OpenClaw (Web Search, APIs, etc.) — Enable your OpenClaw agent to use external tools like web search and APIs directly from prompts.
- Deploying a Custom OpenClaw Skill: Best Practices — Learn deployment strategies and best practices for shipping reliable OpenClaw skills to production.
- Auditing OpenClaw Skills for Security and Privacy — Review and audit third-party OpenClaw skills to ensure they meet your security and privacy standards.
- Finding and Installing OpenClaw Skills from ClawHub — Browse, evaluate, and install community-built skills from the ClawHub skill registry.