openclaw - 💡(How to fix) Fix Feature Request: Skill-Driven Plugin Context Visibility (activates.plugins) [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#55071Fetched 2026-04-08 01:32:48
View on GitHub
Comments
0
Participants
1
Timeline
2
Reactions
0
Author
Participants
Timeline (top)
mentioned ×1subscribed ×1

Error Message

  • Graceful degradation: If an activated Plugin is not installed, the activation is silently ignored (no error)

Fix Action

Fix / Workaround

Current mitigation mechanisms and their limitations

Code Example

Gateway startup
Load ALL plugins globally
Register ALL Tools/Providers/Channels
User sends message → Start session
Snapshot ALL eligible Skills
Assemble system prompt with ALL Tool schemas + ALL matched Skill text
LLM inference + function calling

---

total = 195 + Σ (97 + len(name) + len(description) + len(location))  per skill

---

---
name: data-analyst
description: Query and analyze data from the big data platform
metadata:
  openclaw:
    requires:
      config: ["plugins.entries.bigdata-platform.enabled"]
    activates:
      plugins: ["bigdata-platform", "chart-generator"]
---

---

Only requires.configTraditional gate: Plugin not enabled = skip Skill. Tools still globally injected.
Only activates.pluginsNo gate, but Tools injected on-demand when Skill matches.
BothGate first (requires), then demand-load (activates). Recommended pattern.

---

User sends message
OpenClaw matches Skills based on description (existing behavior)
Collect all `activates.plugins` from matched Skills
Build Tool list = Core Tools + Tools from activated Plugins only
Assemble prompt with filtered Tool schemas + matched Skill text
LLM inference (leaner context, better accuracy)

---

Level 0: Skill descriptions in system prompt (~tens of tokens each, always present)
LLM determines relevance
Level 0.5: SKILL.md read by LLM (~hundreds of tokens, on-demand)
  Contains: capability index table + Plugin dependency declaration
Plugin Tools become visible
Level 1: Plugin docs read by LLM (~hundreds of tokens, on-demand)
  Contains: detailed Tool parameter docs, usage constraints
LLM constructs function call
Level 2: Tool execution (0 tokens — code layer)
  Contains: actual business logic (TypeScript/Python scripts)

---

---
name: data-analyst  
description: Query and analyze data from the big data platform
metadata:
  openclaw:
    requires:
      config: ["plugins.entries.bigdata-platform.enabled"]
    activates:
      plugins: ["bigdata-platform"]
---

# Data Analysis

## Available capabilities (provided by bigdata-platform plugin)

| Capability | Purpose | Details |
|-----------|---------|---------|
| bigdata_query | SQL queries | See {plugins.bigdata-platform}/docs/query.md |
| bigdata_table_info | Table schema | See {plugins.bigdata-platform}/docs/schema.md |
| bigdata_dashboard | Dashboard gen | See {plugins.bigdata-platform}/docs/dashboard.md |

## Workflow
1. Check table schema first
2. Write and execute SQL
3. Summarize results if > 20 rows

---

bigdata-platform/
├── index.tsregisterTool("bigdata_query", ...)
├── openclaw.plugin.json      ← manifest + config schema
├── skills/bigdata/SKILL.mdPlugin's own bundled Skill
├── docs/Detailed docs (read on-demand by LLM)
│   ├── query.md
│   ├── schema.md  
│   └── dashboard.md
└── scripts/Business logic (exec by Tool)
    └── query.py

---

export type OpenClawSkillMetadata = {
  // ...existing fields
  always?: boolean;
  skillKey?: string;
  primaryEnv?: string;
  emoji?: string;
  homepage?: string;
  os?: string[];
  requires?: {
    bins?: string[];
    anyBins?: string[];
    env?: string[];
    config?: string[];
  };
  activates?: {              // ← NEW: demand-driven context loading
    plugins?: string[];      // Plugin names whose Tools become visible
    // Future extensibility:
    // tools?: string[];     // Individual tool overrides
    // providers?: string[]; // Provider-level activation
  };
  install?: SkillInstallSpec[];
};

---

Phase 1 (Pure Skill era):     Script-level deps (requires.bins)
Phase 2 (Plugin era, today):  Config-level deps (requires.config), global Tool injection
Phase 3 (This proposal):      Context-level deps (activates.plugins), demand-driven injection
RAW_BUFFERClick to expand / collapse

Feature Request: Skill-Driven Plugin Context Visibility

Situation

As OpenClaw's plugin ecosystem grows (currently 84 extensions, 75 with independent npm packages), the framework faces a fundamental scalability challenge unique to AI Agent architectures: every registered Tool's function schema consumes LLM context tokens, regardless of whether the current conversation needs it.

Today's loading pipeline:

Gateway startup
  → Load ALL plugins globally
  → Register ALL Tools/Providers/Channels
  → User sends message → Start session
  → Snapshot ALL eligible Skills
  → Assemble system prompt with ALL Tool schemas + ALL matched Skill text
  → LLM inference + function calling

Current token cost formula (from OpenClaw docs):

total = 195 + Σ (97 + len(name) + len(description) + len(location))  per skill

For Tools, every registered tool's full JSON schema (name, description, parameters with nested types) is serialized into the prompt. A single tool with detailed parameter descriptions can consume 200-500+ tokens.

At scale: A user with 20 plugins registering 100 tools → thousands of tokens consumed every turn, even for a simple "hello" message. This creates three compounding problems:

  1. Cost: Token waste on every API call
  2. Performance: Longer prompts = slower inference + higher latency
  3. LLM confusion: More tools = harder selection = lower accuracy (the "paradox of choice" for function calling)

Current mitigation mechanisms and their limitations

MechanismWhat it doesLimitation
optional: true on ToolHides tool from LLM unless user adds to tools.allowStatic config — user must manually manage allowlists per tool
requires.config on SkillSkips Skill if Plugin not enabledBinary — Plugin is either fully visible or fully invisible
requires.bins / requires.envGates Skill on binary/env presenceLoad-time only — no per-conversation dynamics

None of these mechanisms support conversation-aware, dynamic Tool visibility.

Task

Decouple Plugin code loading from Plugin context visibility, enabling Skills to declare Plugin-level dependencies that control which Tool schemas are injected into the LLM prompt on a per-turn basis.

Design goals

  1. Plugins load globally (unchanged) — preserves security, hook/service lifecycle, and startup determinism
  2. Tool schemas inject conditionally — only when a matched Skill declares the corresponding Plugin dependency
  3. Plugin-level granularity — one declaration brings in all Tools + bundled Skills from that Plugin, maintaining internal cohesion
  4. Multi-level context loading — a progressive disclosure pattern that minimizes token usage at each stage

Action

Proposed mechanism: metadata.openclaw.activates in SKILL.md

Add a new frontmatter field activates, placed at the same level as the existing requires, that declares demand-driven context loading dependencies:

---
name: data-analyst
description: Query and analyze data from the big data platform
metadata:
  openclaw:
    requires:
      config: ["plugins.entries.bigdata-platform.enabled"]
    activates:
      plugins: ["bigdata-platform", "chart-generator"]
---

Why activates and not requires?

requires and activates serve orthogonal purposes:

requiresactivates
SemanticsGate / guard — "I need these to exist"Demand-load — "When I'm matched, activate these"
When evaluatedSkill load time (static)Skill match time (per-turn, dynamic)
Failure modeSkill is skipped entirelyPlugin Tools remain invisible (graceful)
Existing fieldsbins, anyBins, env, configplugins (new; extensible)

The structure of activates mirrors requires — both are objects under metadata.openclaw containing named arrays — keeping the frontmatter schema consistent and extensible.

Semantics: When this Skill is matched for the current conversation, OpenClaw should:

  1. Include this Skill's SKILL.md content in the prompt (existing behavior)
  2. Additionally: include all Tool schemas registered by the Plugins listed in activates.plugins
  3. Additionally: include any bundled Skills from those Plugins
  4. Tools from Plugins not referenced by any matched Skill's activates remain invisible to the LLM

Combining requires and activates

The two fields compose naturally:

Only requires.config → Traditional gate: Plugin not enabled = skip Skill. Tools still globally injected.
Only activates.plugins → No gate, but Tools injected on-demand when Skill matches.
Both → Gate first (requires), then demand-load (activates). Recommended pattern.

Prompt assembly flow (proposed)

User sends message
OpenClaw matches Skills based on description (existing behavior)
Collect all `activates.plugins` from matched Skills
Build Tool list = Core Tools + Tools from activated Plugins only
Assemble prompt with filtered Tool schemas + matched Skill text
LLM inference (leaner context, better accuracy)

Multi-level context loading pattern

This proposal naturally enables a progressive disclosure architecture:

Level 0: Skill descriptions in system prompt (~tens of tokens each, always present)
  ↓ LLM determines relevance
Level 0.5: SKILL.md read by LLM (~hundreds of tokens, on-demand)
  Contains: capability index table + Plugin dependency declaration
  ↓ Plugin Tools become visible
Level 1: Plugin docs read by LLM (~hundreds of tokens, on-demand)
  Contains: detailed Tool parameter docs, usage constraints
  ↓ LLM constructs function call
Level 2: Tool execution (0 tokens — code layer)
  Contains: actual business logic (TypeScript/Python scripts)

Token consumption is a funnel — each level is only loaded when the previous level indicates it's needed.

Example: Big Data Platform

Skill (data-analyst/SKILL.md):

---
name: data-analyst  
description: Query and analyze data from the big data platform
metadata:
  openclaw:
    requires:
      config: ["plugins.entries.bigdata-platform.enabled"]
    activates:
      plugins: ["bigdata-platform"]
---

# Data Analysis

## Available capabilities (provided by bigdata-platform plugin)

| Capability | Purpose | Details |
|-----------|---------|---------|
| bigdata_query | SQL queries | See {plugins.bigdata-platform}/docs/query.md |
| bigdata_table_info | Table schema | See {plugins.bigdata-platform}/docs/schema.md |
| bigdata_dashboard | Dashboard gen | See {plugins.bigdata-platform}/docs/dashboard.md |

## Workflow
1. Check table schema first
2. Write and execute SQL
3. Summarize results if > 20 rows

Plugin (bigdata-platform/):

bigdata-platform/
├── index.ts                  ← registerTool("bigdata_query", ...)
├── openclaw.plugin.json      ← manifest + config schema
├── skills/bigdata/SKILL.md   ← Plugin's own bundled Skill
├── docs/                     ← Detailed docs (read on-demand by LLM)
│   ├── query.md
│   ├── schema.md  
│   └── dashboard.md
└── scripts/                  ← Business logic (exec by Tool)
    └── query.py

Conversation flow:

User saysSkills matchedPlugins activatedTools visibleToken overhead
"Hello"NoneNoneCore only~0 extra
"Check yesterday's DAU"data-analystbigdata-platformCore + bigdata_*~200 extra
"DAU report with charts"data-analystbigdata-platform, chart-generatorCore + bigdata_* + chart_*~400 extra

vs. today's behavior: all plugin Tools always visible → ~2000+ extra tokens every turn.

Why Plugin-level (not Tool-level)?

Tool-level granularity (tools: ["bigdata_query", "bigdata_table_info"]) was considered but rejected:

  1. Maintenance burden: Every new Tool in a Plugin requires updating all referencing Skills
  2. Tight coupling: Plugin internal refactors (renaming Tools) break external Skills
  3. Incomplete: Plugin-bundled Skills wouldn't be activated
  4. Against Plugin semantics: A Plugin is a cohesive capability domain; cherry-picking individual Tools breaks that abstraction

Plugin-level declarations respect the Plugin as the atomic unit of capability, matching OpenClaw's architectural direction.

TypeScript type extension

export type OpenClawSkillMetadata = {
  // ...existing fields
  always?: boolean;
  skillKey?: string;
  primaryEnv?: string;
  emoji?: string;
  homepage?: string;
  os?: string[];
  requires?: {
    bins?: string[];
    anyBins?: string[];
    env?: string[];
    config?: string[];
  };
  activates?: {              // ← NEW: demand-driven context loading
    plugins?: string[];      // Plugin names whose Tools become visible
    // Future extensibility:
    // tools?: string[];     // Individual tool overrides
    // providers?: string[]; // Provider-level activation
  };
  install?: SkillInstallSpec[];
};

Backward compatibility

  • No breaking changes: Skills without activates continue to work exactly as today (all registered Tools visible)
  • Opt-in: Only Skills that explicitly declare activates get filtered behavior
  • Graceful degradation: If an activated Plugin is not installed, the activation is silently ignored (no error)
  • requires unchanged: Existing requires-based gating logic is fully preserved

Interaction with existing mechanisms

Existing mechanismInteraction
requires.configComplementary — requires gates Skill loading; activates controls Tool visibility
optional: true ToolsStill respected — activates overrides the need for tools.allow for activated Plugins
tools.allow / tools.denytools.deny still wins (security) — activation cannot override explicit denials
Plugin skills directoryPlugin's bundled Skills are also activated when the Plugin is referenced via activates.plugins
Skills watcherHot reload should re-evaluate activates references

Result

Quantified impact

For a setup with 10 Plugins registering 50 Tools total:

MetricTodayWith this feature
Tool schemas per turn (casual chat)50~15 (Core only)
Tool schemas per turn (domain task)50~20 (Core + relevant)
Estimated token saving per turn1000-3000 tokens
Annual cost saving (1000 turns/day, $3/1M tokens)~$1,000-3,000
LLM tool selection accuracyDegrades with countMaintained

Architectural significance

This proposal addresses a challenge unique to AI Agent frameworks that traditional software dependency management doesn't face: loading a module costs inference tokens, not just memory.

Traditional: import module → costs RAM (cheap, static)
AI Agent: register Tool → costs tokens per turn (expensive, recurring)

The insight: Plugin code loading and context visibility should be decoupled. Code loads globally for security and stability; context visibility is driven by Skill dependency graphs on demand.

This moves OpenClaw's context management from broadcast (all Tools to all turns) to multicast (relevant Tools to relevant turns), which is essential for the framework's scalability as the Plugin ecosystem grows.

Evolution context

Phase 1 (Pure Skill era):     Script-level deps (requires.bins)
Phase 2 (Plugin era, today):  Config-level deps (requires.config), global Tool injection
Phase 3 (This proposal):      Context-level deps (activates.plugins), demand-driven injection

Proposed by @supperdsj — based on production experience running OpenClaw with 40+ custom Skills and multiple domain-specific Plugin workflows.

extent analysis

Fix Plan

To implement the proposed activates mechanism, follow these steps:

  1. Update Skill metadata:

    • Add an activates field to the metadata.openclaw section in SKILL.md files.
    • This field should contain a list of Plugin names that should be activated when the Skill is matched.
  2. Modify Plugin loading:

    • Load all Plugins globally during startup, but do not inject their Tool schemas into the LLM prompt by default.
    • Create a mechanism to track which Plugins are activated for each conversation turn.
  3. Implement demand-driven Tool injection:

    • When a Skill is matched, check its activates field and activate the specified Plugins.
    • Inject the Tool schemas of the activated Plugins into the LLM prompt.
  4. Update prompt assembly flow:

    • Collect all activates.plugins from matched Skills.
    • Build the Tool list by including Core Tools and Tools from activated Plugins.
    • Assemble the prompt with the filtered Tool schemas and matched Skill text.

Example Code

Here's an example of how the activates field could be implemented in a Skill's metadata:

interface OpenClawSkillMetadata {
  // ... existing fields
  activates?: {
    plugins: string[];
  };
}

// Example Skill metadata
const skillMetadata: OpenClawSkillMetadata = {
  name: 'data-analyst',
  description: 'Query and analyze data from the big data platform',
  metadata: {
    openclaw: {
      requires: {
        config: ['plugins.entries.bigdata-platform.enabled'],
      },
      activates: {
        plugins: ['bigdata-platform', 'chart-generator'],
      },
    },
  },
};

When a Skill with this metadata is matched, the bigdata-platform and chart-generator Plugins will be activated, and their Tool schemas will be injected into the LLM prompt.

Verification

To verify that the fix worked, test the following scenarios:

  • A conversation turn with a Skill that has no activates field should only include Core Tools in the LLM prompt.
  • A conversation turn with a Skill that has an activates field should include the Tool schemas of the activated Plugins in the LLM prompt.
  • The number of tokens consumed by the LLM prompt should decrease significantly when the activates mechanism is used.

Extra Tips

  • Make sure to handle cases where a Plugin is not installed or is not activated correctly.
  • Consider adding logging or monitoring to track the performance and token usage of the activates mechanism.
  • Review the existing requires and optional mechanisms to ensure they are still working as expected with the new activates mechanism.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix Feature Request: Skill-Driven Plugin Context Visibility (activates.plugins) [1 participants]