FoundationAgents/MetaGPT · error · RuntimeError

use `revise` after `fill`

Error message

use `revise` after `fill`

What it means

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.

Source

Thrown at metagpt/actions/action_node.py:824

        return sc_dict

    async def simple_revise(self, revise_mode: ReviseMode = ReviseMode.AUTO) -> dict[str, str]:
        if revise_mode == ReviseMode.HUMAN:
            revise_contents = await self.human_revise()
        else:
            revise_contents = await self.auto_revise(revise_mode)

        return revise_contents

    async def revise(self, strgy: str = "simple", revise_mode: ReviseMode = ReviseMode.AUTO) -> dict[str, str]:
        """revise the content of ActionNode and update the instruct_content

        :param strgy: simple/complex
         - simple: run only once
         - complex: run each node
        """
        if not hasattr(self, "llm"):
            raise RuntimeError("use `revise` after `fill`")
        assert revise_mode in ReviseMode
        assert self.instruct_content, 'revise only support with `schema != "raw"`'

        if strgy == "simple":
            revise_contents = await self.simple_revise(revise_mode)
        elif strgy == "complex":
            # revise each child node one-by-one
            revise_contents = {}
            for _, child in self.children.items():
                child_revise_content = await child.simple_revise(revise_mode)
                revise_contents.update(child_revise_content)
            self.update_instruct_content(revise_contents)

        return revise_contents

    @classmethod
    def from_pydantic(cls, model: Type[BaseModel], key: str = None):
        """

View on GitHub (pinned to 11cdf466d0)

Solutions

  1. Run await node.fill(context, llm) (and typically await node.review()) before calling revise().
  2. Manually attach node.llm = LLM() and ensure node.instruct_content is populated if you are working with pre-filled data.
  3. Check hasattr(node, 'llm') and node.instruct_content as a precondition in your own code before revising.

Example fix

# before
await node.revise()  # RuntimeError: use `revise` after `fill`

# after
await node.fill(context=ctx, llm=llm)
comments = await node.review()
revisions = await node.revise()
Defensive patterns

Strategy: type-guard

Validate before calling

if not hasattr(node, 'llm') or not node.instruct_content:
    raise RuntimeError('Node must be filled before revise')
revisions = await node.revise()

Type guard

def is_reviseable(node: ActionNode) -> bool:
    return hasattr(node, 'llm') and bool(getattr(node, 'instruct_content', None))

Try / catch

try:
    revisions = await node.revise()
except RuntimeError:
    await node.fill(context, llm)
    revisions = await node.revise()

Prevention

When it happens

Trigger: 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.

Common situations: Custom review/revise pipelines that skip the fill step; copy-pasted sample code; nodes deserialized from context memory where llm attribute was lost.

Related errors


AI-assisted analysis of FoundationAgents/MetaGPT@11cdf466d0 (2026-08-14). Data as JSON: /api/errors/06659a4fdd7b42d4. Report an issue: GitHub.