{"record":{"id":"5d81b96e4bbd5436","repo":"langchain-ai/deepagents","slug":"rubricmiddleware-build-grader-state-cannot-set","errorCode":null,"errorMessage":"RubricMiddleware: `build_grader_state` cannot set `messages`.","messagePattern":"RubricMiddleware: `build_grader_state` cannot set `messages`\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/deepagents/deepagents/middleware/rubric.py","lineNumber":1011,"sourceCode":"        keeps untrusted transcript content from being read as instructions.\n\n        Args:\n            state: Agent state, read for the rubric and transcript.\n            iteration: Zero-based grading iteration.\n            correction: Feedback about a previous unusable response, if any.\n\n        Returns:\n            The nested grader's input state.\n        \"\"\"\n        grader_state = state\n        if self._prepare_messages_for_grader:\n            grader_state = RubricState(**state)\n            grader_state[\"messages\"] = self._prepare_messages_for_grader(list(state.get(\"messages\", [])))\n        payload = self._build_grader_payload(grader_state, iteration, correction)\n        grader_input = dict(self._build_grader_state(grader_state, iteration)) if self._build_grader_state else {}\n        if \"messages\" in grader_input:\n            msg = \"RubricMiddleware: `build_grader_state` cannot set `messages`.\"\n            raise ValueError(msg)\n        grader_input[\"messages\"] = [HumanMessage(content=payload)]\n        return grader_input\n\n    def _invoke_grader(\n        self,\n        state: RubricState,\n        iteration: int,\n        correction: str | None = None,\n        *,\n        context: object | None = None,\n    ) -> GraderResponse:\n        \"\"\"Run one grader call while preserving nested graph inputs.\n\n        This is the per-call extension point beneath `_grade`'s coverage retry.\n        Overrides should forward `correction` and `context` when delegating here.\n        The context is LangGraph's static runtime context, passed through so a\n        nested grader using a context schema receives the same run dependencies.\n        Grader input must continue through `_grader_input`, which delegates to","sourceCodeStart":993,"sourceCodeEnd":1029,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/deepagents/deepagents/middleware/rubric.py#L993-L1029","documentation":"`build_grader_state` customizes the grader's input state, but `messages` is reserved: the middleware always sets messages itself to a single HumanMessage containing the built grader payload. A builder that returns a dict containing a `messages` key would overwrite that payload, so it's rejected at runtime with ValueError.","triggerScenarios":"A build_grader_state callback that does dict(state) or returns a state including state[\"messages\"] instead of only extra keys.","commonSituations":"Copy-pasting the full state into the builder output; trying to inject custom messages/examples for the grader (the supported route is prepare_messages_for_grader or the payload via system_prompt).","solutions":["Return a dict without the `messages` key: {k: v for k, v in state.items() if k != 'messages'}.","Use prepare_messages_for_grader if you want to shape the conversation content shown to the grader.","Pass custom instructions via system_prompt instead of injecting messages.","Extend grader_state_schema for extra context fields rather than messages."],"exampleFix":"// before\ndef build_grader_state(state, iteration):\n    return dict(state)  # includes messages\n// after\ndef build_grader_state(state, iteration):\n    return {k: v for k, v in state.items() if k != \"messages\"} | {\"iteration\": iteration}","handlingStrategy":"try-catch","validationCode":"def my_builder(state, iteration):\n    out = {k: v for k, v in state.items() if k != \"messages\"}\n    assert \"messages\" not in out\n    return out","typeGuard":"def is_grader_input(d: dict) -> bool:\n    return \"messages\" not in d","tryCatchPattern":"try:\n    result = middleware._invoke_grader(state)\nexcept ValueError as e:\n    if \"cannot set `messages`\" in str(e):\n        fix_builder_to_exclude_messages()\n    else:\n        raise","preventionTips":["In build_grader_state, filter out 'messages' instead of passing state through wholesale.","Use prepare_messages_for_grader for message shaping — that's its job.","Keep builders returning only extra context keys declared in grader_state_schema.","Add a unit test asserting the builder output has no 'messages' key."],"tags":["python","rubric","runtime-error","value-error"],"backgroundTag":"reserved-key-collision","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}