langchain-ai/deepagents · error · TypeError

system_prompt must be str or None, got {type(system_prompt).

Error message

system_prompt must be str or None, got {type(system_prompt).__name__}

What it means

The `compact_conversation` tool middleware accepts an optional `system_prompt` that must be a `str` or `None`. Any other type (dict, bytes, list, etc.) is rejected with `TypeError` in `__init__`, guarding against silently coercing invalid prompt values.

Source

Thrown at libs/deepagents/deepagents/middleware/summarization.py:1858

        system_prompt: str | None = None,
    ) -> None:
        """Initialize with a reference to the summarization middleware.

        Args:
            summarization: The `SummarizationMiddleware` instance whose
                summarization engine this tool will delegate to.
            system_prompt: System-prompt fragment nudging the model to call
                `compact_conversation`. Pass `None` to skip appending the
                nudge entirely (the tool remains registered and callable
                but the model is unlikely to discover it without an
                external mention).

        Raises:
            TypeError: If `system_prompt` is not `str` or `None`.
        """
        if system_prompt is not None and not isinstance(system_prompt, str):
            msg = f"system_prompt must be str or None, got {type(system_prompt).__name__}"
            raise TypeError(msg)
        self._summarization = summarization
        self.system_prompt = system_prompt
        self.tools: list[BaseTool] = [self._create_compact_tool()]

    def _create_compact_tool(self) -> BaseTool:
        """Create the `compact_conversation` structured tool.

        Returns:
            A `StructuredTool` with both sync and async implementations.
        """
        from langchain_core.tools import StructuredTool  # noqa: PLC0415

        mw = self

        def sync_compact(runtime: ToolRuntime) -> Command:
            return mw._run_compact(runtime)

        async def async_compact(runtime: ToolRuntime) -> Command:

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Pass a plain string (or omit for the default)
  2. Convert structured prompt configs to a string before construction (join sections)
  3. Validate config-loaded prompt values are strings

Example fix

// before
CompactTool(summarization=mw, system_prompt={"intro": "...", "rules": "..."})
// after
CompactTool(summarization=mw, system_prompt="intro...\nrules...")
Defensive patterns

Strategy: type-guard

Validate before calling

if system_prompt is not None and not isinstance(system_prompt, str):
    system_prompt = "\n".join(str(p) for p in system_prompt.values()) if isinstance(system_prompt, dict) else str(system_prompt)

Type guard

def is_str_or_none(v: object) -> bool:
    return v is None or isinstance(v, str)

Try / catch

try:
    tool_mw = CompactTool(summarization=mw, system_prompt=prompt)
except TypeError as e:
    if "system_prompt" in str(e):
        logger.error("system_prompt must be str or None, got %r", type(prompt))
    raise

Prevention

When it happens

Trigger: Constructing the compact/summarization tool middleware with `system_prompt` set to a non-string value, e.g. a dict of prompt parts or a `None`-like sentinel object.

Common situations: Loading prompts from YAML/JSON where they deserialize to dicts; concatenating prompt fragments into a list; forgetting to `.join()` or `str()` a computed value.

Understand the failure class

Background: "Wrong argument type", "must be a string", "expected Array or Prism::Scope": TypeError and ArgumentError when a library receives a value of the wrong type — 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/50dfadc6ea693fa3. Report an issue: GitHub.