Debugging and Troubleshooting Errors During Agent Actions in MetaGPT
MetaGPT provides a layered debugging architecture that combines automated error detection via the DebugError action, robust LLM output parsing through CodeParser, and centralized logging to automatically identify, diagnose, and resolve failures during agent execution.
MetaGPT orchestrates complex multi-agent workflows where debugging and troubleshooting errors during agent actions is critical for maintaining pipeline reliability. When agents execute actions—whether running tests, parsing LLM responses, or interacting with external services—failures can emerge from malformed JSON, runtime exceptions, or infrastructure issues. The framework provides specialized utilities across metagpt/actions/debug_error.py, metagpt/utils/common.py, and metagpt/logs.py to surface, analyze, and automatically remediate these errors.
Action-Level Debugging with DebugError
The DebugError action automates the debugging loop by reading test output, feeding failure logs to an LLM, and extracting corrected code. Located in metagpt/actions/debug_error.py (lines 50-77), this specialized Action implementation inspects test results, constructs structured prompts containing the failing code and error logs, and returns a fix.
# https://github.com/FoundationAgents/MetaGPT/blob/main/metagpt/actions/debug_error.py#L50-L77
class DebugError(Action):
i_context: RunCodeContext = Field(default_factory=RunCodeContext)
repo: Optional[ProjectRepo] = Field(default=None, exclude=True)
async def run(self, *args, **kwargs) -> str:
# Retrieve test output from the repository
output_doc = await self.repo.test_outputs.get(filename=self.i_context.output_filename)
if not output_doc:
return ""
# Parse the test runner summary
output_detail = RunCodeResult.loads(output_doc.content)
pattern = r"Ran (\d+) tests in ([\d.]+)s\n\nOK"
if re.search(pattern, output_detail.stderr):
return "" # No failures detected
# Pull source and test code to construct the prompt
code_doc = await self.repo.srcs.get(filename=self.i_context.code_filename)
test_doc = await self.repo.tests.get(filename=self.i_context.test_filename)
prompt = PROMPT_TEMPLATE.format(
code=code_doc.content,
test_code=test_doc.content,
logs=output_detail.stderr,
)
# Request fix from LLM and extract code block
rsp = await self._aask(prompt)
return CodeParser.parse_code(text=rsp)
When an action fails, adding DebugError to the role's workflow enables automatic error recovery. The action uses the base class _aask method to invoke the configured LLM and relies on CodeParser.parse_code to safely extract the corrected implementation from the LLM's markdown response.
Safe LLM Output Extraction with CodeParser
Parsing LLM output is error-prone due to malformed JSON, missing fields, or inconsistent markdown formatting. The CodeParser class in metagpt/utils/common.py (lines 250-280) normalizes this process by splitting markdown documents into logical sections and extracting specific code blocks.
# https://github.com/FoundationAgents/MetaGPT/blob/main/metagpt/utils/common.py#L250-L280
class CodeParser:
@classmethod
def parse_block(cls, block: str, text: str) -> str:
blocks = cls.parse_blocks(text)
for k, v in blocks.items():
if block in k:
return v
return ""
@classmethod
def parse_blocks(cls, text: str):
# Split on "##" headings to create logical sections
blocks = text.split("##")
block_dict = {}
for block in blocks:
if not block.strip():
continue
if "\n" not in block:
block_title, block_content = block, ""
else:
block_title, block_content = block.split("\n", 1)
block_dict[block_title.strip()] = block_content.strip()
return block_dict
The parse_blocks method handles missing or extra headings gracefully, returning a deterministic dictionary of sections. When DebugError or any other action processes LLM responses, using CodeParser.parse_code (which internally leverages these utilities) guarantees robust extraction of Python code from markdown fences, preventing parsing failures from cascading into agent execution errors.
Centralized Logging for Agent Actions
MetaGPT uses loguru for structured logging, configured through metagpt/logs.py. The define_log_level function (lines 9-55) initializes loggers with both console and file handlers, enabling adjustable verbosity across the framework.
# https://github.com/FoundationAgents/MetaGPT/blob/main/metagpt/logs.py#L9-L55
def define_log_level(print_level="INFO", logfile_level="DEBUG", name: str = None):
global _print_level
_print_level = print_level
current_date = datetime.now()
formatted_date = current_date.strftime("%Y%m%d")
log_name = f"{name}_{formatted_date}" if name else formatted_date
_logger.remove()
_logger.add(sys.stderr, level=print_level) # Console output
_logger.add(METAGPT_ROOT / f"logs/{log_name}.txt", level=logfile_level) # File output
return _logger
logger = define_log_level()
For LLM-specific debugging, the log_debug function in metagpt/provider/general_api_base.py (lines 80-95) respects the LLM_LOG environment variable, emitting debug messages only when explicitly enabled.
# https://github.com/FoundationAgents/MetaGPT/blob/main/metagpt/provider/general_api_base.py#L80-L95
LLM_LOG = os.environ.get("LLM_LOG", "debug")
def log_debug(message, **params):
if _console_log_level() == "debug":
logger.debug(message, **params)
Enabling verbose logging:
import os
os.environ["LLM_LOG"] = "debug" # Enable LLM debug output
from metagpt.provider.general_api_base import log_debug
log_debug("Sending request to LLM", method="POST", url=api_url)
This configuration captures every LLM request, file I/O operation, and exception trace in the per-run log file located at logs/{date}.txt, providing a complete audit trail for troubleshooting agent actions.
Exception Handling Utilities
MetaGPT centralizes error handling in metagpt/utils/exceptions.py to ensure consistent error messages and stack trace preservation. The handle_exception function wraps low-level operations, logging the full context before re-raising enriched exceptions.
# https://github.com/FoundationAgents/MetaGPT/blob/main/metagpt/utils/exceptions.py
def handle_exception(e: Exception, context: str = ""):
logger.error(f"Exception in {context}: {e}")
raise
Every utility performing I/O—such as metagpt/utils/s3.py and metagpt/utils/file.py—invokes handle_exception on unexpected errors. This guarantees that debugging and troubleshooting errors during agent actions always produces uniform log entries containing the exception type, message, and operational context, eliminating fragmented error handling across the codebase.
Complete Debugging Workflow Example
The following pattern demonstrates how to integrate MetaGPT's debugging utilities into a custom role or test harness. This example combines DebugError, centralized logging, and repository abstraction to create a self-healing workflow.
# example_debug_flow.py
import os
from metagpt.actions.debug_error import DebugError
from metagpt.utils.project_repo import ProjectRepo
from metagpt.provider.general_api_base import log_debug
# Enable verbose log output for troubleshooting
os.environ["LLM_LOG"] = "debug"
async def debug_failed_action():
# 1️⃣ Prepare repository abstraction pointing to your local project
repo = await ProjectRepo.from_path(root_path="my_project")
# 2️⃣ Initialise DebugError with context from the failing test
dbg = DebugError(
i_context=RunCodeContext(
code_filename="src/foo.py",
test_filename="tests/test_foo.py",
output_filename="outputs/run_test.txt",
),
repo=repo,
)
# 3️⃣ Execute debugging action – returns revised source code or empty string
fixed_code = await dbg.run()
if not fixed_code:
log_debug("No fix suggested – test passed or LLM could not parse logs")
return
# 4️⃣ Persist the suggested fix (optional)
await repo.srcs.save(filename="src/foo_fixed.py", content=fixed_code)
log_debug("Fixed code written to src/foo_fixed.py")
# To execute within an async event loop:
# import asyncio
# asyncio.run(debug_failed_action())
This workflow delivers rich log records for each execution step, structured prompts automatically built from failing test output, and robust code extraction via CodeParser, enabling agents to self-correct during runtime.
Key Files for Debugging Agent Actions
| Path | Purpose |
|---|---|
metagpt/actions/debug_error.py |
Core debugging action that reads test output, builds LLM prompts, and extracts fixes. |
metagpt/utils/common.py |
Contains CodeParser class for safe markdown and code block extraction from LLM responses. |
metagpt/logs.py |
Global logger configuration using loguru; controls console and file output streams. |
metagpt/provider/general_api_base.py |
Implements log_debug function respecting the LLM_LOG environment variable. |
metagpt/utils/exceptions.py |
Centralized exception handling with handle_exception for consistent error reporting. |
metagpt/actions/action.py |
Base Action class defining _aask method used by DebugError for LLM invocation. |
metagpt/utils/file_repository.py |
File abstraction layer used by DebugError to retrieve source and test files. |
Summary
MetaGPT's debugging ecosystem revolves around a clear separation of concerns that enables systematic debugging and troubleshooting errors during agent actions:
- Action-level helpers (
DebugErrorinmetagpt/actions/debug_error.py) automate the detection of test failures and generation of corrective code via LLM prompts. - Parsing utilities (
CodeParserinmetagpt/utils/common.py) normalize markdown extraction, preventing malformed LLM responses from cascading into execution errors. - Central logging (
log_debuganddefine_log_level) provides fine-grained visibility into LLM interactions and file I/O through environment-controlled verbosity. - Exception wrappers (
handle_exceptioninmetagpt/utils/exceptions.py) standardize error messages and preserve stack traces across the codebase.
By wiring these components together, you can automatically detect failures, request corrective code from the LLM, and safely apply patches—all while retaining a complete, searchable audit trail in per-run log files.
Frequently Asked Questions
How does MetaGPT automatically fix code when tests fail?
MetaGPT uses the DebugError action class located in metagpt/actions/debug_error.py to automate error correction. When a test fails, DebugError retrieves the test output from the repository, constructs a structured prompt containing the failing code, test code, and error logs, then invokes the LLM via the _aask method. The response is parsed using CodeParser.parse_code to extract the corrected implementation, which can then be saved back to the project.
What is the purpose of the CodeParser utility in MetaGPT?
CodeParser in metagpt/utils/common.py provides deterministic extraction of markdown sections and code blocks from LLM responses. Its parse_blocks method splits text on ## headings to create logical sections, while parse_block retrieves specific sections by title. This prevents parsing failures—such as malformed JSON or inconsistent markdown—from propagating through the agent pipeline, ensuring that actions like DebugError receive clean, extractable code regardless of LLM output variations.
How can I enable verbose debugging output in MetaGPT?
Set the LLM_LOG environment variable to "debug" before importing MetaGPT modules. This activates the log_debug function in metagpt/provider/general_api_base.py, which emits detailed debug messages about LLM requests and responses. Additionally, the define_log_level function in metagpt/logs.py configures loguru to write DEBUG level logs to logs/{date}.txt while controlling console verbosity separately via the print_level parameter.
Where does MetaGPT handle exceptions to ensure consistent error reporting?
MetaGPT centralizes exception handling in metagpt/utils/exceptions.py through the handle_exception function. This utility wraps low-level operations (such as file I/O in metagpt/utils/file.py or S3 interactions) to log the full error context and stack trace before re-raising enriched exceptions. This ensures that debugging and troubleshooting errors during agent actions produces uniform log entries across the entire codebase, eliminating fragmented error handling patterns.
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 →