# How to Customize Standard Operating Procedures (SOP) for Agent Workflows in MetaGPT

> Learn how to customize Standard Operating Procedures SOP for agent workflows in MetaGPT. Switch between dynamic LLM-driven planning and static pipelines to optimize your agents.

- Repository: [FoundationAgents/MetaGPT](https://github.com/FoundationAgents/MetaGPT)
- Tags: how-to-guide
- Published: 2026-03-04

---

**To customize SOPs in MetaGPT, toggle the `use_fixed_sop` flag in `RoleZero`-based classes to switch between dynamic LLM-driven planning and static, predefined action pipelines.**

MetaGPT treats **Standard Operating Procedures (SOP)** as configurable behavioral rules that govern how each **role** (agent) reacts to inputs, selects tools, and executes actions. By customizing the SOP configuration in the MetaGPT framework, you can shape deterministic workflows with explicit step-by-step logic or enable adaptive, LLM-generated execution strategies. This guide covers the architectural mechanics, source code references, and practical implementations for both fixed and dynamic SOP modes.

## SOP Architecture and the `use_fixed_sop` Switch

The MetaGPT architecture centers on the `RoleZero` base class in [`metagpt/roles/di/role_zero.py`](https://github.com/FoundationAgents/MetaGPT/blob/main/metagpt/roles/di/role_zero.py), which implements the core SOP logic. Every role inherits from this class and respects the `use_fixed_sop` boolean flag (default `False`) stored in the instance.

When `use_fixed_sop` is `False`, the role enters **dynamic SOP** mode. In this mode, the `_think()` method builds an execution plan, queries the LLM for decisions, and uses the `ToolRecommender` to suggest relevant tools based on the current task context. This creates an adaptive "think-act" loop where the agent iteratively plans and executes until completion or budget exhaustion.

When `use_fixed_sop` is `True`, the role enters **fixed SOP** mode. The `_think()` method returns early, bypassing LLM-driven planning entirely. Instead, the role executes a static list of predefined actions set during initialization via `set_actions()`. This mode also typically disables memory tracking to ensure deterministic execution.

The `Team` class in [`metagpt/team.py`](https://github.com/FoundationAgents/MetaGPT/blob/main/metagpt/team.py) (lines 34-36) aggregates these roles and stores the overall SOP description in its docstring, serving as the high-level container that orchestrates multi-agent workflows.

## Implementing Fixed SOP Workflows

Fixed SOPs provide deterministic, repeatable workflows ideal for structured tasks like requirements gathering or architectural design. To implement a fixed SOP, you must override the role's `__init__` method to set `use_fixed_sop=True`, disable memory, and define a static action pipeline.

### Fixed SOP Implementation Pattern

The `ProductManager` role in [`metagpt/roles/product_manager.py`](https://github.com/FoundationAgents/MetaGPT/blob/main/metagpt/roles/product_manager.py) (lines 43-48) demonstrates the canonical pattern:

```python
def __init__(self, **kwargs):
    super().__init__(**kwargs)
    self.use_fixed_sop = True
    self.enable_memory = False
    self.set_actions([PrepareDocuments, WritePRD])

```

Key configuration points for fixed SOPs include:

- **`use_fixed_sop = True`** – Forces the role to skip the LLM planning phase in `RoleZero._think()`.
- **`enable_memory = False`** – Disables conversation memory to ensure the role follows the exact script without historical context interference.
- **`set_actions([...])`** – Accepts a list of action classes or callables that execute sequentially in the order provided.

The `Architect` role in [`metagpt/roles/architect.py`](https://github.com/FoundationAgents/MetaGPT/blob/main/metagpt/roles/architect.py) (lines 46-48) extends this pattern by additionally mapping custom tool execution logic through `_update_tool_execution()`, allowing specific tool calls like `Terminal.run_command` within the fixed workflow.

## Configuring Dynamic SOP Behavior

Dynamic SOPs leverage the LLM's reasoning capabilities for adaptive problem-solving. When `use_fixed_sop` remains `False` (the default), `RoleZero._think()` executes its full logic:

1. Builds a plan based on the current task and context.
2. Queries the `ToolRecommender` to suggest a subset of available tools relevant to the task.
3. Generates a command string for the LLM to decide the next action.
4. `_act()` parses the command string, executes the selected tool(s), and loops until task completion.

This mode is ideal for complex, exploratory tasks where the solution path cannot be predetermined. The dynamic behavior is implemented in [`metagpt/roles/di/role_zero.py`](https://github.com/FoundationAgents/MetaGPT/blob/main/metagpt/roles/di/role_zero.py) (lines 19-22) where `tools = await self.tool_recommender.recommend_tools()` populates the context-aware tool selection.

## Practical Customization Examples

### Creating a Custom Fixed-SOP Role

The following example creates a `DataAnalyst` role with a hardcoded analysis pipeline:

```python
from metagpt.roles.di.role_zero import RoleZero
from metagpt.prompts.di.role_zero import ROLE_INSTRUCTION

class DataAnalyst(RoleZero):
    name = "Dana"
    profile = "Data Analyst"
    instruction = ROLE_INSTRUCTION
    tools = ["Editor:write,read", "Browser:search"]

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.use_fixed_sop = True
        self.enable_memory = False
        self.set_actions([self._load_data, self._run_analysis])

    async def _load_data(self):
        return "Data loaded from source."

    async def _run_analysis(self):
        return "Analysis complete."

```

In this configuration, the `tools` attribute restricts the available toolbox, preventing the LLM from recommending unrelated utilities even if the role were temporarily switched to dynamic mode. The `set_actions()` method injects the static pipeline `[self._load_data, self._run_analysis]`.

### Switching SOP Modes at Runtime

You can dynamically alter SOP behavior after instantiation by modifying the flag before adding the role to a team:

```python
from metagpt.roles.architect import Architect
from metagpt.team import Team

arch = Architect()
arch.use_fixed_sop = False  # Enable dynamic LLM planning

team = Team()
team.hire([arch])
team.run_project("Design a micro-service architecture")
await team.run()

```

When `use_fixed_sop=False`, the `Architect` will use the tool recommendation engine and iterative planning rather than the fixed action sequence defined in its class.

### Integrating with Team Workflows

To deploy a fixed-SOP agent within a multi-agent team:

```python
from metagpt.roles.product_manager import ProductManager
from metagpt.team import Team

pm = ProductManager(use_fixed_sop=True)

team = Team()
team.hire([pm])
team.run_project("Create a PRD for a todo-list app")
await team.run(n_round=3)

```

The `Team.run()` coroutine iterates over hired roles, respecting their individual SOP modes, and terminates when all roles are idle or the budget is exhausted.

## Key Source Files for SOP Customization

When customizing Standard Operating Procedures, consult these specific files and line ranges:

- **[`metagpt/roles/di/role_zero.py`](https://github.com/FoundationAgents/MetaGPT/blob/main/metagpt/roles/di/role_zero.py)** (lines 98-104) – Contains the `use_fixed_sop` flag definition and the `_think()` method logic that branches between fixed and dynamic execution paths.
- **[`metagpt/roles/product_manager.py`](https://github.com/FoundationAgents/MetaGPT/blob/main/metagpt/roles/product_manager.py)** (lines 43-48) – Reference implementation of a fixed-SOP role with disabled memory and static actions.
- **[`metagpt/roles/architect.py`](https://github.com/FoundationAgents/MetaGPT/blob/main/metagpt/roles/architect.py)** (lines 46-48) – Demonstrates fixed-SOP configuration with custom tool execution mapping.
- **[`metagpt/team.py`](https://github.com/FoundationAgents/MetaGPT/blob/main/metagpt/team.py)** (lines 34-36) – Defines the `Team` container and documents the overall SOP concept for multi-agent orchestration.
- **[`metagpt/strategy/task_type.py`](https://github.com/FoundationAgents/MetaGPT/blob/main/metagpt/strategy/task_type.py)** (lines 73-75) – Contains the `TaskType.DEVELOP_SOFTWARE` SOP description used for task-type routing and pipeline selection.

## Summary

- **MetaGPT SOPs** are controlled by the `use_fixed_sop` boolean in `RoleZero`-derived classes, defaulting to dynamic LLM-driven behavior.
- **Fixed SOPs** bypass LLM planning by setting `use_fixed_sop=True`, disabling memory, and using `set_actions()` to define explicit execution pipelines.
- **Dynamic SOPs** leverage `RoleZero._think()` to generate plans, recommend tools via `ToolRecommender`, and iteratively refine actions.
- **Source code locations**: Core logic resides in [`metagpt/roles/di/role_zero.py`](https://github.com/FoundationAgents/MetaGPT/blob/main/metagpt/roles/di/role_zero.py), with implementation examples in [`metagpt/roles/product_manager.py`](https://github.com/FoundationAgents/MetaGPT/blob/main/metagpt/roles/product_manager.py) and [`metagpt/roles/architect.py`](https://github.com/FoundationAgents/MetaGPT/blob/main/metagpt/roles/architect.py).

## Frequently Asked Questions

### What is the difference between fixed and dynamic SOP in MetaGPT?

**Fixed SOP** disables LLM-driven planning and executes a predefined list of actions sequentially, making it ideal for deterministic workflows. **Dynamic SOP** (the default) uses the `_think()` method to generate plans on-the-fly, recommends tools dynamically, and allows the agent to adapt its strategy based on intermediate results. The mode is controlled by the `use_fixed_sop` flag in `RoleZero`.

### How do I disable memory when using fixed SOP?

Set `self.enable_memory = False` in the role's `__init__` method, as demonstrated in `ProductManager` ([`metagpt/roles/product_manager.py`](https://github.com/FoundationAgents/MetaGPT/blob/main/metagpt/roles/product_manager.py), lines 43-48). This prevents the role from accessing conversation history, ensuring it follows the static action pipeline without context interference.

### Can I switch SOP modes after initializing a role?

Yes. The `use_fixed_sop` attribute is a public instance variable that can be toggled at runtime before the role joins a team workflow. For example, you can instantiate an `Architect`, then set `arch.use_fixed_sop = False` to enable dynamic planning for a specific project without modifying the class definition.

### Which source file contains the main SOP logic?

The primary SOP logic resides in **[`metagpt/roles/di/role_zero.py`](https://github.com/FoundationAgents/MetaGPT/blob/main/metagpt/roles/di/role_zero.py)**, specifically lines 98-104 where the `use_fixed_sop` flag is defined and checked, and lines 19-22 where the dynamic tool recommendation occurs. This file serves as the base class for all customizable agent roles in MetaGPT.