OpenClaw plugin that dynamically filters skills using Elasticsearch semantic search. Reduces token usage by ~90% by only injecting relevant skills into the system prompt.
User message → before_prompt_build hook → ES semantic search → Top-K skills → system prompt
Instead of loading all 95+ skills into every conversation (costing ~5000 tokens), this plugin searches for the most relevant skills and only injects those. The LLM sees fewer skills, makes better decisions, and costs less.
- Plugin (
index.ts): Registers abefore_prompt_buildhook that intercepts each message, searches ES for relevant skills, and overrides the system prompt with only the matched skills - Skill (
skills/es-vector-skill/): ES CRUD scripts for managing the skill index, included automatically when the plugin is installed
- Elasticsearch cluster with the
.jina-embeddings-v5-text-smallinference endpoint (available on Elastic Cloud) - Python 3 +
elasticsearch+pyyamlpackages (for index management scripts)
pip3 install elasticsearch pyyaml# 1. Clone this repo
git clone https://github.com/LiJieY/es-skill-router.git
cd es-skill-router
# 2. Install the plugin
openclaw plugins install -l .
# 3. Configure (add to ~/.openclaw/openclaw.json → plugins.entries)Add to ~/.openclaw/openclaw.json:
{
"plugins": {
"entries": {
"es-skill-router": {
"enabled": true,
"config": {
"esUrl": "https://your-cluster.es.cloud.com:9243",
"esUser": "elastic",
"esPassword": "your-password",
"index": "openclaw-skills",
"topK": 5,
"minScore": 0.5
}
}
}
}
}Or use environment variables:
export ES_URL="https://your-cluster:9243"
export ES_USER="elastic"
export ES_PASSWORD="your-password"openclaw gateway restartAfter installation, index all installed skills into Elasticsearch:
# Set connection
export ES_URL="https://your-cluster:9243"
export ES_USER="elastic"
export ES_PASSWORD="your-password"
# Index all skills (auto-discovers from OpenClaw skill directories)
python3 skills/es-vector-skill/scripts/index_skills.py --index openclaw-skills --recreateOutput:
Found 95 skills
Created index: openclaw-skills
{"success": true, "indexed": 95, "errors": 0}
Send any message to your agent. Check the gateway logs:
grep "es-skill-router\|ready.*index" /tmp/openclaw/openclaw-$(date +%Y-%m-%d).logYou should see:
ready: index=openclaw-skills topK=5 minScore=0.5
"your message..." → [skill1, skill2, skill3, skill4, skill5]
| Option | Default | Description |
|---|---|---|
esUrl |
ES_URL env |
Elasticsearch URL |
esUser |
ES_USER env |
ES username |
esPassword |
ES_PASSWORD env |
ES password |
esApiKey |
ES_API_KEY env |
ES API key (alternative to user/pass) |
index |
openclaw-skills |
ES index name for skill vectors |
topK |
5 |
Number of skills to keep |
minScore |
0.5 |
Minimum relevance score |
enabled |
true |
Enable/disable the router |
python3 skills/es-vector-skill/scripts/index_skills.py --index openclaw-skillsNew skills are added incrementally (existing ones are updated).
| COS Vectors (Hook) | ES Skill Router (Plugin) | |
|---|---|---|
| Hook type | message:received (async) |
before_prompt_build (sync) |
| Timing | 1 message lag | Same message |
| Embedding | External API (OpenAI/Ollama) | ES built-in (jina v5) |
| Token savings | ~92% | ~92% |
| Setup | Hook + scripts + COS bucket | One plugin install |
MIT