跳转到主要内容

Documentation Index

Fetch the complete documentation index at: https://docs.qoder.com/llms.txt

Use this file to discover all available pages before exploring further.

options.plugins 用来把本地 plugin 目录加载进当前会话。SDK 会为每个本地 plugin 转成一个 --plugin-dir <path> 启动参数;插件里包含的 commands、agents、skills 和 MCP servers 都会参与本次会话的能力发现。

加载本地 plugin

from qoder_agent_sdk import QoderAgentOptions, QoderSDKClient

options = QoderAgentOptions(
    plugins=[
        {"type": "local", "path": "/path/to/my-plugin"},
    ],
)

async with QoderSDKClient(options) as client:
    info = await client.get_server_info()
    print(info.get("commands"))
    print(info.get("agents"))
    print(info.get("plugins"))
可以同时传多个本地 plugin,会按顺序写出多次 --plugin-dir
options = QoderAgentOptions(
    plugins=[
        {"type": "local", "path": "/path/to/plugin-a"},
        {"type": "local", "path": "/path/to/plugin-b"},
    ],
)
💡 query() 是一次性的消息流,无法在握手后查询 init 响应。要读取插件贡献的命令 / agent / skill,请用 QoderSDKClient 并在 connect() 之后调用 get_server_info(),或在消息流里捕获 SystemMessage(subtype='init') 自行读取 message.data

插件目录布局

一个本地 plugin 通常可以包含:
my-plugin/
  .qoder-plugin/plugin.json
  commands/
  agents/
  skills/
  .mcp.json
.qoder-plugin/plugin.json 用来声明插件名、版本、描述。其余目录按文件类型自动被 CLI 扫描。 SDK 不会校验路径是否存在 / 是否合法:
  • 不存在的 --plugin-dir 路径在 SDK 模式里会被静默忽略,会话仍正常初始化。
  • 损坏的 frontmatter / .mcp.json 不阻断 init,损坏的命令不会出现在 init 响应中。
  • 想显式诊断 plugin 加载失败,目前只能依赖 reload_plugins().error_count 兜底。

插件贡献 slash commands

插件里的 commands/*.md 会出现在 get_server_info()['commands'] 中,名称以 <plugin>:<cmd> 限定名形式出现。
async with QoderSDKClient(options) as client:
    info = await client.get_server_info()
    for cmd in info.get("commands", []):
        print(cmd["name"], cmd.get("description"))

插件贡献 agents

插件里的 agents/*.md 会出现在 get_server_info()['agents'] 中。SDK 还提供同步便捷方法直接拿到这份列表:
async with QoderSDKClient(options) as client:
    for agent in client.supported_agents():
        print(agent["name"], agent.get("description"))

插件贡献 skills

插件里的 skills/<name>/SKILL.md 会以插件限定名(plugin:skill)注册。要让主会话能调用,需要在 options.skills 里显式列出,见 Skills 文档

插件贡献 MCP servers

插件里的 .mcp.json 会由 CLI 启动并纳入 MCP 状态,可以通过 get_mcp_status() 读取:
async with QoderSDKClient(options) as client:
    status = await client.get_mcp_status()
    for server in status["mcpServers"]:
        print(server["name"], server["status"])

临时覆盖已安装同名插件

通过 options.plugins 加载的本地 plugin 是 session-scoped。当前会话中,如果它和已安装插件同名,本地 plugin 会优先参与本次会话能力发现。这个能力适合做 plugin 开发、调试和灰度验证。
options = QoderAgentOptions(
    # 本地版本只在这个 query 会话内生效,不会改动用户全局安装状态
    plugins=[{"type": "local", "path": "./my-plugin-dev"}],
)

运行中重新加载 Plugins

如果 plugin 目录发生变化,可以在同一个 QoderSDKClient 会话里调用 reload_plugins(),让 CLI 重新扫描 plugin 资源。
async with QoderSDKClient(options) as client:
    refreshed = await client.reload_plugins()

    print(refreshed["commands"])
    print(refreshed["agents"])
    print(refreshed["plugins"])
    print(refreshed["mcpServers"])
    print(refreshed["error_count"])
典型用途:
  • 开发 plugin 时新增或删除 commands/*.md 后刷新。
  • 安装或更新本地 plugin 后,不重启宿主应用。
  • 宿主 UI 需要展示 reload 后的 commands、agents、plugins 和 MCP 状态。
注意:reload_plugins() 只在 QoderSDKClient(streaming)模式下有意义;一次性的 query() 流没有运行时控制 channel。

Options 速查

字段类型说明
pluginslist[SdkPluginConfig]加载本地 plugin 目录,目前常用 {"type": "local", "path": ...}
settingsstr | Path | dict[str, Any] | None透传给 CLI 的 settings,可以包含 enabledPluginspluginConfigs 等字段
setting_sourceslist[Literal["user", "project", "local"]] | None控制 CLI 读取哪些 settings 来源
settings.enabledPluginssettings.pluginConfigssettings.allowedChannelPluginssettings.strictPluginOnlyCustomization 这类企业策略字段 SDK 类型已透传,但实际链路依赖具体 CLI 版本,使用前请结合自己环境验证。

返回值参考

client.get_server_info()SystemMessage(subtype='init').data

{
    "commands": [
        {"name": "plugin-a:greet", "description": "...", "argumentHint": "..."},
        ...
    ],
    "agents": [
        {"name": "plugin-a:helper", "description": "...", "model": "sonnet"},
        ...
    ],
    "skills": [
        {"name": "plugin-a:echo", "description": "...", "source": "plugin"},
        ...
    ],
    "plugins": [
        {"name": "plugin-a", "path": "/path/to/plugin-a", "source": "local"},
        ...
    ],
    # 还包含 models / account / output_style 等字段
}

client.reload_plugins()

返回 ReloadPluginsResponse
{
    "commands": list[Any],
    "agents": list[Any],
    "plugins": list[PluginInfo],            # {"name": str, "path": str, "source": str?}
    "mcpServers": list[McpServerStatus],    # 见 mcp.md 的 McpServerStatus
    "error_count": int,                     # 本次 reload 加载失败的 plugin 数
}

最佳实践

  • 给宿主 UI 先读 get_server_info():它是展示 commands、agents、skills、plugins 的稳定入口。一次性 query() 想要这份数据时改用 QoderSDKClient,或在消息流里读 SystemMessage(subtype='init').data
  • 开发 plugin 时使用 options.plugins:它只影响当前会话,不需要修改用户全局安装状态。
  • reload 之前先准备好用户提示reload_plugins() 会触发 CLI 重新扫描磁盘,可能短暂改变可用资源列表,UI 上最好同步更新。
  • 错误诊断看 error_count:reload 后 error_count > 0 表示有 plugin 资源加载失败,应该把它的来源展示给用户。

当前限制

  • 部分 qodercli 版本下,本地 plugin 的 commands、agents、MCP 可以正常出现在初始化结果中,但 plugin skills 可能没有出现在 get_server_info()['skills'],这属于 CLI 侧发现链路问题。
  • 当前 qodercli 实现下,不存在的 --plugin-dir 路径在 SDK 模式里会被静默忽略;如果需要显式诊断 plugin 加载失败,目前只能通过 reload_plugins().error_count 兜底。
  • reload_plugins()QoderSDKClient 暴露的运行时控制 API;如果当前 CLI 版本返回 this._plugins 相关内部错误,需要升级到修复后的 qodercli。
  • settings.strictPluginOnlyCustomizationsettings.allowedChannelPluginssettings.pluginConfigs.<pid>.options 模板替换都是 dict 透传字段,SDK 不解析,能否生效完全取决于 CLI 版本。