langchain-ai/deepagents · error · ValueError

HarnessProfileConfig.from_harness_profile() cannot export `e

Error message

HarnessProfileConfig.from_harness_profile() cannot export `extra_middleware`. Middleware instances and factories are runtime-only; keep them in `HarnessProfile`.

What it means

HarnessProfileConfig is the serializable form of a profile, and middleware instances/factories are runtime-only objects that cannot be serialized. from_harness_profile() refuses to export a non-empty extra_middleware so callers do not silently lose middleware during conversion. Such middleware must remain on the HarnessProfile itself.

Source

Thrown at libs/deepagents/deepagents/profiles/harness/harness_profiles.py:467

        Returns:
            A declarative `HarnessProfileConfig`.

        Raises:
            ValueError: If `profile` contains runtime-only state such as
                non-empty `extra_middleware`, or if a class-form
                `excluded_middleware` entry has no `serialized_name` alias.
            TypeError: If `tool_description_overrides` contains a non-string
                key or value.
        """
        extra = profile.extra_middleware
        if callable(extra) or (isinstance(extra, tuple) and extra):
            msg = (
                "HarnessProfileConfig.from_harness_profile() cannot export "
                "`extra_middleware`. Middleware instances and factories are "
                "runtime-only; keep them in `HarnessProfile`."
            )
            raise ValueError(msg)

        return cls(
            base_system_prompt=profile.base_system_prompt,
            system_prompt_suffix=profile.system_prompt_suffix,
            tool_description_overrides=_coerce_str_mapping(
                dict(profile.tool_description_overrides),
                "tool_description_overrides",
            ),
            excluded_tools=profile.excluded_tools,
            excluded_middleware=frozenset(_serialize_runtime_excluded_middleware_entry(entry) for entry in profile.excluded_middleware),
            general_purpose_subagent=profile.general_purpose_subagent,
        )


@dataclass(frozen=True)
class HarnessProfile:
    """Runtime configuration for deep agent behavior.

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Strip extra_middleware from the HarnessProfile (set it to an empty list) before converting, or convert an equivalent profile built without it.
  2. Persist middleware separately — e.g. store a string identifier and rebuild the middleware instance on load.
  3. Use HarnessProfileConfig.from_dict/to_dict with only serializable fields, keeping runtime middleware in code.

Example fix

// before
config = HarnessProfileConfig.from_harness_profile(profile_with_extra_middleware)
// after
bare = replace(profile_with_extra_middleware, extra_middleware=[])
config = HarnessProfileConfig.from_harness_profile(bare)
Defensive patterns

Strategy: validation

Validate before calling

if getattr(profile, 'extra_middleware', None):
    raise ValueError("Profile has runtime extra_middleware; strip before exporting to HarnessProfileConfig")
config = HarnessProfileConfig.from_harness_profile(profile)

Try / catch

try:
    config = HarnessProfileConfig.from_harness_profile(profile)
except ValueError as e:
    if "cannot export" in str(e):
        config = HarnessProfileConfig.from_harness_profile(replace(profile, extra_middleware=[]))
    else:
        raise

Prevention

When it happens

Trigger: Calling HarnessProfileConfig.from_harness_profile(profile) when profile.extra_middleware contains a middleware instance, a non-empty tuple entry, or a callable factory.

Common situations: Trying to serialize a HarnessProfile that has extra middleware registered (e.g. custom auth or logging middleware) into a dict/JSON for persistence or transmission.

Related errors


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