diff --git a/src/crewai/task.py b/src/crewai/task.py index 754fab491..96e52cad5 100644 --- a/src/crewai/task.py +++ b/src/crewai/task.py @@ -135,6 +135,10 @@ class Task(BaseModel): description="Whether the task should have a human review the final answer of the agent", default=False, ) + markdown: Optional[bool] = Field( + description="Whether the task should instruct the agent to return the final answer formatted in Markdown", + default=False, + ) converter_cls: Optional[Type[Converter]] = Field( description="A converter class used to export structured output", default=None, @@ -522,10 +526,14 @@ class Task(BaseModel): return guardrail_result def prompt(self) -> str: - """Prompt the task. - + """Generates the task prompt with optional markdown formatting. + + When the markdown attribute is True, instructions for formatting the + response in Markdown syntax will be added to the prompt. + Returns: - Prompt of the task. + str: The formatted prompt string containing the task description, + expected output, and optional markdown formatting instructions. """ tasks_slices = [self.description] @@ -533,6 +541,17 @@ class Task(BaseModel): expected_output=self.expected_output ) tasks_slices = [self.description, output] + + if self.markdown: + markdown_instruction = """Your final answer MUST be formatted in Markdown syntax. +Follow these guidelines: +- Use # for headers +- Use ** for bold text +- Use * for italic text +- Use - or * for bullet points +- Use `code` for inline code +- Use ```language for code blocks""" + tasks_slices.append(markdown_instruction) return "\n".join(tasks_slices) def interpolate_inputs_and_add_conversation_history( diff --git a/tests/test_markdown_task.py b/tests/test_markdown_task.py new file mode 100644 index 000000000..873d18550 --- /dev/null +++ b/tests/test_markdown_task.py @@ -0,0 +1,96 @@ +"""Test the markdown attribute in Task class.""" + +import pytest +from pydantic import BaseModel + +from crewai import Agent, Task + + +@pytest.mark.parametrize( + "markdown_enabled,should_contain_instructions", + [ + (True, True), + (False, False), + ], +) +def test_markdown_option_in_task_prompt(markdown_enabled, should_contain_instructions): + """Test that markdown flag correctly controls the inclusion of markdown formatting instructions.""" + + researcher = Agent( + role="Researcher", + goal="Research a topic", + backstory="You're a researcher specialized in providing well-formatted content.", + allow_delegation=False, + ) + + task = Task( + description="Research advances in AI in 2023", + expected_output="A summary of key AI advances in 2023", + markdown=markdown_enabled, + agent=researcher, + ) + + prompt = task.prompt() + + assert "Research advances in AI in 2023" in prompt + assert "A summary of key AI advances in 2023" in prompt + + if should_contain_instructions: + assert "Your final answer MUST be formatted in Markdown syntax." in prompt + assert "Use # for headers" in prompt + assert "Use ** for bold text" in prompt + else: + assert "Your final answer MUST be formatted in Markdown syntax." not in prompt + + +def test_markdown_with_empty_description(): + """Test markdown formatting with empty description.""" + + researcher = Agent( + role="Researcher", + goal="Research a topic", + backstory="You're a researcher.", + allow_delegation=False, + ) + + task = Task( + description="", + expected_output="A summary", + markdown=True, + agent=researcher, + ) + + prompt = task.prompt() + + assert prompt.strip() != "" + assert "A summary" in prompt + assert "Your final answer MUST be formatted in Markdown syntax." in prompt + + +def test_markdown_with_complex_output_format(): + """Test markdown with JSON output format to ensure compatibility.""" + + class ResearchOutput(BaseModel): + title: str + findings: list[str] + + researcher = Agent( + role="Researcher", + goal="Research a topic", + backstory="You're a researcher.", + allow_delegation=False, + ) + + task = Task( + description="Research topic", + expected_output="Research results", + markdown=True, + output_json=ResearchOutput, + agent=researcher, + ) + + prompt = task.prompt() + + assert "Your final answer MUST be formatted in Markdown syntax." in prompt + assert "Research topic" in prompt + assert "Research results" in prompt