How to Migrate OpenClaw Plugins from extension-api to plugin-sdk
I ran openclaw plugins install my-tool and everything seemed fine. But when I tried to start OpenClaw, it crashed immediately with a cryptic error about missing modules.
The culprit? A breaking change in OpenClaw’s plugin SDK import paths that has no compatibility layer.
The Error That Stopped Everything
After updating to the latest OpenClaw version, my plugins started failing with:
Error: Cannot find module 'openclaw/extension-api' at Function.Module._resolveFilename (node:internal/modules/cjs/loader:1077:15) at Module.require (node:internal/modules/cjs/loader:1225:19)This wasn’t a deprecation warning. This wasn’t a helpful migration message. My plugins were completely broken.
What Actually Changed
OpenClaw migrated from openclaw/extension-api to openclaw/plugin-sdk/* as the import path for plugin development.
// Before (deprecated, will break)import { Tool } from 'openclaw/extension-api'
// After (new SDK path)import { Tool } from 'openclaw/plugin-sdk'This isn’t just a rename. It’s a fundamental restructuring with no backwards compatibility and no migration tooling. Plugins importing from the old path will hard-fail on launch, not gracefully degrade.
Why This Matters
I spent 30 minutes thinking I had corrupted my installation. The error message doesn’t tell you what changed. It just fails.
┌─────────────────────┬──────────────────────┬─────────────────────┐│ Impact Area │ Before │ After │├─────────────────────┼──────────────────────┼─────────────────────┤│ Plugin loading │ Graceful import │ Hard-fail on launch ││ Error message │ May show deprecation │ Immediate crash ││ Fix complexity │ Simple rename │ Requires code change││ Third-party plugins │ Work normally │ Broken until updated│└─────────────────────┴──────────────────────┴─────────────────────┘Discovery Process: How I Found the Problem
First, I checked if it was a cache issue:
openclaw doctor --fixrm -rf ~/.openclaw/plugins/*Still broken. Then I tried reinstalling:
openclaw plugins install my-toolThe install succeeded, but the error persisted. That’s when I realized: the plugin code itself was using the old import path.
I checked the plugin source:
grep -r "extension-api" ~/.openclaw/plugins/my-tool/And there it was. Multiple files importing from openclaw/extension-api.
The Three Migration Paths
Path 1: Check for Plugin Updates (Easiest)
The plugin maintainer may have already fixed this:
# Check if there's a newer versionnpm view my-tool versions --json
# Check the repository for migration branchesgh api repos/owner/my-tool/branches --jq '.[].name' | grep -i migrat
# Reinstall if updatedopenclaw plugins install my-toolThis worked for some of my plugins. The maintainers had already published updates.
Path 2: Pin OpenClaw Version (Workaround)
For plugins without updates, pinning to an older OpenClaw version works:
# Pin to the last working version
# Or use npx for one-off runsThis is a temporary fix, but it let me continue working while waiting for plugin updates.
Path 3: Fork and Fix (Most Control)
For private plugins or slow-to-update maintainers, I had to fix it myself:
# Find all affected importsgrep -rn "openclaw/extension-api" ./src
# Using sed to replace (backup first!)find ./src -name "*.ts" -exec sed -i.bak 's|openclaw/extension-api|openclaw/plugin-sdk|g' {} +
# Or manually update each fileBefore (broken):
import { Tool, Agent } from 'openclaw/extension-api'
export const myTool: Tool = { name: 'my-tool', description: 'A sample tool', execute: async (input) => { return { result: 'done' } }}After (working):
import { Tool, Agent } from 'openclaw/plugin-sdk'
export const myTool: Tool = { name: 'my-tool', description: 'A sample tool', execute: async (input) => { return { result: 'done' } }}Bonus Breaking Changes
While debugging, I discovered two more changes:
1. ClawHub is Now the Default Store
# Default: ClawHub first, then npmopenclaw plugins install my-tool
# Force npm sourceopenclaw plugins install my-tool --source npm
# Force ClawHub sourceopenclaw plugins install my-tool --source clawhub2. Private Registry Installs Require Explicit Flag
# Old way (may fail)openclaw plugins install my-private-plugin
# New way (explicit source)openclaw plugins install my-private-plugin --source npmThis caused issues with my company’s private plugin registry until I added the --source npm flag.
My Migration Checklist
After fixing all my plugins, I created this checklist for future reference:
□ List all installed plugins: openclaw plugins list□ Check each plugin repo for migration branch or updated version□ Update plugins from ClawHub or npm as available□ For private plugins, check imports for openclaw/extension-api□ Update imports to openclaw/plugin-sdk□ Test each plugin individually after update□ Use openclaw doctor --fix to clean up stale references□ Update private npm registry installs to use --source npm□ Document any plugins that needed manual updatesHow to Audit Your Plugins
Before updating OpenClaw, run this to identify at-risk plugins:
# List installed pluginsopenclaw plugins list
# Check plugin source for old importsfor plugin in $(openclaw plugins list --json | jq -r '.[].name'); do echo "Checking $plugin..." npm view "$plugin" repository.url 2>/dev/nulldone
# Or check locally installed pluginsgrep -r "openclaw/extension-api" ~/.openclaw/plugins/If you see any matches, don’t update OpenClaw until you’ve verified the plugins have been migrated.
What I Learned
- Breaking changes without migration tooling cost real time. I lost 2 hours to this across all my projects.
- Check the changelog before updating. This was documented, but I didn’t check.
- Pin versions in production.
package-lock.jsonor equivalent isn’t enough when tools update globally. - The error message didn’t help. A simple “This import path was migrated in version X.Y.Z” would have saved me time.
Reference Links
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments