langchain-ai/deepagents · error · TypeError
ptc list entries must be str or BaseTool
Error message
ptc list entries must be str or BaseTool
What it means
Within a list-form `ptc` config, every entry must be either a tool name string or a `BaseTool` instance; any other type raises TypeError. The list must remain unambiguous for name-based allowlisting.
Source
Thrown at libs/partners/quickjs/langchain_quickjs/_ptc.py:97
individual tool invocation.
"""
if isinstance(config, list):
explicit_tools: list[BaseTool] = []
allow_names: set[str] = set()
for entry in config:
if isinstance(entry, BaseTool):
if entry.name == _RESERVED_SUBAGENT_TASK_NAME:
raise ValueError(_TASK_IN_PTC_MSG)
if entry.name != self_tool_name:
explicit_tools.append(entry)
continue
if isinstance(entry, str):
if entry == _RESERVED_SUBAGENT_TASK_NAME:
raise ValueError(_TASK_IN_PTC_MSG)
allow_names.add(entry)
continue
msg = "ptc list entries must be str or BaseTool"
raise TypeError(msg)
selected = [
*explicit_tools,
*[t for t in tools if t.name != self_tool_name and t.name in allow_names],
]
deduped: list[BaseTool] = []
seen_names: set[str] = set()
for tool in selected:
if tool.name in seen_names:
continue
seen_names.add(tool.name)
deduped.append(tool)
selected = deduped
_raise_on_invalid_ptc_tools(selected)
return selected
msg = (
"Unsupported `ptc` config type. "
"Use a list of tool names, list of BaseTool instances, or disable PTC."
)View on GitHub (pinned to a1af029e6e)
Solutions
- Replace the offending entry with the tool's name string or its BaseTool instance
- If passing decorated functions, use the returned BaseTool object, not the raw function
- Normalize heterogeneous input: `[t.name if isinstance(t, BaseTool) else str(t) for t in items]` only for valid items
Example fix
# before
ptc=[my_tool, {"name": "websearch"}]
# after
ptc=[my_tool, "websearch"] Defensive patterns
Strategy: type-guard
Validate before calling
bad = [x for x in ptc_list if not isinstance(x, (str, BaseTool))]
if bad:
raise TypeError(f"ptc entries must be str or BaseTool, got {bad!r}") Type guard
def is_valid_ptc_entry(x: object) -> TypeGuard[Union[str, BaseTool]]:
return isinstance(x, (str, BaseTool)) Try / catch
try:
selected = filter_tools_for_ptc(tools, ptc_list)
except TypeError as e:
if "str or BaseTool" in str(e):
ptc_list = [x.name if isinstance(x, BaseTool) else str(x) for x in ptc_list if isinstance(x, (str, BaseTool))]
selected = filter_tools_for_ptc(tools, ptc_list)
else:
raise Prevention
- Use the BaseTool returned by @tool decorators, not the decorated function
- Normalize configs to strings as early as possible in the load path
- Add runtime type checks where ptc config crosses a serialization boundary (JSON/YAML)
When it happens
Trigger: Passing a ptc list containing e.g. a dict, `None`, a callable, or a tuple — anything that is not `str` or `BaseTool` — to `filter_tools_for_ptc` (via agent `ptc` config).
Common situations: Passing `@tool`-decorated function objects (which are not BaseTool instances) instead of the resulting tool; passing tool-name/description dicts; JSON config values parsed into mixed types.
Understand the failure class
Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.
Related errors
- Unsupported `ptc` config type. Use a list of tool names, lis
- interpreter_ptc must be False, 'safe', 'all', or a list of t
- model_retries must be an int, got {self.model_retries!r}
- cli_max_retries must be None or an int, got {self.cli_max_re
- Goal criteria request must be an object.
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/8cbc0c0f3a1267e6.
Report an issue: GitHub.