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
SkillsMiddleware accepts a custom `system_prompt` as a str or None; anything else (e.g. a list of prompt parts, a ChatPromptTemplate, bytes) is rejected with TypeError. String prompts are additionally checked for required format slots, so non-string composite prompt objects must be converted to a str first.
Source
Thrown at libs/deepagents/deepagents/middleware/skills.py:841
are rendered as `**{label} Skills**` in the system prompt
(do not include the trailing `Skills` in your label).
system_prompt: System-prompt fragment template. Must contain
`{skills_locations}`, `{skills_load_warnings}`, and
`{skills_list}` slots for runtime substitution. Pass `None`
to skip appending entirely (skills are still loaded into
`state["skills_metadata"]`).
Raises:
TypeError: If a tuple entry in `sources` is not exactly a
`(str, str)` pair, or if `system_prompt` is not `str` or
`None`.
ValueError: If `system_prompt` is a string missing any of the
required format slots.
"""
if system_prompt is not None:
if not isinstance(system_prompt, str):
msg = f"system_prompt must be str or None, got {type(system_prompt).__name__}"
raise TypeError(msg)
required = ("{skills_locations}", "{skills_load_warnings}", "{skills_list}")
missing = [slot for slot in required if slot not in system_prompt]
if missing:
msg = f"system_prompt missing required format slot(s): {', '.join(missing)}"
raise ValueError(msg)
self._backend = backend
# `self.sources` remains paths-only (`list[str]`) to preserve
# backwards-compat for callers that inspect it directly; label
# information is mirrored on `self.source_labels` at the same index.
self.sources: list[str] = [_source_path(s) for s in sources]
self.source_labels: list[str] = [_derive_source_label(s) for s in sources]
self.system_prompt_template = system_prompt
def _format_skills_locations(self) -> str:
"""Format skills locations for display in system prompt."""
locations = []
last = len(self.sources) - 1
View on GitHub (pinned to a1af029e6e)
Solutions
- Convert to str: system_prompt="\n".join(parts) or str(template.invoke({})).
- Pass None to use the default system prompt.
- If composing dynamically, render the final template into a string before constructing.
- Use only the three supported slots {skills_locations}, {skills_load_warnings}, {skills_list} when customizing.
Example fix
// before system_prompt=[intro, instructions] // after system_prompt="\n\n".join([intro, instructions])
Defensive patterns
Strategy: type-guard
Validate before calling
sp = system_prompt
if sp is not None and not isinstance(sp, str):
sp = "\n".join(sp) if isinstance(sp, list) else str(sp) Type guard
def is_valid_system_prompt(v: object) -> TypeGuard[str | None]:
return v is None or isinstance(v, str) Try / catch
try:
mw = SkillsMiddleware(backend=b, system_prompt=system_prompt)
except TypeError as e:
if "system_prompt must be str or None" in str(e):
mw = SkillsMiddleware(backend=b, system_prompt=str(system_prompt))
else:
raise Prevention
- Render templates/lists to a single str before passing.
- Pass None to use the built-in default prompt.
- Type-annotate system_prompt: str | None at call sites.
- Don't pass LangChain prompt objects directly to the middleware.
When it happens
Trigger: SkillsMiddleware(backend=..., system_prompt=["part1", "part2"]) or passing a LangChain prompt template / ChatPromptTemplate object instead of a rendered string.
Common situations: Building the prompt programmatically as a list and forgetting to join; passing an f-string pipeline object; refactoring from another middleware that accepted templates.
Related errors
- Invalid skill source: expected str or (str, str) tuple, got
- interpreter_ptc must be False, 'safe', 'all', or a list of t
- max_retries must be an int, got {type(max_retries).__name__}
- stream_output_is_visible must be a bool, got {type(stream_ou
- context.{key} must be a string or null, got {type(value).__n
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/199f06665fc3e271.
Report an issue: GitHub.