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
HumanProviderfor human roles or uses the configured LLM instance - Prompt Injection – Calls
_get_prefix()to generate the system prompt and assigns it toself.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.llmbefore calling_process_role_extra()to ensure the system prompt is generated using the correct LLM instance - The
RoleConfigclass (defined inmetagpt/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
descis explicitly provided, it overrides the template entirely - The
profile,name, andgoalfields form the core identity statement - Optional
constraintsappend 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
llmattribute inmetagpt/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 optionalconstraintsusingPREFIX_TEMPLATEandCONSTRAINT_TEMPLATE, with automatic environment context appended when applicable. - Action-level overrides allow specific tasks to use different models by calling
set_llm()withoverride=Truebefore adding the action to the role viaset_actions(). - Configuration hierarchy flows from global YAML files (e.g.,
config/examples/openai-gpt-4-turbo.yaml) to runtimeRoleConfigobjects to directLLMinstance 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →