Token导航 LogoToken导航

Agent Skill · 研究检索

backend-integrator(后端集成商)

backend-integrator 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

backend-integrator 是研究检索类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为接触敏感数据;许可证信息还不明确,第三方扫描有提醒项,按安装量在研究检索类的 73,675 个 Skill 里排第 47,223。

总安装 744周安装 31GitHub Stars 968下载 248核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:backend-integrator(后端集成商)
来源仓库:https://github.com/massgen/massgen
仓库路径:skills/backend-integrator
安装命令:
npx skills add https://github.com/massgen/massgen --skill backend-integrator
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/massgen/massgen --skill backend-integrator

这个 Skill 是做什么的

研究检索类 Skill 主要解决「找资料、核对事实、把来源整理清楚」的问题,通常会让助手先检索再总结。

用于将新 LLM 后端集成到 MassGen 系统中,提供完整清单与模式参考。适合添加 provider、审计缺失集成点或理解扩展机制。根据 API 类型选择 Stateless/OpenAI-compatible 或 Response API 基类。实施前应评估接口规范与认证方式,确保与现有调度与错误处理兼容。

backend-integrator 属于研究检索类 Skill,可作为该场景下的辅助能力补充。

来源仓库内路径:skills/backend-integrator

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/massgen/massgen --skill backend-integrator;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要接触敏感数据,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

backend-integrator 怎么安装?

在终端执行 npx skills add https://github.com/massgen/massgen --skill backend-integrator。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

backend-integrator 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

backend-integrator 需要什么权限?

权限级别是接触敏感数据。该 Skill 可能接触密钥、Token、环境变量或敏感配置,应进入高风险复核队列,默认不自动发布。

backend-integrator 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

backend-integrator 用的人多吗?

公开数据是累计安装 744 次,近一周安装 31 次,下载 248 次,GitHub 968 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

backend-integrator 安全吗?

第三方扫描有提醒项,说明存在需要人工确认的行为。安装前请打开源码看清它读了什么、联网到哪里。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。

先想清楚的地方

  • 需要接触敏感数据,装到常用环境前要先评估影响面。
  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方扫描存在提醒项或未通过项,需要人工逐条确认。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理研究检索类任务、又不想每次都手写提示词的人。

不太适合

  • 环境里有大量密钥、凭证,不方便给第三方 Skill 读取的人。
  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

研究检索类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
find-skills

寻找技能 · Codex、Claude

31,199,81316,486操作浏览器MIT有提醒
self-improving-agent

自我改进 Agent · OpenClaw

16,464,0023,396接触敏感数据MIT-0通过
soultrace

灵魂追踪 · Codex、Claude

7,588,94412需要联网未明确有提醒
self-improving

自我完善 · OpenClaw

6,829,2841,046需要联网MIT-0通过
microsoft-foundry

微软代工厂 · Codex、Claude

6,614,144764调用外部服务未明确有提醒
backend-integrator

后端集成商 · 本页

744968接触敏感数据未明确有提醒

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

Backend Integrator

This skill provides the complete checklist and patterns for integrating a new LLM backend into MassGen. A full integration touches ~15 files across the codebase.

When to Use This Skill

  • Adding a new LLM provider/backend
  • Auditing an existing backend for missing integration points
  • Understanding what files to modify when extending backend capabilities

Integration Architecture

Backend Type Decision:
  Stateless + OpenAI-compatible API   → subclass ChatCompletionsBackend
  Stateless + custom API              → subclass CustomToolAndMCPBackend
  Stateless + Response API format     → subclass ResponseBackend
  Stateful CLI wrapper (like Codex, Gemini CLI) → subclass LLMBackend directly
  Stateful SDK wrapper (like Claude Code, Copilot) → subclass LLMBackend directly

Complete Checklist

Phase 1: Core Implementation (3 files)

1.1 Backend Class

File: massgen/backend/<name>.py

Choose base class:

  • LLMBackend — bare minimum, you handle everything
  • CustomToolAndMCPBackend — adds MCP + custom tool support (most common)
  • ChatCompletionsBackend — for OpenAI-compatible APIs (inherits from above)
  • ResponseBackend — for OpenAI Response API format

Required methods:

async def stream_with_tools(self, messages, tools, **kwargs) -> AsyncGenerator[StreamChunk, None]:
    """Main streaming method. Yield StreamChunks."""

def get_provider_name(self) -> str:
    """Return provider name string (e.g., 'OpenAI', 'Codex')."""

def get_filesystem_support(self) -> FilesystemSupport:
    """Return NONE, NATIVE, or MCP."""

StreamChunk types to yield:

TypeWhenKey fields
"content"Text outputcontent="..."
"tool_calls"Tool invocationtool_calls=[{id, name, arguments}]
"reasoning"Thinking/reasoning deltareasoning_delta="..."
"reasoning_done"Reasoning completereasoning_text="..."
"reasoning_summary"Reasoning summary deltareasoning_summary_delta="..."
"reasoning_summary_done"Reasoning summary completereasoning_summary_text="..."
"complete_message"Full assistant messagecomplete_message={...}
"complete_response"Raw API responseresponse={...}
"done"Stream completeusage={prompt_tokens, completion_tokens, total_tokens}
"error"Error occurrederror="..."
"agent_status"Status updatestatus="...", detail="..."
"backend_status"Backend-level statusstatus="...", detail="..."
"compression_status"Compression eventstatus="...", detail="..."
"hook_execution"Hook ranhook_info={...}, tool_call_id="..."

Common fields on all chunks: source (agent/orchestrator ID), display (bool, default True).

Token tracking — call one of:

self._update_token_usage_from_api_response(usage_dict, model)  # If API returns usage
self._estimate_token_usage(messages, response_text, model)      # Fallback

Timing — call in stream_with_tools:

self.start_api_call_timing(self.model)       # Before API call
self.record_first_token()                     # On first content chunk
self.end_api_call_timing(success=True/False)  # After completion

For stateful backends (CLI/SDK wrappers), also implement:

def is_stateful(self) -> bool: return True
async def clear_history(self) -> None: ...
async def reset_state(self) -> None: ...

Compression support — inherit StreamingBufferMixin and call:

self._clear_streaming_buffer(**kwargs)       # Start of stream
self._finalize_streaming_buffer(agent_id=id) # End of stream
1.2 Formatter (if needed)

File: massgen/formatter/<name>_formatter.py

Only needed if the API uses a non-standard message/tool format (not OpenAI chat completions format). Subclass FormatterBase and implement format_messages(), format_tools(), format_mcp_tools().

Existing formatters:

  • _claude_formatter.py — Anthropic Messages API
  • _gemini_formatter.py — Gemini API
  • _chat_completions_formatter.py — OpenAI/generic (reuse for compatible APIs)
  • _response_formatter.py — OpenAI Response API format
1.3 API Params Handler (if needed)

File: massgen/api_params_handler/<name>_api_params_handler.py

Only needed if the backend calls an HTTP API and needs to filter/transform YAML config params before passing to the API. Subclass APIParamsHandlerBase.

CLI/SDK wrappers (Codex, Claude Code) typically don't need this — they build commands directly.

Phase 2: Registration (4 files)

2.1 Backend init.py

File: massgen/backend/__init__.py

from .your_backend import YourBackend
# Add to __all__
2.2 CLI Backend Mapping

File: massgen/cli.py

Add to create_backend() function:

elif backend_type == "your_backend":
    api_key = kwargs.get("api_key") or os.getenv("YOUR_API_KEY")
    if not api_key:
        raise ConfigurationError(
            _api_key_error_message("YourBackend", "YOUR_API_KEY", config_path)
        )
    return YourBackend(api_key=api_key, **kwargs)

For CLI-based backends that don't need API keys, skip the key check.

2.3 Capabilities Registry

File: massgen/backend/capabilities.py

Add entry to BACKEND_CAPABILITIES:

"your_backend": BackendCapabilities(
    backend_type="your_backend",
    provider_name="YourProvider",
    supported_capabilities={"mcp", "web_search", ...},
    builtin_tools=["web_search"],  # Provider-native tools
    filesystem_support="mcp",      # "none", "mcp", or "native"
    models=["model-a", "model-b"], # Newest first
    default_model="model-a",
    env_var="YOUR_API_KEY",        # Or None
    notes="...",
    model_release_dates={"model-a": "2025-06"},
    base_url="https://api.example.com/v1",  # If applicable
)
2.4 Config Validator (if needed)

File: massgen/config_validator.py

Add backend-specific validation to _validate_backend() if there are special rules (e.g., required params, incompatible combinations).

Phase 3: Token Management (1 file)

3.1 Pricing

File: massgen/token_manager/token_manager.py

Check LiteLLM first — only add to PROVIDER_PRICING if the model is NOT in the LiteLLM database. Provider name must match get_provider_name() exactly (case-sensitive).

Phase 4: Excluded Params (2 files, if adding new YAML params)

4.1 Base Class Exclusions

File: massgen/backend/base.py -> get_base_excluded_config_params()

4.2 API Params Handler Exclusions

File: massgen/api_params_handler/_api_params_handler_base.py -> get_base_excluded_params()

Both must stay in sync. Add any new framework-level YAML params that should NOT be passed to the provider API.

Phase 5: Authentication

5.1 API Key Backends (standard)

Most backends use API keys. Set env_var in capabilities.py and add the key check in cli.py:

# cli.py
api_key = kwargs.get("api_key") or os.getenv("YOUR_API_KEY")
if not api_key:
    raise ConfigurationError(...)
return YourBackend(api_key=api_key, **kwargs)
5.2 OAuth / Subscription Auth (CLI/SDK wrappers)

For backends that support OAuth (like Codex, Claude Code), implement a multi-tier auth cascade:

def __init__(self, api_key=None, **kwargs):
    # Tier 1: Explicit API key
    self.api_key = api_key or os.getenv("YOUR_API_KEY")
    # Tier 2: Check cached OAuth tokens
    self.use_oauth = not bool(self.api_key)
    self.auth_file = Path.home() / ".your_cli" / "auth.json"

async def _ensure_authenticated(self):
    if self.api_key:
        os.environ["YOUR_API_KEY"] = self.api_key
        return
    if self._has_cached_credentials():
        return
    # Tier 3: Initiate OAuth flow
    await self._initiate_oauth_flow()

async def _initiate_oauth_flow(self, use_device_flow=False):
    """Wrap the CLI's login command."""
    cmd = [self._cli_path, "login"]
    if use_device_flow:
        cmd.append("--device-auth")  # For headless/SSH
    proc = await asyncio.create_subprocess_exec(*cmd, ...)

In cli.py: Skip API key check — delegate auth to the backend:

elif backend_type == "your_backend":
    # Auth handled by backend (API key or OAuth)
    return YourBackend(**kwargs)

In capabilities.py: Set env_var to the API key name (optional, not required for OAuth):

env_var="YOUR_API_KEY",  # Optional - can use OAuth instead
notes="Works with subscription auth (via `your-cli login`) or YOUR_API_KEY."

*NOTE: We only offer oauth through supported SDKs or programmatic command line usage as suggested by the provider. We must find the accepted way of using oauth for each backend to ensure we are supporting it correctly (e.g., use the Claude Agent SDK, NOT Claude Code with API spoofing).*

5.3 No Auth (local inference)

For local servers (LM Studio, vLLM, SGLang), set env_var=None in capabilities. No key check in cli.py.

Reference implementations:

  • codex.py — Full OAuth with browser + device code flows
  • claude_code.py — 3-tier: CLAUDE_CODE_API_KEY -> ANTHROPIC_API_KEY -> subscription login
  • lmstudio / vllm / sglang — No auth (env_var=None)

Phase 6: Custom Tools & MCP

6.1 Standard Path (API backends)

If inheriting from CustomToolAndMCPBackend, MCP and custom tools work automatically:

  • MCP servers from YAML mcp_servers config
  • Custom tools from custom_tools / custom_tools_path config
  • Filesystem MCP injected by FilesystemManager when cwd is set
  • Tool execution handled by ToolManager
6.2 Multimodal Tools (all backend types)

When enable_multimodal_tools: true is set, the backend must register read_media and generate_media custom tools. Use the shared helper in massgen/backend/base.py:

from .base import get_multimodal_tool_definitions

# In __init__:
enable_multimodal = self.config.get("enable_multimodal_tools", False) or kwargs.get("enable_multimodal_tools", False)
if enable_multimodal:
    custom_tools.extend(get_multimodal_tool_definitions())
  • API backends (CustomToolAndMCPBackend subclasses): handled automatically — base class calls get_multimodal_tool_definitions() and registers via _register_custom_tools()
  • CLI/SDK backends (LLMBackend subclasses like Codex, Claude Code): must do this explicitly in __init__, then wrap as MCP server (see §6.4)

Important: Always use get_multimodal_tool_definitions() — never inline the tool dicts. This keeps the definitions in one place.

6.3 CLI/SDK Wrappers — MCP Servers

These backends must configure the CLI/SDK's own MCP system:

Codex: Write project-scoped .codex/config.toml in the workspace (-C dir). Codex reads this automatically. Convert MassGen's mcp_servers list to TOML format:

[mcp_servers.filesystem]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/workspace"]

Claude Code: Pass mcp_servers dict directly to SDK options. The SDK handles server lifecycle:

options = {"mcp_servers": {"filesystem": {"command": "npx", "args": [...]}}}
6.4 CLI/SDK Wrappers — Custom Tools

Custom tools need special handling since the LLM runs inside an external process:

Preferred: Wrap as MCP server (what claude_code.py does):

  1. Load custom tools via ToolManager (schemas + executors)
  2. Create an MCP server that exposes each tool
  3. Register the MCP server with the CLI/SDK
  4. When the LLM calls the MCP tool, the wrapper executes via ToolManager
# claude_code.py pattern (simplified)
def _create_sdk_mcp_server_from_custom_tools(self):
    tool_schemas = self._custom_tool_manager.fetch_tool_schemas()
    mcp_tools = []
    for schema in tool_schemas:
        name = schema["function"]["name"]
        async def wrapper(args, tool_name=name):
            return await self._execute_massgen_custom_tool(tool_name, args)
        mcp_tools.append(tool(name=name, ...)(wrapper))
    return create_sdk_mcp_server(name="massgen_custom_tools", tools=mcp_tools)

For CLI wrappers without SDK MCP (like Codex): Use the shared massgen/mcp_tools/custom_tools_server.py utility. It creates a standalone fastmcp server that wraps ToolManager tools via stdio transport.

from ..mcp_tools.custom_tools_server import build_server_config, write_tool_specs

def _setup_custom_tools_mcp(self, custom_tools):
    # 1. Write tool specs JSON to workspace
    specs_path = Path(self.cwd) / ".codex" / "custom_tool_specs.json"
    write_tool_specs(custom_tools, specs_path)

    # 2. Get MCP server config (fastmcp run ... --tool-specs ...)
    server_config = build_server_config(
        tool_specs_path=specs_path,
        allowed_paths=[self.cwd],
        agent_id="my_backend",
    )

    # 3. Add to mcp_servers list (written to workspace config before launch)
    self.mcp_servers.append(server_config)

The server is launched by the CLI as a subprocess and connects via stdio. Cleanup the specs file on reset_state().

Reference: codex.py uses this pattern. custom_tools_server.py also provides build_server_config() which returns a ready-to-use MCP server dict.

Fallback: System prompt injection

  • Describe tools as JSON schema in the system prompt
  • Parse structured output (JSON blocks) for tool calls
  • Only use when MCP wrapping isn't feasible
6.5 Custom Tool YAML Config
backend:
  type: your_backend
  custom_tools:
    - path: "massgen/tool/_basic"          # Directory with TOOL.md
      function: "two_num_tool"
    - path: "path/to/tool.py"             # Single file
      function: ["func_a", "func_b"]
      preset_args: [{"timeout": 30}, {}]
  custom_tools_path: "massgen/tool/"      # Auto-discover from directory
  auto_discover_custom_tools: true        # Discover from registry

MassGen workflow tools (new_answer, vote, etc.): Always injected via system prompt — these are coordination-level, not executable tools. See §6.7 for full details.

6.7 Workflow Tool Integration (vote, new_answer, etc.)

Workflow tools are NOT native function-calling tools — they're injected into the system prompt and parsed from the model's text output. This pattern is shared between Claude Code and Codex backends.

Shared helpers in massgen/backend/base.py:

from .base import build_workflow_instructions, parse_workflow_tool_calls, extract_structured_response

# build_workflow_instructions(tools) → str
#   Filters tools to workflow tools, returns instruction text with usage examples.
#   Returns "" if no workflow tools present.

# parse_workflow_tool_calls(text) → List[Dict]
#   Extracts JSON tool calls from text output.
#   Returns standard format: {id, type, function: {name, arguments}}

# extract_structured_response(text) → Optional[Dict]
#   Low-level: extracts {"tool_name": "...", "arguments": {...}} from text.
#   Tries: ```json blocks → regex → brace-matching → line-by-line.

For API backends: Workflow tools are passed as normal function tools — no injection needed.

For CLI/SDK backends (Codex, Claude Code): The model can't receive native function tool definitions, so:

  1. Build instructions: Call build_workflow_instructions(tools) to get the instruction text
  2. Inject into system prompt: Append to whatever mechanism the backend uses for system prompts
  3. Accumulate text output: Track all content chunks during streaming
  4. Parse after streaming: Call parse_workflow_tool_calls(accumulated_text) to extract tool calls
  5. Yield as done chunk: yield StreamChunk(type="done", tool_calls=workflow_tool_calls)

Codex-specific: Instructions go into AGENTS.md at the workspace root (Codex auto-reads this). The orchestrator's system message is also extracted from messages and included, since Codex only receives a single user prompt via CLI — the system message from the orchestrator would otherwise be lost. This approach was utilized as the developer instructions approach wasn't working.

Claude Code-specific: Instructions are built by _build_system_prompt_with_workflow_tools() which also adds tool calling sections, then passed as system_prompt to the SDK.

It is an open question as to whether typical workflow tool parsing works (e.g., Claude Code) or if we need to use MCP tools (e.g., Codex).

6.7.1 MCP-Based vs Text-Based Workflow Tools

When deciding between MCP-based and text-based workflow tools for CLI/SDK backends:

MCP-based approach (attempted but not always reliable):

  • Register workflow tools as an MCP server
  • Pass to the SDK/CLI's MCP system
  • Caveat: MCP tool naming varies by SDK. Claude Code prefixes with mcp__{server_name}__: # If server is "massgen_workflow_tools", tool names become: # "new_answer" → "mcp__massgen_workflow_tools__new_answer" # "vote" → "mcp__massgen_workflow_tools__vote"
  • When using MCP workflow tools, use build_workflow_mcp_instructions() with the appropriate prefix: instructions = build_workflow_mcp_instructions(tools, mcp_prefix="mcp__massgen_workflow_tools__")

Text-based approach (current fallback for Claude Code):

  • Inject workflow tool instructions into system prompt
  • Parse JSON tool calls from model's text output using parse_workflow_tool_calls()
  • More reliable but requires robust parsing

Current status: Claude Code uses text-based workflow tools (JSON parsing) because MCP-based approach was unreliable. Codex uses text-based as well via AGENTS.md instructions.

6.6 Provider-Native Tools: Keep vs. Override

CLI/SDK-based agents (Codex, Claude Code) come with their own built-in tools (file editing, shell execution, web search, sub-agents, etc.). When integrating, decide which to keep and which to override with MassGen equivalents. Document these decisions in get_tool_category_overrides() on the NativeToolBackendMixin — see §6.8 and Phase 10.2 for details.

General rule: Prefer the provider's native tools unless MassGen has a specific reason to override. Native tools are optimized for the provider's model and avoid extra MCP overhead.

Override when MassGen adds value:

  • Sub-agents/Task tools: Override with MassGen's sub-agents — theirs can't participate in MassGen coordination (voting, consensus, intelligence sharing)
  • Filesystem tools: May override if MassGen needs path permission enforcement or workspace isolation beyond what the provider offers

Keep provider-native:

  • File read/write/edit: Provider tools are model-optimized
  • Shell/command execution: Provider sandboxing is already configured
  • Web search: Provider integration is usually seamless

Implementation: Use the provider's tool filtering mechanism to disable specific tools:

# Codex: via .codex/config.toml
[mcp_servers.some_server]
disabled_tools = ["task", "sub_agent"]

# Claude Code: via SDK disallowed_tools param
all_params["disallowed_tools"] = [
    "Read", "Write", "Edit", "MultiEdit",  # Use MassGen's MCP filesystem
    "Bash", "BashOutput", "KillShell",     # Use MassGen's execute_command
    "LS", "Grep", "Glob",                  # Use MassGen's filesystem tools
    "TodoWrite",                            # MassGen has its own task tracking
    "NotebookEdit", "NotebookRead",
    "ExitPlanMode",
    # Security restrictions
    "Bash(rm*)", "Bash(sudo*)", "Bash(su*)", "Bash(chmod*)", "Bash(chown*)",
]
# Conditionally keep web tools:
if not enable_web_search:
    disallowed_tools.extend(["WebSearch", "WebFetch"])

Key patterns:

  • Claude Code SDK supports glob patterns for Bash restrictions: "Bash(rm*)", "Bash(sudo*)"
  • Check if "disallowed_tools" not in all_params to allow user override via YAML config
  • Codex uses disabled_tools per MCP server in .codex/config.toml; for built-in tools, Codex doesn't have a disable mechanism — use --full-auto to auto-approve instead

Document in capabilities.py which native tools the backend provides:

builtin_tools=["file_edit", "shell", "web_search", "sub_agent"],
notes="Native tools: file ops, shell, web search, sub-agents. Override sub-agents with MassGen's."
6.8 NativeToolBackendMixin

File: massgen/backend/native_tool_mixin.py

For backends with built-in tools (CLI/SDK wrappers), use NativeToolBackendMixin to standardize tool filtering and hook integration:

from .native_tool_mixin import NativeToolBackendMixin

class YourBackend(NativeToolBackendMixin, LLMBackend):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.__init_native_tool_mixin__()
        # Optional: initialize hook adapter
        self._init_native_hook_adapter(
            "massgen.mcp_tools.native_hook_adapters.YourBackendAdapter"
        )

    def get_disallowed_tools(self, config):
        """Return native tools to disable (MassGen has equivalents)."""
        return ["NativeTool1", "NativeTool2"]

Mixin provides:

MethodPurpose
get_disallowed_tools(config)Abstract — declare which native tools to disable
get_tool_category_overrides()Abstract — declare which MCP categories to skip/override
supports_native_hooks()Check if hook adapter is available
get_native_hook_adapter()Get the adapter instance
set_native_hooks_config(config)Set MassGen hooks in native format
_init_native_hook_adapter(path)Initialize adapter by import path

Reference implementations:

  • claude_code.py — disables most native tools (Read, Write, Bash, etc.) in favor of MassGen MCP
  • codex.py — keeps all native tools (MassGen skips attaching MCP equivalents instead)

Phase 7: Testing (2+ files)

7.1 Capabilities Test

Automatically tested by massgen/tests/test_backend_capabilities.py once you add to capabilities.py.

uv run pytest massgen/tests/test_backend_capabilities.py -v
7.2 Integration Test

Create: massgen/tests/test_<name>_integration.py or add to cross-backend test scripts.

Cross-backend test pattern:

BACKEND_CONFIGS = {
    "claude": {"type": "claude", "model": "claude-haiku-4-5-20251001"},
    "openai": {"type": "openai", "model": "gpt-4o-mini"},
    "your_backend": {"type": "your_backend", "model": "model-a"},
}
7.3 Hook Firing Test (CLI/SDK backends) ⚠️ REQUIRED

Script: scripts/test_hook_backends.py

This is mandatory for every new CLI/SDK backend. The script verifies that the full hook pipeline actually fires during real streaming — not just that the hook data structures are correct.

Two modes:

Unit mode (no API calls — runs in CI):

uv run python scripts/test_hook_backends.py --backend your_backend

Verifies: backend stores GeneralHookManager, MidStreamInjectionHook returns injection content, HighPriorityTaskReminderHook fires, combined hooks aggregate correctly.

E2E mode (real API calls):

uv run python scripts/test_hook_backends.py --backend your_backend --e2e
uv run python scripts/test_hook_backends.py --backend your_backend --e2e --verbose

Verifies the complete live flow: PreToolUse hook fires → tool executes → PostToolUse hook fires → injection content is fed back to the model and acknowledged.

Adding your backend: Add an entry to BACKEND_CONFIGS in the script:

"your_backend": {
    "type": "your_backend",
    "model": "your-model",
    "description": "Your Backend description",
    "api_style": "openai",  # or "anthropic", "gemini"
},

Currently covered: claude, openai, gemini (native SDK), openrouter, grok Not yet covered: codex, claude_code, copilot, gemini_cli — these use file-based IPC or SDK-native hooks and need separate E2E hook verification.

Why this matters: Unit tests verify that hook data structures are correct. This script verifies that hooks actually fire during a real streaming turn. A backend can pass all unit tests and still silently drop hooks during live execution.

7.4 Sandbox / Path Permission Test (CLI/SDK backends) ⚠️ REQUIRED

Script: scripts/test_native_tools_sandbox.py

This is mandatory for every new CLI/SDK backend with built-in file/shell tools. It runs real agents against a real filesystem with unique secrets and verifies that permission boundaries are actually enforced — not just that the enforcement code exists.

# Test your new backend
uv run python scripts/test_native_tools_sandbox.py --backend your_backend

# Use LLM judge to detect subtle leakage
uv run python scripts/test_native_tools_sandbox.py --backend your_backend --llm-judge

The script verifies the full permission matrix:

ZoneExpected readsExpected writes
Workspace (cwd)✅ allowed✅ allowed
Writable context path✅ allowed✅ allowed
Read-only context path✅ allowed❌ blocked
Outside all contextsdepends on backend❌ blocked
Parent directorydepends on backend❌ blocked
/tmp✅ alloweddepends on backend

It uses unique secrets (UUIDs written to each zone's files) to detect unauthorized reads even when the operation "fails" — if the secret string appears in the model's response, there's a leak regardless of error messages.

Adding your backend: Add an entry to BACKEND_CONFIGS in the script:

"your_backend": {
    "module": "massgen.backend.your_backend",
    "class": "YourBackend",
    "model": "your-model",
    "blocks_reads_outside": True,   # Does your enforcement block reads?
    "blocks_tmp_writes": True,      # Does your enforcement block /tmp writes?
},

Currently covered: claude_code, codex Not yet covered: copilot, gemini_cli — must be added when those backends are used in production.

Why this matters: Permission callback and hook unit tests verify the enforcement logic in isolation. This script verifies that enforcement actually stops a live agent from accessing restricted paths. A backend can have correct hook logic and still allow unauthorized access if the hook isn't wired into the right execution path.

7.5 Config Validation
uv run python scripts/validate_all_configs.py

Phase 8: Config Examples (2+ files)

8.1 Single Agent

Create: massgen/configs/providers/<name>/single_<name>.yaml

8.2 Multi-Agent / Tools

Create: massgen/configs/providers/<name>/<name>_with_tools.yaml

Phase 9: Documentation (3+ files)

9.1 YAML Schema

File: docs/source/reference/yaml_schema.rst — document backend-specific params

9.2 Backend Tables
uv run python docs/scripts/generate_backend_tables.py
9.3 User Guide

File: docs/source/user_guide/backends.rst — add section for new backend

Phase 10: System Prompt Considerations

The system prompt is assembled by massgen/system_message_builder.py using priority-based sections from massgen/system_prompt_sections.py. Different sections are conditionally included based on backend capabilities and config flags.

10.1 Section Categories

Always included (all backends):

SectionPurpose
AgentIdentitySectionWHO the agent is
EvaluationSectionvote/new_answer coordination primitives
CoreBehaviorsSectionAction bias, parallel execution
OutputFirstVerificationSectionQuality iteration loop
SkillsSectionopenskills read via command execution
MemorySectionDecision documentation
WorkspaceStructureSectionWorkspace paths
ProjectInstructionsSectionCLAUDE.md/AGENTS.md
SubagentSectionMassGen subagent delegation
BroadcastCommunicationSectionInter-agent communication
PostEvaluationSectionsubmit/restart
FileSearchSectionrg/sg universal CLI tools
TaskContextSectionCONTEXT.md creation
NoveltyPressureSectionNovelty/diversity pressure across agents
ChangedocSectionChange documentation

Conditional on config flags:

SectionGate
TaskPlanningSectionenable_task_planning=True
EvolvingSkillsSectionauto_discover_custom_tools=True AND enable_task_planning=True
PlanningModeSectionplanning_mode_enabled=True
CodeBasedToolsSectionenable_code_based_tools=True (CodeAct paradigm)
CommandExecutionSectionenable_mcp_command_line=True
DecompositionSectionDecomposition mode active
MultimodalToolsSectionenable_multimodal_tools=True

Model-specific:

SectionGate
GPT5GuidanceSectionGPT-5 models only
GrokGuidanceSectionGrok models only

Adapted for native backends:

SectionAdaptation
FilesystemOperationsSectionhas_native_tools=True → generic tool language
FilesystemBestPracticesSectionComparison tool language adjusted
10.2 tool_category_overrides

File: massgen/backend/native_tool_mixin.py

The get_tool_category_overrides() abstract method on NativeToolBackendMixin declares which MassGen tool categories a backend handles natively. Each native backend implements this method:

@abstractmethod
def get_tool_category_overrides(self) -> Dict[str, str]:
    # "skip"     = backend has native equivalent
    # "override" = attach MassGen's version, disable native
    # (absent)   = attach MCP normally

Categories: filesystem, command_execution, file_search, web_search, planning, subagents

Currently used by system_message_builder.py to:

  • Pass has_native_tools=True to filesystem sections when filesystem: "skip"
  • Document which tool categories each backend handles natively

Note: MCP server injection filtering (which MCP servers to attach) is handled individually by each CLI/SDK backend (codex.py, claude_code.py). The get_tool_category_overrides() method serves as documentation and controls system prompt section behavior. Non-mixin backends (API-based) return {} by default via system_message_builder.py's fallback.

10.3 Path Permission Integration

When filesystem: "skip", the backend's native tools handle file ops — but they may not enforce MassGen's granular per-path permissions from PathPermissionManager (PPM). Each backend addresses this differently:

Two-layer defense (recommended for SDK backends with permission callbacks):

  1. Layer 1 — Permission callback (coarse gate): Extract paths from the SDK's permission request, validate against PPM. Fail-open if no path extractable (defer to Layer 2).
  2. Layer 2 — PreToolUse hook (fine-grained): The orchestrator auto-registers PathPermissionManagerHook as PRE_TOOL_USE for non-Claude-Code native backends. Full toolName/toolArgs available for precise validation.

Backend-specific approaches:

BackendPPM Strategy
Claude CodeOwn add_dirs sandboxing — PPM hook skipped by orchestrator
CopilotTwo-layer defense (permission callback + PPM PreToolUse hook). In Docker mode, container provides isolation + PPM as defense-in-depth
CodexNo native hook support — relies on Docker/workspace isolation
API backendsPPM enforced via ToolManager automatically

Reference: copilot.py (_build_permission_callback) and orchestrator.py (_setup_native_hooks_for_agent) for the two-layer pattern. See massgen/filesystem_manager/_path_permission_manager.py for PPM internals.

Phase 11: Hooks

MassGen supports hooks for intercepting tool execution and other lifecycle events. Hooks run transparently (not documented in the system prompt).

Note that some backends may not support hooks (e.g., Codex). In this case, hooks will only be applied where possible within MassGen's tool execution framework.

11.1 Hook Types and Built-in Hooks

Hook types (HookType enum in massgen/mcp_tools/hooks.py):

HookTypeTrigger
PRE_TOOL_USEBefore tool execution
POST_TOOL_USEAfter tool execution

Built-in hook classes (PatternHook subclasses — registered by the orchestrator):

Hook ClassTypePurpose
PathPermissionManagerHookPreToolUseEnforce per-path read/write permissions (in _path_permission_manager.py)
RoundTimeoutPreHookPreToolUseEnforce round time limits
HumanInputHookPreToolUseInject human input into agent flow
MidStreamInjectionHookPostToolUseInject coordination messages (voting reminders, etc.)
SubagentCompleteHookPostToolUseNotify when subagent completes
BackgroundToolCompleteHookPostToolUseNotify when background tool completes
HighPriorityTaskReminderHookPostToolUseRemind agent of current task
MediaCallLedgerHookPostToolUseTrack media generation calls
RoundTimeoutPostHookPostToolUseEnforce round time limits
11.2 Hook Architecture
GeneralHookManager (massgen/mcp_tools/hooks/)
    ├── Registers global and per-agent hooks
    ├── Executes hooks in order for MCP-based backends
    └── For native backends → NativeHookAdapter
            ├── ClaudeCodeNativeHookAdapter
            │   └── Converts to Claude Agent SDK HookMatcher format
            └── (future) CodexNativeHookAdapter
11.3 Native Hook Adapters — How to Implement

For backends with native tool execution (CLI/SDK wrappers), MassGen hooks need to be bridged into the backend's hook system. This is done via NativeHookAdapter (base class in massgen/mcp_tools/native_hook_adapters/base.py).

Step 1: Create adapter subclass:

# massgen/mcp_tools/native_hook_adapters/your_backend_adapter.py
from .base import NativeHookAdapter

class YourBackendNativeHookAdapter(NativeHookAdapter):
    def supports_hook_type(self, hook_type):
        return hook_type in (HookType.PRE_TOOL_USE, HookType.POST_TOOL_USE)

    def convert_hook_to_native(self, hook, hook_type, context_factory=None):
        """Wrap MassGen hook as your backend's native hook format."""
        async def native_hook(tool_name, tool_args, context):
            event = self.create_hook_event_from_native(
                {"tool_name": tool_name, "tool_input": tool_args},
                hook_type, context_factory() if context_factory else {},
            )
            result = await hook.execute(event)
            return self.convert_hook_result_to_native(result, hook_type)
        return {"pattern": hook.matcher, "handler": native_hook}

    def build_native_hooks_config(self, hook_manager, agent_id=None, context_factory=None):
        """Convert all registered hooks to native config."""
        config = {"PreToolUse": [], "PostToolUse": []}
        for hook_type, hooks in hook_manager.get_hooks(agent_id).items():
            for hook in hooks:
                native = self.convert_hook_to_native(hook, hook_type, context_factory)
                config[hook_type.value].append(native)
        return config

    def merge_native_configs(self, *configs):
        """Merge permission hooks + MassGen hooks + user hooks."""
        merged = {"PreToolUse": [], "PostToolUse": []}
        for config in configs:
            for key in merged:
                merged[key].extend(config.get(key, []))
        return merged

Step 2: Initialize in backend __init__:

from ..mcp_tools.native_hook_adapters import YourBackendNativeHookAdapter
self._native_hook_adapter = YourBackendNativeHookAdapter()

Step 3: Implement the backend interface methods:

def supports_native_hooks(self) -> bool:
    return self._native_hook_adapter is not None

def get_native_hook_adapter(self):
    return self._native_hook_adapter

def set_native_hooks_config(self, config):
    self._massgen_hooks_config = config

Step 4: Merge hooks when launching the backend process. The orchestrator calls set_native_hooks_config() with converted hooks; your backend merges with its own permission hooks when building options.

11.4 Reference
  • Hook framework: massgen/mcp_tools/hooks/
  • Adapter base: massgen/mcp_tools/native_hook_adapters/base.py
  • Claude Code adapter: massgen/mcp_tools/native_hook_adapters/claude_code_adapter.py
  • Copilot adapter: massgen/mcp_tools/native_hook_adapters/copilot_adapter.py
  • Path permissions: massgen/filesystem_manager/_path_permission_manager.py
  • Orchestrator hook setup: massgen/orchestrator.py (search for native_hook)

Common Patterns

CLI Wrapper Backend (like Codex)

__init__: find CLI binary, set config defaults
stream_with_tools: build command -> spawn subprocess -> parse JSONL stdout -> yield StreamChunks
MCP: write project-scoped config file in workspace before launch
Custom tools: wrap as MCP server or inject via system prompt
Cleanup: remove workspace config on reset_state/clear_history
Docker Execution for CLI Backends

If a CLI-based backend doesn't support Docker natively, run the CLI inside the MassGen container:

  1. Install the CLI in the Docker image (add to npm install -g in Dockerfile) or via command_line_docker_packages.preinstall.npm
  2. In __init__, detect command_line_execution_mode: "docker" and skip host CLI lookup
  3. In stream_with_tools, use container.client.api.exec_create() + exec_start(stream=True) to run the CLI inside the container
  4. If the CLI has its own sandbox, disable it — the container provides isolation
  5. If the CLI needs host credentials, mount them read-only via _build_credential_mounts()

IMPORTANT: Some CLI backends require command_line_docker_network_mode: bridge when running in Docker mode. This allows the container to make outbound network requests to APIs. Add config validation to enforce this:

# In config_validator.py
if backend_type == "your_backend":
    execution_mode = backend_config.get("command_line_execution_mode")
    if execution_mode == "docker":
        if "command_line_docker_network_mode" not in backend_config:
            result.add_error(
                "YourBackend in Docker mode requires 'command_line_docker_network_mode'",
                f"{location}.command_line_docker_network_mode",
                "Add 'command_line_docker_network_mode: bridge' (required for network access)",
            )

Reference: codex.py implements this pattern with _stream_docker() / _stream_local() branching.

Docker Execution for SDK Backends (like Copilot)

SDK-based backends (in-process Python clients) cannot run inside Docker — the SDK stays on host. Instead, Docker isolates file/shell operations by:

  1. Disable built-in tools in Docker mode via excluded_tools so the SDK doesn't use its native file/shell tools
  2. Route all file/shell ops through MCP servers that execute inside the Docker container
  3. Point working_directory to the Docker-mounted workspace path
# In __init__:
self._docker_execution = (
    kwargs.get("command_line_execution_mode") == "docker"
    or self.config.get("command_line_execution_mode") == "docker"
)

# Property to check if Docker is actually active:
@property
def _is_docker_mode(self) -> bool:
    if not self._docker_execution:
        return False
    if not self.filesystem_manager:
        return False
    dm = getattr(self.filesystem_manager, "docker_manager", None)
    if dm is None:
        return False
    agent_id = self.config.get("agent_id")
    if agent_id and dm.get_container(agent_id):
        return True
    return False

# In get_disallowed_tools():
def get_disallowed_tools(self, config):
    if self._docker_execution:
        return ["editFile", "createFile", "deleteFile",
                "readFile", "listDirectory",
                "runShellCommand", "shellCommand"]
    return []

# In stream_with_tools(), merge Docker-excluded tools into session config:
if self._docker_execution:
    docker_excluded = self.get_disallowed_tools(self.config)
    if docker_excluded:
        excluded_tools = list(set((excluded_tools or []) + docker_excluded))

Key differences from CLI Docker pattern:

  • SDK stays on host (no exec_create / exec_start)
  • Built-in tools disabled via SDK session config (excluded_tools), not by running inside container
  • MCP servers still execute inside container (same as CLI pattern)
  • PPM permission callback still active as defense-in-depth

Config validation: Same pattern — require command_line_docker_network_mode:

if backend_type == "copilot":
    execution_mode = backend_config.get("command_line_execution_mode")
    if execution_mode == "docker":
        if "command_line_docker_network_mode" not in backend_config:
            result.add_error(...)

Reference: copilot.py implements this pattern.

Docker MCP Path Resolution

MCP server configs are built by the orchestrator on the host with absolute host file paths (e.g., fastmcp run /host/path/massgen/mcp_tools/planning/_server.py:create_server). Inside Docker, these paths don't exist unless explicitly mounted.

Solution: _docker_manager.py bind-mounts the massgen/ package directory into the container at the same host path (read-only). This makes host-path-based MCP configs work as-is inside the container, using the latest source from the host rather than stale pip-installed modules.

Shell Sandboxing for Backends with Native Tools

This section applies only to backends that bring their own shell/file tools (e.g., CLI wrappers with built-in command execution). If a backend delegates all tool execution to MassGen's MCP servers, MassGen's PathPermissionManager handles sandboxing automatically.

When the backend has its own tools that can access the filesystem or run commands, you must map MassGen's permission model to the backend's sandbox mechanism:

MassGen conceptExpected access
WorkspaceWrite
Temp workspacesRead-only
Read context pathsRead-only
Write context pathsWrite — must be explicitly granted in backend sandbox config

The workspace is typically writable by default. Read access to the full filesystem is usually allowed. The key task is ensuring write context paths are added to the backend's writable allowlist (e.g., sandbox_workspace_write.writable_roots for Codex, allowed_directories for Claude Code).

Docker mode: Skip backend sandbox config — the container IS the sandbox. Grant full access inside the container.

SDK Wrapper Backend (like Claude Code, Copilot)

__init__: import SDK, configure options, detect Docker mode
stream_with_tools: call SDK with messages -> iterate events -> yield StreamChunks
MCP: pass mcp_servers dict to SDK options
Custom tools: create SDK MCP server from tool definitions
State: SDK manages conversation state internally
Docker: SDK stays on host; disable built-in file/shell tools via excluded_tools;
        route file/shell ops through MCP servers in container (see §Docker Execution for SDK Backends)

API Backend (like Claude, Gemini)

Subclass CustomToolAndMCPBackend or ChatCompletionsBackend
Implement formatter if non-standard API format
Implement API params handler to filter/transform config -> API params
MCP + custom tools handled automatically by base class

Reference Backends by Complexity

BackendLinesTypeGood reference for
grok.py~81Subclass of ChatCompletionsMinimal API backend
chat_completions.py~1150OpenAI-compatibleStandard API backend
response.py~1600Response APIReasoning models
claude.py~1830Custom APIFull-featured API
copilot.py~1250SDK wrapperSDK-based + PPM permission callback + Docker mode
codex.py~2090CLI wrapperCLI-based + Docker
gemini.py~2460Custom APINon-OpenAI API
claude_code.py~3530SDK wrapperFull-featured stateful

File Summary

#FileRequired?Purpose
1massgen/backend/<name>.pyYesCore backend
2massgen/formatter/<name>_formatter.pyIf non-standard APIMessage/tool formatting
3massgen/api_params_handler/<name>_handler.pyIf HTTP APIParam filtering
4massgen/backend/__init__.pyYesExport
5massgen/cli.pyYesBackend creation
6massgen/backend/capabilities.pyYesModel registry
7massgen/config_validator.pyIf special rulesValidation
8massgen/token_manager/token_manager.pyIf not in LiteLLMPricing
9massgen/backend/base.pyIf new YAML paramsExcluded params
10massgen/api_params_handler/_base.pyIf new YAML paramsExcluded params
11massgen/tests/test_*YesTests
12massgen/configs/providers/<name>/YesExample configs
13docs/source/reference/yaml_schema.rstYesSchema docs
14docs/source/user_guide/backends.rstYesUser guide
15docs/scripts/generate_backend_tables.pyRun itRegenerate tables

平台分布

Codex

34.53%
按下载量换算86

Claude

27.82%
按下载量换算69

Cursor

19.06%
按下载量换算47

Gemini CLI

9.43%
按下载量换算23

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

可疑

权限和风险

接触敏感数据

该 Skill 可能接触密钥、Token、环境变量或敏感配置,应进入高风险复核队列,默认不自动发布。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在提醒或未通过项,安装前请自行复核。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills