Managing Incremental Development Cycles and State Updates in MetaGPT

MetaGPT enables incremental software development through the --inc CLI flag for loading existing repositories and the rc.state mechanism in BaseRole that persists action sequences across interruptions, allowing AI agents to resume development from exact breakpoints.

MetaGPT is an extensible Python framework where autonomous AI agents called Roles collaborate to design, develop, and refine software projects. Managing incremental development cycles and state updates in MetaGPT relies on two core mechanisms: the incremental mode flag that loads existing codebases without restarting from scratch, and the role state machine that tracks execution progress through indexed action sequences. Together, these systems allow a single CLI command to load legacy code, create a fresh AI-driven development loop, and resume from the exact point where the previous run terminated.

Understanding MetaGPT's Incremental Development Architecture

The Incremental Mode Flag (--inc)

The --inc flag triggers MetaGPT's incremental development capability, allowing the framework to work on an existing repository rather than generating a new project from scratch. When activated, the system parses the existing codebase, creates a Git tag named base to preserve the original state, and injects the project path into the configuration context.

This mechanism is implemented in metagpt/software_company.py within the generate_repo function, which handles the CLI argument parsing and delegates to config.update_via_cli to set the incremental flag and project path.

Role State Machines and rc.state

Each Role in MetaGPT maintains an internal state machine through the RoleContext object (self.rc). The critical field rc.state stores an integer index pointing to the current action in the role's self.actions list. This state persists across interruptions and enables precise recovery.

The state management logic resides in metagpt/roles/role.py, where the _set_state method updates rc.state and synchronizes the next todo action:

def _set_state(self, state: int):
    """Update the current state."""
    self.rc.state = state
    logger.debug(f"actions={self.actions}, state={state}")
    self.set_todo(self.actions[self.rc.state] if state >= 0 else None)

How MetaGPT Implements Incremental Development Cycles

Configuration and CLI Entry Points

MetaGPT's configuration system in metagpt/config2.py uses a Pydantic-based Config model to merge environment variables, YAML files, and CLI arguments. When the --inc flag is present, the update_via_cli method marks the run as incremental and records the existing repository path:


# metagpt/software_company.py

def generate_repo(..., inc=False, project_path="", ...):
    # …

    config.update_via_cli(project_path, project_name, inc, reqa_file, max_auto_summarize_code)
    ctx = Context(config=config)
    # …

This configuration then propagates through the Context object to all roles and actions.

Team Assembly and Round-Based Execution

The generate_repo function constructs a Team object (defined in metagpt/team.py) and hires the standard pipeline of roles:

company = Team(context=ctx)
company.hire([
    TeamLeader(),
    ProductManager(),
    Architect(),
    Engineer2(),
    DataAnalyst(),
])

The Team.run() method initiates a round-based loop where each role executes its _think and _act methods. During incremental runs, roles read the existing repository state from disk before proposing modifications, ensuring continuity with the legacy codebase.

Git Tag Management for Base State Preservation

Before AI agents modify files, MetaGPT creates a Git tag named base to preserve the original repository state. This functionality, implemented in metagpt/utils/git_repository.py, allows the system to:

  1. Compare changes between the original and modified states
  2. Rollback to the base state if necessary
  3. Generate diffs for review purposes

The test harness in tests/metagpt/test_incremental_dev.py demonstrates this workflow through the check_or_create_base_tag helper function, which prepares archived projects for incremental development testing.

State Update Mechanisms in MetaGPT Roles

The _set_state Method and State Transitions

State transitions in MetaGPT roles follow a deterministic pattern governed by the _think method. When react_mode is set to "by_order", the role simply increments rc.state to proceed to the next action. For more complex workflows, the role prompts the LLM to select the next state number based on current context.

The _set_state method in metagpt/roles/role.py (lines 302-313) performs three critical operations:

  1. Updates the integer index in self.rc.state
  2. Logs the available actions and new state for debugging
  3. Sets the current todo action by indexing into self.actions

Persistence and Recovery with Binary Serialization

MetaGPT implements robust persistence through binary serialization of the entire Team state. The Team.serialize() method creates a .team file containing:

  • All role contexts (rc objects)
  • Action histories
  • Message buffers
  • Git repository state

Recovery is handled by Team.deserialize() in metagpt/team.py:

if recover_path:
    stg_path = Path(recover_path)
    company = Team.deserialize(stg_path=stg_path, context=ctx)
    idea = company.idea

Because rc.state is part of the serialized RoleContext, the framework resumes execution from the exact breakpoint, maintaining continuity across system restarts or crashes.

Practical Examples: Running Incremental Development

Running an Incremental Development Session

To evolve an existing codebase with new requirements, use the --inc flag combined with --project-path:


# 1️⃣  Prepare an existing repo (e.g. cloned at ./old_project)

# 2️⃣  Issue a new requirement to MetaGPT

metagpt startup \
    "Add a dark mode toggle to the UI" \
    --inc \
    --project-path ./old_project \
    --n-round 30 \
    --code-review \
    --investment 5.0

What happens under the hood:

  • The CLI parses --inc and sets Config.inc = True via update_via_cli in metagpt/config2.py
  • software_company.generate_repo loads the old repo, creates a base Git tag, and builds a fresh Team
  • The Team runs a multi-round loop; each role updates its rc.state and writes commits to the repository

Inspecting Role State at Runtime

You can programmatically inspect and manipulate role states for debugging or custom workflows:

from metagpt.roles.engineer import Engineer2
from metagpt.context import Context
from metagpt.config2 import config

ctx = Context(config=config)
engineer = Engineer2()
engineer.set_env(ctx.env)          # bind to environment

engineer._set_state(2)            # jump to the 3rd action

print(engineer.rc.state)          # → 2

print(engineer.rc.todo)           # currently scheduled Action object

This snippet directly manipulates rc.state (via the private _set_state method) – the same mechanism the framework uses automatically after each successful action in metagpt/roles/role.py.

Serializing and Recovering a Team

To persist progress across system restarts:


# Serialize after 10 rounds

team_path = team.serialize()   # creates <project_path>/team/<timestamp>.team

# Later, resume from the saved snapshot

recovered_team = Team.deserialize(stg_path=team_path, context=Context())
await recovered_team.run(n_round=20, idea="Continue development")

The restored Team brings back each role’s rc.state, enabling seamless continuation of incremental development cycles even after hardware failures or planned maintenance.

Summary

  • Incremental mode (--inc) allows MetaGPT to work on existing repositories by loading legacy code, creating a base Git tag for rollback protection, and injecting the project path into the configuration via software_company.generate_repo.

  • Role state machines track execution progress through the rc.state integer index in RoleContext, which points to the current action in the role's action list and persists across interruptions.

  • State transitions are managed by the _set_state method in metagpt/roles/role.py, which updates the state index and synchronizes the next todo action for deterministic workflow progression.

  • Persistence and recovery rely on binary serialization of the entire Team state to .team files, allowing Team.deserialize to restore exact role contexts including rc.state for seamless continuation of development cycles.

Frequently Asked Questions

How does MetaGPT handle existing codebases without overwriting them?

MetaGPT uses the --inc (incremental) flag combined with --project-path to load existing repositories. The framework creates a base Git tag via check_or_create_base_tag in metagpt/utils/git_repository.py to preserve the original state, then applies new requirements through AI-driven development cycles without destroying legacy code.

What is the rc.state variable in MetaGPT roles?

The rc.state variable is an integer index stored in the RoleContext object (self.rc) that tracks which action a role should execute next. Defined in metagpt/roles/role.py, this state is updated via _set_state and persists across serialization cycles, enabling roles to resume from exact breakpoints after system interruptions.

How can I resume a MetaGPT project after a crash?

Use the binary serialization feature by calling team.serialize() to create a .team snapshot file. To resume, invoke Team.deserialize(stg_path=team_path, context=Context()) which restores all role contexts including rc.state values, then continue execution with await recovered_team.run(). This mechanism is implemented in metagpt/team.py.

What is the difference between by_order and LLM-based state selection?

When react_mode is set to "by_order", MetaGPT roles increment rc.state sequentially through their action list. For complex workflows, the _think method prompts the LLM to select the next state number based on current context and observations. Both approaches use _set_state in metagpt/roles/role.py to update the role's execution pointer.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →