Configuring Role-Specific LLM Parameters and Prompts in MetaGPT

You can configure role-specific LLM parameters and prompts in MetaGPT by assigning a custom LLM instance to a Role's llm attribute and defining profile, goal, and constraints that dynamically generate the system prompt via the _get_prefix() method in metagpt/roles/role.py.

MetaGPT's role-based architecture allows developers to create autonomous agents with distinct personalities and capabilities. By configuring role-specific LLM parameters and prompts, you can fine-tune each agent's behavior, tone, and tool usage without modifying the core framework. This guide examines the implementation in the FoundationAgents/MetaGPT repository to show exactly how these customizations work under the hood.

How Role-Specific LLM Configuration Works in MetaGPT

The Role Class and Runtime Context

The foundation of agent customization lies in the Role class defined in metagpt/roles/role.py. Each role maintains its own RoleContext instance that tracks the message buffer, memory, and react mode, while the llm attribute holds the language model instance used for inference.

When a role is instantiated, Pydantic's model_validator triggers _process_role_extra, which orchestrates the initialization of LLM parameters and prompt generation.

The _process_role_extra Validation Hook

The _process_role_extra method (lines 61-79 in metagpt/roles/role.py) serves as the central configuration hub:

def _process_role_extra(self):
    kwargs = self.model_extra or {}

    if self.is_human:
        self.llm = HumanProvider(None)

    self._check_actions()
    self.llm.system_prompt = self._get_prefix()      # ← inject role‑specific prompt

    self.llm.cost_manager = self.context.cost_manager
    if not self.observe_all_msg_from_buffer:
        self._watch(kwargs.pop("watch", [UserRequirement]))

This method performs three critical tasks:

  • LLM Selection – Assigns a HumanProvider for human roles or uses the configured LLM instance
  • Prompt Injection – Calls _get_prefix() to generate the system prompt and assigns it to self.llm.system_prompt
  • Context Binding – Attaches the cost manager and initializes the watch list for message observation

Setting Up Custom LLM Parameters for Individual Roles

To override the global LLM configuration for a specific role, instantiate a custom LLM object and assign it before the role processes messages. The following example demonstrates configuring a TutorialAssistant with GPT-4 Turbo:

from metagpt.roles.tutorial_assistant import TutorialAssistant
from metagpt.configs.role_custom_config import RoleConfig
from metagpt.provider import LLM

# 1️⃣ Load a custom LLM (e.g. OpenAI gpt‑4‑turbo)

custom_llm = LLM(
    api_key="sk-********",           # <-- keep secret, do NOT commit

    model="gpt-4-turbo",
    # base_url="https://api.openai.com/v1"

)

# 2️⃣ Define role‑specific metadata

role_cfg = RoleConfig(
    name="Alice",
    profile="Software Engineer",
    goal="Explain Python decorators to a junior dev",
    constraints="Use no more than 200 words; avoid code execution"
)

# 3️⃣ Instantiate the role and inject the custom LLM

assistant = TutorialAssistant(config=role_cfg)
assistant.llm = custom_llm               # overrides the global config

assistant._process_role_extra()         # recompute system_prompt & watch list

# 4️⃣ Run the role (the system prompt now contains the custom goal & constraints)

reply = await assistant.run("How do decorators work?")
print(reply.content)

Critical implementation details:

  • Assign assistant.llm before calling _process_role_extra() to ensure the system prompt is generated using the correct LLM instance
  • The RoleConfig class (defined in metagpt/config2.py) validates the metadata schema
  • Global configurations reside in YAML files like config/examples/openai-gpt-4-turbo.yaml, but per-role instances override these

Customizing System Prompts for Tailored Agent Behavior

MetaGPT generates role-specific system prompts dynamically using templates defined in metagpt/roles/role.py.

Prompt Template Structure

The system prompt construction relies on two key templates:

PREFIX_TEMPLATE = """You are a {profile}, named {name}, your goal is {goal}."""

CONSTRAINT_TEMPLATE = """\nConstraints:\n{constraints}"""

These templates are combined in the _get_prefix() method to create a coherent identity for the agent.

Dynamic Prompt Generation with _get_prefix

The _get_prefix() method (lines 71-84 in metagpt/roles/role.py) assembles the final system prompt:

def _get_prefix(self):
    if self.desc:
        return self.desc

    prefix = PREFIX_TEMPLATE.format(**{
        "profile": self.profile,
        "name": self.name,
        "goal": self.goal,
    })

    if self.constraints:
        prefix += CONSTRAINT_TEMPLATE.format(**{"constraints": self.constraints})

    if self.rc.env and self.rc.env.desc:
        # add environment context

        all_roles = self.rc.env.role_names()
        other_role_names = ", ".join([r for r in all_roles if r != self.name])
        env_desc = f"You are in {self.rc.env.desc} with roles({other_role_names})."
        prefix += env_desc
    return prefix

Key behaviors:

  • If desc is explicitly provided, it overrides the template entirely
  • The profile, name, and goal fields form the core identity statement
  • Optional constraints append specific behavioral limitations
  • When operating within an Environment, the prompt automatically includes context about other available roles

Per-Action LLM Overrides

While role-level configuration sets the default model, individual actions can override this to use specialized models for specific tasks. This is implemented in the _init_action method of metagpt/roles/role.py:

def _init_action(self, action: Action):
    action.set_context(self.context)
    override = not action.private_config
    action.set_llm(self.llm, override=override)   # ← shares the role’s LLM

    action.set_prefix(self._get_prefix())

To use a different model for a specific action, instantiate the action with its own LLM before adding it to the role:

from metagpt.actions import WriteCode
from metagpt.provider import LLM

# A cheap model for general chat

chat_llm = LLM(api_key="...", model="gpt-3.5-turbo")

# A powerful model for code generation

code_llm = LLM(api_key="...", model="gpt-4")

# Action that uses the heavyweight model

write_code = WriteCode()
write_code.set_llm(code_llm, override=True)

assistant = TutorialAssistant()
assistant.set_actions([write_code])   # the action keeps its own LLM

Only WriteCode will invoke gpt-4; other actions in the role continue using the default chat_llm. This pattern enables cost-effective heterogeneous inference where expensive models handle complex generation tasks while cheaper models manage routine interactions.

Summary

  • Role-level LLM assignment occurs through the llm attribute in metagpt/roles/role.py, validated during _process_role_extra() which injects the system prompt and cost manager.
  • System prompts are dynamically assembled from profile, name, goal, and optional constraints using PREFIX_TEMPLATE and CONSTRAINT_TEMPLATE, with automatic environment context appended when applicable.
  • Action-level overrides allow specific tasks to use different models by calling set_llm() with override=True before adding the action to the role via set_actions().
  • Configuration hierarchy flows from global YAML files (e.g., config/examples/openai-gpt-4-turbo.yaml) to runtime RoleConfig objects to direct LLM instance assignment.

Frequently Asked Questions

How do I assign a different LLM model to a specific role?

Assign a custom LLM instance to the role's llm attribute and call _process_role_extra() to recompute the system prompt. This overrides the global configuration defined in YAML files like config/examples/openai-gpt-4-turbo.yaml. Ensure you set the LLM before the role processes its first message to guarantee the correct model handles all subsequent inference calls.

Can I customize the system prompt template for a role?

Yes, the system prompt is generated dynamically in metagpt/roles/role.py using PREFIX_TEMPLATE and optional CONSTRAINT_TEMPLATE. You can customize the output by setting the profile, name, goal, and constraints attributes on your role instance, or override the _get_prefix() method entirely to return a custom desc string that bypasses the template system.

Is it possible to use different LLMs for different actions within the same role?

Absolutely. Instantiate actions with their own LLM instances and call set_llm(model, override=True) before adding them to the role via set_actions(). According to the _init_action implementation in metagpt/roles/role.py, actions with private_config set will retain their specific LLM while other actions inherit the role's default model, enabling cost-effective routing such as using GPT-4 for coding and GPT-3.5 for chat.

Where are LLM configurations stored in MetaGPT?

MetaGPT supports hierarchical configuration through YAML files in the config/ directory (such as config/examples/openai-gpt-4-turbo.yaml), runtime LLMConfig objects defined in metagpt/config2.py, and direct instantiation of the LLM class from metagpt/provider/llm.py. The global configuration singleton loads settings from environment variables and YAML, but per-role overrides take precedence when explicitly assigned to the llm attribute before _process_role_extra() executes.

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 →