OpenHands 源码解析 · 第 19 讲
OpenHands 源码解析系列 第 19 讲:插件系统与扩展点 基于 OpenHands 源码 · 2026-08-15 一、什么是插件系统 OpenHands 的插件系统(Plugin System)是平台可扩展性的核心。它让管理员、组织和用户能够在不同层级注册外部插件市场(Marketplace),动态加载 Skill、Hook 和 MCP 工具——而无需修改核心代码。整个系统围绕三个关键概念构建: Marketplace :一个 Git 仓库,包含插件描述、Skill 文件和扩展点定义 MarketplaceRegistration :注册一个市场源的配置对象 Scope 层级 :Instance → Org → User 三级继承与覆盖机制 本节深入源码,拆解插件系统从注册、组合、克隆到会话绑定的完整链路。 二、MarketplaceRegistration:插件市场的注册模型 一切始于 MarketplaceRegistration ,它定义了一个插件市场的来源和加载策略: 📄 openhands/app_server/settings/settings_models.py(第 75-151 行) class MarketplaceRegistration(BaseModel): name: str = Field(description='Identifier for this marketplace registration') source: str = Field( description="Marketplace source: 'github:owner/repo', git URL, or local path" ) ref: str | None = Field( default=None, description='Optional branch, tag, or commit (only for git sources)', ) repo_path: str | None = Field( default=None, description=( 'Subdirectory path within the git repository containing the marketplace ' "(e.g., 'marketplaces/internal' for monorepos)." ), ) auto_load: bool = Field( default=False, description=( 'Auto-load behavior for this marketplace. ' 'True = load all plugins at conversation start. ' 'False = registered for resolution but not auto-loaded.' ), ) scope: 'MarketplaceScope | None' = Field( default=None, description=( 'Scope of this marketplace registration. ' 'Set automatically by backend based on storage layer' ), ) 六个字段各司其职: name 是标识符, source 指定仓库来源, ref 锁定版本, repo_path 支持 monorepo 子目录, auto_load 控制是否在会话启动时自动加载, scope 由后端自动设置表示来源层级。 严格的输入校验 每个字段都有对应的 Pydantic validator,防止注入攻击和路径穿越: 📄 settings_models.py(第 153-214 行) # name 校验:必须以字母开头,只允许字母数字横线下划线 @field_validator('name') @classmethod def validate_name(cls, v: str) -> str: if not re.match(r'^[a-zA-Z][a-zA-Z0-9_-]*$', v): raise ValueError('name mu…