langchain-ai/deepagents · error · FleetImportError

{source}: {_display_path(path)}: malformed tools.json: expec

Error message

{source}: {_display_path(path)}: malformed tools.json: expected tools list

What it means

FleetImportError raised by _load_tool_requests while parsing a tools.json for fleet MCP import. The file was valid JSON and a valid object, but its top-level 'tools' key is missing or not a list. The library requires an explicit JSON array of tool request objects.

Source

Thrown at libs/talon/deepagents_talon/fleet_import.py:366


def _load_tool_requests(path: Path, scope: str, source: Path) -> list[_ToolRequest]:
    try:
        data = json.loads(path.read_text(encoding="utf-8"))
    except json.JSONDecodeError as exc:
        msg = f"{source}: {_display_path(path)}: malformed tools.json: {exc.msg}"
        raise FleetImportError(msg) from exc
    except OSError as exc:
        msg = f"{source}: {_display_path(path)}: {exc}"
        raise FleetImportError(msg) from exc
    if not isinstance(data, dict):
        msg = f"{source}: {_display_path(path)}: malformed tools.json: expected object"
        raise FleetImportError(msg)

    raw_tools = data.get("tools")
    if not isinstance(raw_tools, list):
        msg = f"{source}: {_display_path(path)}: malformed tools.json: expected tools list"
        raise FleetImportError(msg)
    interrupt_config = data.get("interrupt_config")
    interrupts = interrupt_config if isinstance(interrupt_config, dict) else {}

    requests: list[_ToolRequest] = []
    for index, item in enumerate(raw_tools):
        if not isinstance(item, dict):
            msg = f"{source}: {_display_path(path)}: tools[{index}] must be an object"
            raise FleetImportError(msg)
        tool = cast("Mapping[str, object]", item)
        name = _required_str(tool, "name", path, index, source)
        server_url = _sanitize_server_url(
            _required_str(tool, "mcp_server_url", path, index, source)
        )
        server_name = _required_str(tool, "mcp_server_name", path, index, source)
        requests.append(
            _ToolRequest(
                name=name,
                server_url=server_url,

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Open the tools.json at the displayed path and add a top-level 'tools' key containing a JSON array
  2. If the file is a different schema version, regenerate it with the matching fleet export tooling
  3. Validate the JSON structure with a schema check before importing

Example fix

// before
{"mcpUrl": "https://example.com"}
// after
{"tools": [{"name": "my-tool", "mcp_server_url": "https://example.com", "mcp_server_name": "example"}]}
Defensive patterns

Strategy: validation

Validate before calling

import json
data = json.loads(path.read_text())
if not isinstance(data.get("tools"), list):
    raise ValueError(f"{path}: 'tools' must be a list")

Type guard

def has_tools_list(data: object) -> TypeGuard[dict[str, list[object]]]:
    return isinstance(data, dict) and isinstance(data.get("tools"), list)

Try / catch

try:
    summaries = _mcp_summaries(...)
except FleetImportError as exc:
    logger.error("Invalid fleet tools.json: %s", exc)
    return []

Prevention

When it happens

Trigger: Calling _mcp_summaries/_load_tool_requests on a tools.json whose 'tools' key is absent, set to null, or is a dict/string instead of a JSON array.

Common situations: Hand-edited or partial fleet export files; a tools.json written as a bare object '{"tool": ...}' instead of '{"tools": [...]}'; schema drift between talon versions; truncated/merged config files.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/17f60178629aa6cc. Report an issue: GitHub.