扩展机制深入:Configuration、Plugins、MCP 与 Skills

Extensions 是 Agent 超越内置工具集的方式。在 Codex 和 Claw 中,extension-related features 不是单独一层。它们横跨 configuration、prompt construction、tool registration、permissions、model requests 和 UI events。

这篇深入文章把四种扩展界面放在一起讨论:

  • Configuration:turn 开始前运行时如何成形。
  • Plugins:添加行为的打包代码或元数据。
  • MCP:基于协议的外部工具和资源。
  • Skills:可复用的任务特定指令和工作流。

Extension Pipeline

实用 extension pipeline 有五个阶段:

def build_extension_context(workspace, cli):
    config = resolve_configuration(workspace, cli)
    plugins = load_plugins(config)
    mcp_servers = connect_mcp_servers(config)
    skills = discover_skills(workspace, config)

    tools = []
    tools += builtin_tools(config)
    tools += plugin_tools(plugins)
    tools += mcp_tools(mcp_servers)
    tools += skill_tools(skills)

    prompt_context = render_extension_prompt_context(
        config=config,
        plugins=plugins,
        mcp_servers=mcp_servers,
        skills=skills,
    )

    return ExtensionContext(
        config=config,
        tools=tools,
        prompt_context=prompt_context,
    )

顺序很重要。只有 configuration 解析完成后,才能正确构建模型可见工具列表。只有知道哪些 plugins、MCP servers 和 skills 处于活动状态后,才能正确渲染 extension prompt context。

Configuration Resolution

Configuration 是 merge problem。Defaults 应该容易覆盖,本地项目设置不应与全局用户偏好混淆。

def resolve_configuration(workspace, cli_flags):
    layers = [
        defaults(),
        system_config(),
        user_config(),
        project_config(workspace),
        local_project_config(workspace),
        environment_variables(),
        cli_flags,
    ]

    config = {}
    provenance = {}

    for layer in layers:
        for key, value in layer.items():
            config[key] = value
            provenance[key] = layer.name

    return validate(config, provenance)

Provenance 很有用。如果运行时选择 model X,用户可能需要知道它来自 CLI flag、环境变量、项目配置还是默认值。Claw 的 CLI 因此跟踪 model provenance。Codex 也必须把 resolved configuration 带过 TUI、exec、app server 和 sandbox commands 等不同入口。

Plugin Loading

Plugins 是打包扩展单元。plugin 可以贡献 commands、hooks、tool definitions、prompt sections 或 marketplace metadata。

def load_plugins(config):
    plugins = []

    for entry in config.enabled_plugins:
        manifest = read_plugin_manifest(entry.path)
        validate_manifest(manifest)

        plugin = Plugin(
            id=manifest.id,
            tools=load_plugin_tools(manifest),
            hooks=load_plugin_hooks(manifest),
            prompt_sections=manifest.prompt_sections,
        )
        plugins.append(plugin)

    return plugins

Plugin 边界应该明确:

  • plugin tool 应该有 schema。
  • plugin hook 应该声明何时运行。
  • plugin 不应绕过权限。
  • plugin 的 prompt text 应该简洁且限定范围。
  • plugin load failures 应该可见且可恢复。

MCP Loading

MCP 把 Agent 连接到外部工具和资源。运行时启动或连接到配置好的 servers,发现 capabilities,并把这些 capabilities 暴露给模型。

async def connect_mcp_servers(config):
    connected = []

    for spec in config.mcp_servers:
        server = await McpServer.connect(spec.command, spec.args, spec.env)
        capabilities = await server.initialize()

        connected.append({
            "server": server,
            "tools": capabilities.tools,
            "resources": capabilities.resources,
        })

    return connected

MCP tools 在与内置工具混合前应该被规范化:

def mcp_tool_to_agent_tool(server, mcp_tool):
    return Tool(
        name=f"mcp_{server.name}_{mcp_tool.name}",
        description=mcp_tool.description,
        input_schema=mcp_tool.input_schema,
        run=lambda args: server.call_tool(mcp_tool.name, args),
    )

运行时仍需要策略检查。External 不等于 trusted。

Skills

Skills 打包可复用 operational knowledge。skill 可以简单到只是 prompt fragment,也可以复杂到选择工具并验证输出的 workflow。

def discover_skills(workspace, config):
    skill_dirs = [
        config.user_skill_dir,
        workspace / ".codex" / "skills",
        workspace / ".claw" / "skills",
    ]

    skills = []
    for directory in skill_dirs:
        for manifest in find_skill_manifests(directory):
            skills.append(load_skill(manifest))

    return skills

好的 skill 有狭窄 trigger:

class Skill:
    name: str
    description: str
    trigger_examples: list[str]
    instructions: str
    allowed_tools: set[str]

    def applies_to(self, task):
        return semantic_match(task, self.trigger_examples)

Skills 不应该变成第二个隐藏提示系统。当模型能看到选中了哪个 skill 以及为什么选它时,skills 效果最好。

渲染 Extension Context

模型需要简洁上下文,而不是完整 manifests。

def render_extension_prompt_context(config, plugins, mcp_servers, skills):
    lines = []

    lines.append(f"Active profile: {config.profile}")

    if plugins:
        lines.append("Enabled plugins:")
        for plugin in plugins:
            lines.append(f"- {plugin.id}: {plugin.summary}")

    if mcp_servers:
        lines.append("Connected MCP servers:")
        for server in mcp_servers:
            lines.append(f"- {server.name}: {len(server.tools)} tools")

    if skills:
        lines.append("Available skills:")
        for skill in skills:
            lines.append(f"- {skill.name}: {skill.description}")

    return "\n".join(lines)

这类内容通常属于 prompt 的动态部分,因为活动 plugins、MCP servers 和 skills 可能跨 sessions 或 workspaces 变化。

注册 Extension Tools

一旦 extension capabilities 变成工具,它们对模型应该看起来像内置工具,但仍携带用于 policy 和 diagnostics 的 metadata。

def register_extension_tools(registry, extension_context):
    for tool in extension_context.tools:
        registry.register(
            name=tool.name,
            schema=tool.input_schema,
            handler=tool.run,
            source=tool.source,
            permission_profile=tool.permission_profile,
        )

source 字段很重要。如果工具失败,UI 应该能说明它来自 built-in handler、plugin、MCP server 还是 skill。

Extension Tools 的权限

Extension tools 应该经过与内置工具相同的授权路径。

async def authorize_extension_tool(call, policy):
    if call.source == "mcp":
        required = "external_tool"
    elif call.source == "plugin":
        required = call.metadata.permission_profile
    elif call.source == "skill":
        required = required_mode_for_skill(call)
    else:
        required = classify_builtin_tool(call)

    return await policy.authorize(call, required_mode=required)

重要规则很简单:extension loading 应该增加 capability,而不是静默增加 authority。

失败处理

Extension systems 的失败方式比内置工具更多:

  • plugin manifest 无效。
  • plugin hook 崩溃。
  • MCP server 无法启动。
  • MCP server 启动但未初始化。
  • skill manifest 格式错误。
  • 外部来源的 tool schema 对模型不安全。
def load_extension_safely(loader, descriptor):
    try:
        return loader(descriptor)
    except Exception as error:
        return ExtensionLoadFailure(
            name=descriptor.name,
            reason=str(error),
            recoverable=True,
        )

可恢复失败应该报告给用户,并从模型可见工具列表中排除。模型不应该看到无法执行的工具。

Codex 与 Claw 对比

扩展关注点 Codex Claw
Configuration TUI、exec、app server、tools、sandboxing 共享的宽运行时配置 以 CLI 为中心的配置,包含 model、permissions、prompt sections、plugins、MCP、skills
Plugins 存在于较新的运行时和产品界面 一等 CLI plugin management 和 runtime tool definitions
MCP Client/server 和 resource/tool surfaces MCP server manager、resources、auth 和 tool exposure
Skills 集成进 prompt/tool context Skill listing、install、invocation 和 tool-like surfaces
Permission boundary Approval 和 sandbox orchestration Permission policy 和 enforcer
Prompt boundary Runtime context 和 model-visible schemas 带 config 和 project memory sections 的 modular prompt builder

实用设计规则

  • 在构建工具前解析 configuration。
  • 为重要配置值跟踪 provenance。
  • 保持 extension prompt text 简洁。
  • 把 MCP 和 plugin tools 规范化成与内置工具相同的 registry shape。
  • 永远不要让 extension tools 绕过权限。
  • 把 load failures 作为 diagnostics 发出,而不是作为坏掉的模型可见工具。
  • 把 skills 视为有清晰 triggers 的 workflows,而不是模糊 prompt bundles。

最小端到端流程

async def start_agent_with_extensions(workspace, cli):
    config = resolve_configuration(workspace, cli)
    extension_context = build_extension_context(workspace, cli)

    prompt = build_prompt(
        base_instructions=config.base_instructions,
        project_memory=load_project_memory(workspace),
        extension_context=extension_context.prompt_context,
    )

    registry = ToolRegistry()
    register_builtin_tools(registry, config)
    register_extension_tools(registry, extension_context)

    runtime = AgentRuntime(
        config=config,
        prompt=prompt,
        tools=registry,
        permission_policy=build_permission_policy(config),
    )

    return runtime

这是清晰心智模型:configuration 塑造运行时,extensions 增加 capabilities,prompt 告诉模型存在哪些能力,registry 执行工具,permissions 约束每个动作。