langchain-ai/deepagents · error · TypeError

Goal criteria request must be an object.

Error message

Goal criteria request must be an object.

What it means

`_goal_criteria_request` (a hook used by `before_agent`/`abefore_agent`) parses an incoming goal-criteria request payload and raises `TypeError` if the payload is not a `dict`. It then further validates `request_id`, `kind`, and `objective`, raising `ValueError` for missing/invalid required fields. This guards the tool/hook boundary against malformed requests.

Source

Thrown at libs/code/deepagents_code/goal_rubric.py:1214

        summary = summary[:_CRITERIA_RESULT_LOG_LIMIT] + "..."
    return summary


def _goal_criteria_request(value: object) -> GoalCriteriaRequest:
    """Validate a goal-criteria request from graph input.

    Returns:
        A normalized typed request: a `GoalAmendRequest` when `kind` is amend
        (with `criteria` and `feedback` guaranteed present), otherwise a
        `GoalCreateRequest`. Fields not valid for the resolved kind are dropped.

    Raises:
        TypeError: If the request or one of its fields has the wrong type.
        ValueError: If a required request value is missing or invalid.
    """
    if not isinstance(value, dict):
        msg = "Goal criteria request must be an object."
        raise TypeError(msg)
    request_id = value.get("request_id")
    kind = value.get("kind")
    objective = value.get("objective")
    if not isinstance(request_id, str) or not request_id.strip():
        msg = "Goal criteria request requires a request_id."
        raise ValueError(msg)
    if kind not in {"create", "amend"}:
        msg = "Goal criteria request kind must be create or amend."
        raise ValueError(msg)
    if not isinstance(objective, str) or not objective.strip():
        msg = "Goal criteria request requires an objective."
        raise ValueError(msg)

    # Values are validated for non-blankness but stored verbatim (not stripped):
    # this feature deliberately preserves the user's exact goal/criteria wording,
    # and the prompt builders wrap each value in explicit XML boundaries.
    optional: dict[str, str] = {}
    for key in ("criteria", "feedback", "previous_criteria"):

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Send the request as a JSON object with string `request_id`, valid `kind`, and non-empty `objective`
  2. If receiving a JSON string, `json.loads` it before handing it to the hook
  3. Validate the payload shape at the client boundary before invoking the agent

Example fix

// before
await hook.before_agent(state, request='{"request_id": "r1", ...}')

// after
import json
payload = request if isinstance(request, dict) else json.loads(request)
await hook.before_agent(state, payload)
Defensive patterns

Strategy: type-guard

Validate before calling

def validate_request(value) -> dict:
    if not isinstance(value, dict):
        raise TypeError("Goal criteria request must be an object.")
    if not isinstance(value.get("request_id"), str) or not value["request_id"].strip():
        raise ValueError("request_id required")
    return value

Type guard

def is_criteria_request(v: object) -> bool:
    return (
        isinstance(v, dict)
        and isinstance(v.get("request_id"), str)
        and bool(v["request_id"].strip())
        and isinstance(v.get("objective"), str)
        and bool(v["objective"].strip())
    )

Try / catch

try:
    validated = _goal_criteria_request(payload)
except TypeError as exc:
    logger.error("payload not an object: %s", exc)
except ValueError as exc:
    logger.error("invalid request field: %s", exc)

Prevention

When it happens

Trigger: A before-agent hook receives a request value that is a JSON string, list, or None instead of an object — e.g. the client sent `"{...}"` as a string, an array of fields, or omitted the payload entirely.

Common situations: Tool clients double-encoding JSON so the object arrives as a string; schema drift between caller and hook (field renamed/moved); programmatic callers passing the wrong structure; agent state containing a list of requests instead of a single request object.

Related errors


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