feat(plugin): progressive plugin loading — activate plugin components on demand - #92
Merged
Merged
Conversation
… on demand Installed plugins used to inject every bundled skill's frontmatter line and every MCP tool's full JSON schema into each request, so TTFT grew linearly with the number of installed plugins. This change brings the plugin back as a runtime aggregation unit: - At assembly time, plugin components are removed from the enabled sets; the system prompt keeps a one-line directory entry per plugin (slug + description, sorted by slug, byte-stable across activation states) and a single load_plugin tool is registered. - When the model activates a plugin, its MCP servers are connected and its skills registered in place; schemas and skill instructions are recomputed every ReAct round, so they take effect on the next step. - Activation is sticky per chat (chat_sessions.metadata.activated_plugins); explicitly invoking a plugin counts as activation. Sub-agent bound plugins are deferred the same way with run-scoped activation only. - Plugins with stdio-transport MCP components stay eagerly loaded; set PLUGIN_PROGRESSIVE_LOADING=false to revert to eager assembly. Also hides AgentScope's builtin Skill viewer schema (skills load exclusively through view_text_file here, so the schema was pure per-round prefill waste) and adds a localized display for the load_plugin tool call in the chat UI.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Installed plugins used to inject all of their bundled capabilities into every request — one skill-list line per skill in the system prompt, plus the full JSON schema of every MCP tool in the
toolsparameter, re-sent on every ReAct round. TTFT therefore grew linearly with the number of installed plugins.This PR introduces progressive plugin loading: the plugin becomes a runtime aggregation unit again.
slug+ description) and a singleload_plugintool is registered.load_plugin. Only then are the plugin's MCP servers connected (stateless HTTP clients appended to the live toolkit) and its skills registered. Schemas and skill instructions are recomputed each round, so everything is usable from the next step.chat_sessions.metadata.activated_plugins), so subsequent turns assemble the plugin eagerly with no repeated activation. Explicitly invoking a plugin (slash /+menu) counts as activation.The plugin directory is sorted by slug and byte-stable regardless of activation state, so provider-side prefix caching pays for an activation only on the activation turn and the one after it.
Boundaries
PLUGIN_PROGRESSIVE_LOADING=falsereverts to eager assembly.Also included
Skillviewer schema: skills load exclusively throughview_text_filein this stack, so the schema was pure per-round prefill waste and a wrong entry point bypassing path mapping / runtime hints / observability.load_plugintool call: localized label, inline plugin slug, and a formatted activation-summary card instead of a raw JSON dump.Testing
tests/test_plugin_progressive_loading.py(9 cases): deferral resolution (visibility / enabled intersection / stdio exclusion / activation & invocation exemption with persistence), directory rendering stability,load_pluginruntime side effects (toolkit mutation, allow rules, close-list, chat persistence, sub-agent no-persist), env kill switch.