{"record":{"id":"06659a4fdd7b42d4","repo":"FoundationAgents/MetaGPT","slug":"use-revise-after-fill","errorCode":null,"errorMessage":"use `revise` after `fill`","messagePattern":"use `revise` after `fill`","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"metagpt/actions/action_node.py","lineNumber":824,"sourceCode":"        return sc_dict\n\n    async def simple_revise(self, revise_mode: ReviseMode = ReviseMode.AUTO) -> dict[str, str]:\n        if revise_mode == ReviseMode.HUMAN:\n            revise_contents = await self.human_revise()\n        else:\n            revise_contents = await self.auto_revise(revise_mode)\n\n        return revise_contents\n\n    async def revise(self, strgy: str = \"simple\", revise_mode: ReviseMode = ReviseMode.AUTO) -> dict[str, str]:\n        \"\"\"revise the content of ActionNode and update the instruct_content\n\n        :param strgy: simple/complex\n         - simple: run only once\n         - complex: run each node\n        \"\"\"\n        if not hasattr(self, \"llm\"):\n            raise RuntimeError(\"use `revise` after `fill`\")\n        assert revise_mode in ReviseMode\n        assert self.instruct_content, 'revise only support with `schema != \"raw\"`'\n\n        if strgy == \"simple\":\n            revise_contents = await self.simple_revise(revise_mode)\n        elif strgy == \"complex\":\n            # revise each child node one-by-one\n            revise_contents = {}\n            for _, child in self.children.items():\n                child_revise_content = await child.simple_revise(revise_mode)\n                revise_contents.update(child_revise_content)\n            self.update_instruct_content(revise_contents)\n\n        return revise_contents\n\n    @classmethod\n    def from_pydantic(cls, model: Type[BaseModel], key: str = None):\n        \"\"\"","sourceCodeStart":806,"sourceCodeEnd":842,"githubUrl":"https://github.com/FoundationAgents/MetaGPT/blob/11cdf466d042aece04fc6cfd13b28e1a70341b1f/metagpt/actions/action_node.py#L806-L842","documentation":"ActionNode.revise() rewrites node content based on review comments and updates instruct_content. Like review(), it depends on the LLM instance that only ActionNode.fill() attaches, so calling revise() on an unfilled node raises RuntimeError('use `revise` after `fill`'). It additionally asserts instruct_content exists because revise only works with structured (non-raw) schema.","triggerScenarios":"Calling await node.revise() on an ActionNode that never went through fill(context, llm), or calling revise before review so there is nothing to revise, or invoking revise on a node rebuilt from serialized state without re-attaching llm.","commonSituations":"Custom review/revise pipelines that skip the fill step; copy-pasted sample code; nodes deserialized from context memory where llm attribute was lost.","solutions":["Run await node.fill(context, llm) (and typically await node.review()) before calling revise().","Manually attach node.llm = LLM() and ensure node.instruct_content is populated if you are working with pre-filled data.","Check hasattr(node, 'llm') and node.instruct_content as a precondition in your own code before revising."],"exampleFix":"# before\nawait node.revise()  # RuntimeError: use `revise` after `fill`\n\n# after\nawait node.fill(context=ctx, llm=llm)\ncomments = await node.review()\nrevisions = await node.revise()","handlingStrategy":"type-guard","validationCode":"if not hasattr(node, 'llm') or not node.instruct_content:\n    raise RuntimeError('Node must be filled before revise')\nrevisions = await node.revise()","typeGuard":"def is_reviseable(node: ActionNode) -> bool:\n    return hasattr(node, 'llm') and bool(getattr(node, 'instruct_content', None))","tryCatchPattern":"try:\n    revisions = await node.revise()\nexcept RuntimeError:\n    await node.fill(context, llm)\n    revisions = await node.revise()","preventionTips":["Follow the fill -> review -> revise lifecycle in order.","Ensure child nodes are filled when using strgy='complex'.","Re-attach llm to nodes loaded from serialized state."],"tags":["action-node","api-misuse","llm","ordering"],"backgroundTag":null,"analyzedSha":"11cdf466d042aece04fc6cfd13b28e1a70341b1f","analyzedAt":"2026-08-14T23:20:02.994Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}