-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Implement CrewAI Flows for agentic workflow - GitHub Issue #168 #170
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Implement CrewAI Flows for agentic workflow - GitHub Issue #168 #170
Conversation
Resolves GitHub Issue patchy631#168: Replace current implementation with CrewAI flows ### What Changed: - ✅ Implemented event-driven CrewAI Flows architecture - ✅ Added structured state management with Pydantic models - ✅ Created modular, reusable flow components - ✅ Enhanced error handling and debugging capabilities - ✅ Maintained backwards compatibility with original implementation ### New Files: - `news_flow.py`: Core CrewAI Flow implementation with AINewsGeneratorFlow - `app_flow.py`: Streamlit UI using the new flows architecture - `demo_flow.py`: Programmatic usage examples and demos - `test_flow.py`: Comprehensive testing suite - `test_simple.py`: Structure validation without dependencies - `requirements.txt`: Updated dependency specifications ### Key Features: - **Event-Driven Architecture**: @start/@listen decorators for flow control - **State Management**: NewsFlowState with ResearchReport & BlogPost models - **Better UX**: Enhanced progress tracking and error messages - **Modularity**: Reusable flow components for research & content generation - **Backwards Compatibility**: Original app.py preserved and functional ### Benefits: - 🔄 Event-driven workflow execution - 📊 Structured data flow between agents - 🛠️ Improved debugging and error handling - 🧩 Modular, testable components - ⚡ Better state persistence ### Usage: ```bash # New flows implementation (recommended) streamlit run app_flow.py # Legacy implementation (backwards compatibility) streamlit run app.py # Programmatic usage python demo_flow.py "AI trends" ``` 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
WalkthroughA new modular AI News Generator system is introduced using CrewAI Flows, with extensive documentation, a Streamlit app, a programmatic demo, and comprehensive testing. The new flow-based architecture features event-driven orchestration, structured state management, and clear separation of research and content generation phases. Legacy and new implementations are documented side-by-side. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant StreamlitApp
participant NewsFlow
participant ResearchAgent
participant WriterAgent
User->>StreamlitApp: Enter topic, temperature, click Generate
StreamlitApp->>NewsFlow: kickoff_news_flow(topic, temperature)
NewsFlow->>ResearchAgent: conduct_research(topic)
ResearchAgent-->>NewsFlow: ResearchReport
NewsFlow->>WriterAgent: generate_content(ResearchReport)
WriterAgent-->>NewsFlow: BlogPost
NewsFlow-->>StreamlitApp: Final output (blog, research, stats)
StreamlitApp-->>User: Display blog post, research, download option
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. ✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (15)
ai_news_generator/test_flow.py (2)
11-11
: Remove unused imports.The
Mock
andpatch
imports fromunittest.mock
are not used in the test code and should be removed to keep the imports clean.-from unittest.mock import Mock, patch
95-95
: Remove unnecessary f-string prefix.The f-string on line 95 doesn't contain any placeholders, so the
f
prefix is unnecessary.- print(f"✅ Integration test passed!") + print("✅ Integration test passed!")ai_news_generator/README.md (2)
27-28
: Minor markdown formatting fix.The static analysis tool suggests fixing the unordered list indentation for better consistency.
- - [Serper API Key](https://serper.dev/) - - [Cohere API Key](https://dashboard.cohere.com/api-keys) +- [Serper API Key](https://serper.dev/) +- [Cohere API Key](https://dashboard.cohere.com/api-keys)
77-83
: Consider adding language specification to code block.For better syntax highlighting and clarity, consider specifying the language for the architecture diagram code block.
-``` +```text 🔍 Research Phase (@start) ↓ ✍️ Content Generation (@listen) ↓ 🏁 Finalization (@listen)</blockquote></details> <details> <summary>ai_news_generator/test_simple.py (1)</summary><blockquote> `7-7`: **Remove unused import.** The `importlib.util` import is not used anywhere in the code and should be removed. ```diff import sys -import importlib.util from pathlib import Path
ai_news_generator/app_flow.py (2)
1-1
: Remove unused import.The
os
module is imported but never used in the code.-import os import streamlit as st
3-3
: Remove unused import.
AINewsGeneratorFlow
is imported but not directly used in the app code. Onlycreate_news_flow
is actually needed.-from news_flow import create_news_flow, AINewsGeneratorFlow +from news_flow import create_news_flowai_news_generator/demo_flow.py (3)
84-111
: Remove unnecessary f-string prefixes and unused variable.Static analysis correctly identified several unnecessary f-string prefixes and an unused variable assignment.
- print(f"📋 Initial state:") + print("📋 Initial state:") print(f" Topic: {flow.state.topic}") print(f" Temperature: {flow.state.temperature}") print(f" Research report: {flow.state.research_report}") print(f" Final blog post: {flow.state.final_blog_post}") # Execute the flow print("\n🔄 Executing flow...") - result = flow.kickoff() + flow.kickoff() # Inspect final state - print(f"\n📋 Final state:") + print("\n📋 Final state:") print(f" Research report exists: {flow.state.research_report is not None}") print(f" Blog post exists: {flow.state.final_blog_post is not None}") if flow.state.research_report: print(f" Research citations: {len(flow.state.research_report.citations)}") print(f" Executive summary: {len(flow.state.research_report.executive_summary)} chars") if flow.state.final_blog_post: print(f" Blog title: {flow.state.final_blog_post.title}") print(f" Blog word count: {flow.state.final_blog_post.word_count}") # Use convenience methods - print(f"\n📄 Content preview (first 200 chars):") + print("\n📄 Content preview (first 200 chars):") content = flow.get_blog_content()
155-155
: Remove unnecessary f-string prefix.- print(f"\n📊 BATCH RESULTS:") + print("\n📊 BATCH RESULTS:")
219-221
: Remove unnecessary f-string prefixes.- print(f"\n💡 Next steps:") - print(f" - Run: streamlit run app_flow.py") - print(f" - Or use: from news_flow import kickoff_news_flow") + print("\n💡 Next steps:") + print(" - Run: streamlit run app_flow.py") + print(" - Or use: from news_flow import kickoff_news_flow")ai_news_generator/news_flow.py (5)
1-11
: Remove unused import.The
os
module is imported but never used in this file.#!/usr/bin/env python -import os from typing import Optional from pydantic import BaseModel, Field
48-54
: Consider making the LLM model configurable.The LLM model is hardcoded to "command-r". Consider making it configurable for flexibility.
def _setup_llm(self): """Initialize the LLM with proper configuration""" + model_name = os.getenv('LLM_MODEL', 'command-r') self.llm = LLM( - model="command-r", + model=model_name, temperature=self.state.temperature if self.state else 0.7 )Note: This would require keeping the
os
import.
109-122
: Consider adding error handling for API failures.The research phase could fail due to API issues. Consider wrapping the execution in error handling.
# Execute research task research_crew = Crew( agents=[senior_research_analyst], tasks=[research_task], verbose=True ) - result = research_crew.kickoff() - - # Store research results in state - self.state.research_report = result.pydantic + try: + result = research_crew.kickoff() + # Store research results in state + self.state.research_report = result.pydantic + except Exception as e: + print(f"❌ Research phase failed: {e}") + raise print(f"✅ Research phase completed for: {self.state.topic}") return result
173-186
: Add consistent error handling.For consistency with the suggested error handling in
conduct_research
, consider adding similar error handling here.# Execute writing task writing_crew = Crew( agents=[content_writer], tasks=[writing_task], verbose=True ) - result = writing_crew.kickoff() - - # Store blog post results in state - self.state.final_blog_post = result.pydantic + try: + result = writing_crew.kickoff() + # Store blog post results in state + self.state.final_blog_post = result.pydantic + except Exception as e: + print(f"❌ Content generation failed: {e}") + raise print(f"✅ Content generation completed for: {self.state.topic}") return result
207-207
: Remove unnecessary f-string prefix.- print(f"✅ Flow completed successfully!") + print("✅ Flow completed successfully!")
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
ai_news_generator/__pycache__/news_flow.cpython-311.pyc
is excluded by!**/*.pyc
📒 Files selected for processing (7)
ai_news_generator/README.md
(2 hunks)ai_news_generator/app_flow.py
(1 hunks)ai_news_generator/demo_flow.py
(1 hunks)ai_news_generator/news_flow.py
(1 hunks)ai_news_generator/requirements.txt
(1 hunks)ai_news_generator/test_flow.py
(1 hunks)ai_news_generator/test_simple.py
(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
ai_news_generator/README.md (1)
ai_news_generator/app.py (1)
generate_content
(48-143)
ai_news_generator/test_simple.py (2)
ai_news_generator/demo_flow.py (1)
main
(167-221)ai_news_generator/test_flow.py (1)
main
(101-124)
ai_news_generator/test_flow.py (1)
ai_news_generator/news_flow.py (6)
NewsFlowState
(26-31)AINewsGeneratorFlow
(33-232)create_news_flow
(235-251)get_blog_content
(218-224)get_research_summary
(226-232)kickoff_news_flow
(254-267)
🪛 markdownlint-cli2 (0.17.2)
ai_news_generator/README.md
27-27: Unordered list indentation
Expected: 0; Actual: 3
(MD007, ul-indent)
28-28: Unordered list indentation
Expected: 0; Actual: 3
(MD007, ul-indent)
77-77: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
85-85: Trailing punctuation in heading
Punctuation: ':'
(MD026, no-trailing-punctuation)
92-92: Trailing punctuation in heading
Punctuation: ':'
(MD026, no-trailing-punctuation)
🪛 LanguageTool
ai_news_generator/README.md
[style] ~139-~139: Using many exclamation marks might seem excessive (in this case: 5 exclamation marks for a text that’s 2746 characters long)
Context: ... Contribution Contributions are welcome! Please fork the repository and submit a...
(EN_EXCESSIVE_EXCLAMATION)
🪛 Ruff (0.12.2)
ai_news_generator/test_simple.py
7-7: importlib.util
imported but unused
Remove unused import: importlib.util
(F401)
ai_news_generator/test_flow.py
11-11: unittest.mock.Mock
imported but unused
Remove unused import
(F401)
11-11: unittest.mock.patch
imported but unused
Remove unused import
(F401)
95-95: f-string without any placeholders
Remove extraneous f
prefix
(F541)
ai_news_generator/app_flow.py
1-1: os
imported but unused
Remove unused import: os
(F401)
3-3: news_flow.AINewsGeneratorFlow
imported but unused
Remove unused import: news_flow.AINewsGeneratorFlow
(F401)
ai_news_generator/demo_flow.py
84-84: f-string without any placeholders
Remove extraneous f
prefix
(F541)
92-92: Local variable result
is assigned to but never used
Remove assignment to unused variable result
(F841)
95-95: f-string without any placeholders
Remove extraneous f
prefix
(F541)
108-108: f-string without any placeholders
Remove extraneous f
prefix
(F541)
155-155: f-string without any placeholders
Remove extraneous f
prefix
(F541)
219-219: f-string without any placeholders
Remove extraneous f
prefix
(F541)
220-220: f-string without any placeholders
Remove extraneous f
prefix
(F541)
221-221: f-string without any placeholders
Remove extraneous f
prefix
(F541)
ai_news_generator/news_flow.py
2-2: os
imported but unused
Remove unused import: os
(F401)
207-207: f-string without any placeholders
Remove extraneous f
prefix
(F541)
🔇 Additional comments (13)
ai_news_generator/requirements.txt (1)
1-5
: LGTM!The dependency versions and selection look appropriate for the CrewAI Flows implementation. Using minimum version constraints (>=) provides good flexibility while ensuring compatibility.
ai_news_generator/test_flow.py (2)
66-100
: LGTM - Well-structured integration test!The integration test properly checks for API key prerequisites and gracefully skips when they're not available. The validation of the result structure is thorough and appropriate.
14-64
: LGTM - Comprehensive unit tests!The unit tests provide good coverage of the state model, flow initialization, structure validation, and convenience methods. The test organization and assertions are well-structured.
ai_news_generator/README.md (1)
8-143
: Excellent documentation structure!The README provides comprehensive coverage of both legacy and new implementations, clear installation instructions, testing guidance, and a helpful migration guide. The architecture explanation effectively communicates the benefits of the CrewAI Flows approach.
ai_news_generator/test_simple.py (1)
10-178
: Excellent structural validation approach!This lightweight validation script is perfect for early-stage testing without external dependencies. The comprehensive checks for file structure, syntax, imports, class definitions, decorators, and requirements provide valuable feedback for development and CI/CD pipelines.
ai_news_generator/app_flow.py (3)
70-161
: Excellent user experience implementation!The flow execution logic provides excellent user feedback with progress bars, real-time status updates, state visualization, and comprehensive error handling. The multi-column layout effectively separates content from progress tracking.
23-69
: Well-designed sidebar interface!The sidebar provides intuitive controls with helpful expandable sections explaining CrewAI Flows and usage instructions. The temperature slider and prominent generate button create a good user experience.
165-208
: Great architectural visualization!The flow architecture section effectively communicates the event-driven structure with clear phase descriptions and code examples showing the decorator pattern.
ai_news_generator/demo_flow.py (3)
1-22
: LGTM!Good setup with proper shebang, comprehensive docstring with usage examples, and appropriate imports for the demo functionality.
23-38
: LGTM!Well-implemented API key validation with clear user feedback.
223-224
: LGTM!Proper implementation of the main guard pattern.
ai_news_generator/news_flow.py (2)
218-233
: LGTM!Well-implemented convenience methods with safe fallback values.
234-276
: LGTM!Well-designed factory functions with clear documentation and helpful example usage in the main guard.
filename = f"demo_output_{topic.lower().replace(' ', '_')}.md" | ||
with open(filename, 'w') as f: | ||
f.write(result['blog_post']) | ||
print(f" Saved to: {filename}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Sanitize filename to avoid filesystem issues.
The filename generation could fail with special characters in the topic. Consider sanitizing the filename more robustly.
- filename = f"demo_output_{topic.lower().replace(' ', '_')}.md"
+ import re
+ safe_topic = re.sub(r'[^\w\s-]', '', topic.lower()).strip()
+ safe_topic = re.sub(r'[-\s]+', '_', safe_topic)
+ filename = f"demo_output_{safe_topic}.md"
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
filename = f"demo_output_{topic.lower().replace(' ', '_')}.md" | |
with open(filename, 'w') as f: | |
f.write(result['blog_post']) | |
print(f" Saved to: {filename}") | |
import re | |
safe_topic = re.sub(r'[^\w\s-]', '', topic.lower()).strip() | |
safe_topic = re.sub(r'[-\s]+', '_', safe_topic) | |
filename = f"demo_output_{safe_topic}.md" | |
with open(filename, 'w') as f: | |
f.write(result['blog_post']) | |
print(f" Saved to: {filename}") |
🤖 Prompt for AI Agents
In ai_news_generator/demo_flow.py around lines 58 to 61, the filename is
generated by directly transforming the topic string, which may include special
characters causing filesystem errors. To fix this, sanitize the topic string by
removing or replacing any characters that are not alphanumeric, underscores, or
hyphens before constructing the filename. Use a robust method such as a regex
substitution to ensure the filename is safe for all filesystems.
class ResearchReport(BaseModel): | ||
"""Model for research report output""" | ||
executive_summary: str = Field(description="Executive summary of key findings") | ||
analysis: str = Field(description="Comprehensive analysis of current trends and developments") | ||
facts_and_statistics: str = Field(description="List of verified facts and statistics") | ||
citations: list[str] = Field(description="All citations and links to original sources", default=[]) | ||
main_themes: str = Field(description="Clear categorization of main themes and patterns") | ||
|
||
class BlogPost(BaseModel): | ||
"""Model for blog post output""" | ||
title: str = Field(description="Blog post title") | ||
content: str = Field(description="Full blog post content in markdown format") | ||
word_count: int = Field(description="Approximate word count", default=0) | ||
|
||
class NewsFlowState(BaseModel): | ||
"""State management for the AI News Generation Flow""" | ||
topic: str = Field(description="The topic to research and write about") | ||
temperature: float = Field(description="LLM temperature setting", default=0.7) | ||
research_report: Optional[ResearchReport] = None | ||
final_blog_post: Optional[BlogPost] = None | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
❓ Verification inconclusive
Well-structured Pydantic models!
The models are well-designed with clear field descriptions. Note that Line 17 uses list[str]
syntax which requires Python 3.9+. Ensure the project documentation specifies this requirement.
🏁 Script executed:
#!/bin/bash
# Check if Python version requirement is documented
rg -A 2 "python" requirements.txt README.md setup.py pyproject.toml 2>/dev/null | head -20
Length of output: 78
Well-structured Pydantic models!
The models are well-designed with clear field descriptions. Line 17’s use of list[str]
requires Python 3.9+. I searched README.md, setup.py and pyproject.toml and didn’t find any documented Python version requirement. Please add the minimum Python version to your project metadata, for example:
- In setup.py:
setup( …, python_requires=">=3.9", … )
- Or in pyproject.toml:
[project] requires-python = ">=3.9"
- And consider adding a note about this requirement to the README.
🤖 Prompt for AI Agents
In ai_news_generator/news_flow.py around lines 12 to 32, the use of list[str]
requires Python 3.9 or higher, but the project metadata does not specify a
minimum Python version. To fix this, add a python version requirement of >=3.9
in your setup.py by including python_requires=">=3.9" in the setup() call or in
pyproject.toml by adding requires-python = ">=3.9" under the [project] section.
Also, update the README.md to document this minimum Python version requirement
for clarity.
Summary
This PR implements CrewAI Flows to create an agentic workflow for the ai_news_generator project, resolving GitHub Issue #168.
What Changed
✅ Implemented CrewAI Flows Architecture
@start()
and@listen()
decorators✅ New Flow-Based Implementation
news_flow.py
: Core AINewsGeneratorFlow with structured phasesapp_flow.py
: Enhanced Streamlit UI with real-time progress tracking✅ Backwards Compatibility
app.py
preserved and fully functionalKey Benefits
Architecture
Files Added
ai_news_generator/news_flow.py
- Core CrewAI Flow implementationai_news_generator/app_flow.py
- Enhanced Streamlit interfaceai_news_generator/demo_flow.py
- Programmatic usage examplesai_news_generator/test_flow.py
- Comprehensive test suiteai_news_generator/test_simple.py
- Structure validationai_news_generator/requirements.txt
- Updated dependenciesUsage
New CrewAI Flows Implementation (Recommended):
Legacy Implementation (Backwards Compatibility):
Programmatic Usage:
Testing
All structural validations pass:
Test plan
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation
Tests
Chores