In daily work, writing personal and team weekly reports is a tedious and monotonous task. Fortunately, this scenario is very suitable for leveraging artificial intelligence (AI) technology to simplify the process. Although there are various GPT-based agents available in the market, such as Wenxin Yiyan, iFlytek Spark, and Zhipu Qingyan, which can summarize content provided by users, they cannot create content from scratch without user input. Moreover, there is currently no effective solution in the market for summarizing the workflows of department members for team weekly reports.
To address this issue, I adopted a multi-agent collaboration approach and chose the CrewAI framework to build an automated secretary team. CrewAI is a framework focused on multi-agent collaboration, showcasing significant advantages in team collaboration capabilities, communication interfaces, built-in algorithms, parallel computing, scalability, and application scenarios.
If you want to learn more about CrewAI, you can check out this article on WeChat. “Follow my steps to easily create AI agents”.
Next, I will share how to use the CrewAI framework to create multi-agent applications to automatically organize, summarize, and send weekly reports for department members.
Preparation:
First, to achieve this workflow, we need to clarify the roles, tasks, and required tools for the agents. Since our goal is to compile individual weekly reports into a team report, I developed custom tools to operate on Yuque documents and Alibaba Cloud email, all built according to CrewAI specifications.

Core Files and Agent Definitions:
In the core files of CrewAI, agents.yaml
and tasks.yaml
define the agents and tasks, while crew.py
and main.py
define the logic and input information for the agents.
-
agents.yaml: In this file, we define two agents, one for obtaining individual weekly reports and summarizing them into a team weekly report, and the other for sending emails and publishing Yuque documents. For example:
writer:
role: >
Weekly Report Writer
goal: >
Summarize the weekly reports of department members into a team report.
backstory: >
You are a secretary to the manager, responsible for compiling the weekly reports of department members into a team report. You need to review each member's weekly report to ensure they are accurate, then summarize them into a team report.
sender:
role: >
Email and Yuque Sender
goal: >
Send emails and Yuque documents to the leaders
backstory: >
You are an email and Yuque sender, responsible for sending emails and Yuque documents to the leaders. You need to send the team weekly report to the leaders, ensuring the email content is correct and not creating attachments separately.
-
tasks.yaml: In this file, we define two tasks, one for summarizing weekly report content and organizing the document in Markdown format; the other task is to send the organized report to the leaders.
writing_task:
description: >
Summarize the weekly reports of department members into a team report.
Ensure the final document is in Chinese.
Avoid content compression as much as possible, ensuring all work content is included.
Do not list names; just write down the work done.
Call the member report retrieval tool only once; do not call it repeatedly, as each call retrieves the same information.
After completing the overall creation of the department report, confirm with the human whether to send the email and publish the Yuque document.
The final team report should be filled out according to the following sample, output in markdown format:
## Key Work This Week
### Product A Related
* xxxx 5.5.6: Fixed backend bugs this week.
* XXXX 6 & 6.2 Development: Planned to fix issues raised during XXX 6.0 testing and develop XXX 6.2.
### XXX Project
* Multiple optimizations were made, including alarm rules, log download interfaces, node management interfaces, etc.
* Planned for project maintenance and version adaptation.
### Frontend Logic
...
## Plans for Next Week
* Continue development and issue handling related to XXX 6.
* Subsequent development of XXX 3.0 page components.
...
expected_output: >
A markdown formatted team report.
send_task:
description: >
Send emails and Yuque documents to relevant leaders.
Do not send emails or publish Yuque documents until the compilation is complete.
Ensure the content parameter for sending emails and publishing Yuque is the markdown formatted team report content.
Email content example:
This week, the main work completed is... Below are the details:
[Compiled Department Weekly Report]
***********************************************************************
Zhang San /Zhangsan
Mobile: 86-13122223333;
Email: [email protected]
XXXXXXX Company / XXXXXXXX Technology Ltd.
***********************************************************************
Yuque document content example:
[Compiled markdown formatted department weekly report]
expected_output: >
Was the task completed?
Agent Logic Orchestration:
In crew.py
, we orchestrate the workflow of the agents by defining the WeeklyReportCrew
class. Each agent has its own role and goal; for instance, the writer
agent aims to summarize the weekly reports of department members, while the sender
agent is responsible for sending the report to the leaders.
from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task
from weekly_report.tools.ali_mail import SendEmailTool
from weekly_report.tools.send_yuque_doc import SendYuqueDocTool
from weekly_report.utils.llms import LLMs
from langchain.agents import load_tools
# Uncomment the following line to use an example of a custom tool
from weekly_report.tools.weekly_reports import GetWeeklyReportsTool
# Check our tools documentations for more information on how to use them
# from crewai_tools import SerperDevTool
llm = LLMs(model_name="glm-3-turbo").get_llm()
function_calling_llm = LLMs(model_name="gpt-3.5-turbo-0125").get_llm()
get_weekly_reports_tool = GetWeeklyReportsTool()
send_email_tool = SendEmailTool()
send_yuque_doc_tool = SendYuqueDocTool()
human_tools = load_tools(["human"])
@CrewBase
class WeeklyReportCrew():
"""WeeklyReport crew"""
agents_config = 'config/agents.yaml'
tasks_config = 'config/tasks.yaml'
@agent
def writer(self) -> Agent:
return Agent(
config=self.agents_config['writer'],
tools=[get_weekly_reports_tool],
verbose=True,
llm=llm,
function_calling_llm=function_calling_llm,
allow_delegation=True
)
@agent
def sender(self) -> Agent:
return Agent(
config=self.agents_config['sender'],
tools=[send_email_tool, send_yuque_doc_tool],
verbose=True,
llm=llm,
function_calling_llm=function_calling_llm,
allow_delegation=True
)
@task
def writing_task(self) -> Task:
return Task(
config=self.tasks_config['writing_task'],
agent=self.writer(),
# context=[self.manage_task()]
)
@task
def send_task(self) -> Task:
return Task(
config=self.tasks_config['send_task'],
agent=self.sender(),
context=[self.writing_task()]
)
@crew
def crew(self) -> Crew:
"""Creates the WeeklyReport crew"""
return Crew(
agents=self.agents, # Automatically created by the @agent decorator
tasks=self.tasks, # Automatically created by the @task decorator
# process=Process.sequential,
verbose=2,
process=Process.hierarchical, # In case you wanna use that instead https://docs.crewai.com/how-to/Hierarchical/
manager_llm=function_calling_llm,
)
Custom Tool Development:
In the CrewAI framework, custom tools are implemented through Python classes that inherit from BaseTool
and complete specific tasks as needed. For example, SendEmailTool
and SendYuqueDocTool
are two tools used for sending emails and publishing Yuque documents.
-
SendEmailTool: This tool is responsible for sending emails containing the weekly report content. It uses Python’s smtplib
library to send emails through Alibaba Cloud’s corporate email. The input for the tool is a string containing the email content, and the output is the success or failure message of the sending process.
import os
from dotenv import load_dotenv
from crewai_tools import BaseTool
from pydantic.v1 import BaseModel, Field
from typing import Type, List
class SendEmailInput(BaseModel):
content: str = Field(..., title="Email Body", description="Specific content of the weekly report")
class SendEmailTool(BaseTool):
name: str = "Email Sending Tool"
description: str = "Tool for sending department weekly report emails, title and recipient do not need to be filled, fixed to AI&UI group weekly report"
args_schema: Type[BaseModel] = SendEmailInput
def send_email(self, content: str):
load_dotenv()
# Configure Alibaba corporate email
mail_host = "smtp.qiye.aliyun.com"
sender = os.getenv("ALI_SENDER")
passwd = os.getenv("ALI_PASSWD")
import smtplib
from email.mime.text import MIMEText
from email.header import Header
from email.utils import formataddr
receivers = os.getenv("ALI_RECEIVERS")
# Send email in markdown format
content = f"""{content}"""
import markdown2
content = markdown2.markdown(content)
print(content)
print(sender)
print(receivers)
msg = MIMEText(content, 'html', 'utf-8')
msg['From'] = formataddr(["xdfs", sender])
msg['To'] = receivers
msg['Subject'] = Header("AI&UI Group Weekly Report", 'utf-8').encode()
print(msg)
to_list = receivers.split(',')
try:
server = smtplib.SMTP_SSL(mail_host, 465)
server.login(sender, passwd)
server.sendmail(sender, to_list, msg.as_string())
server.close()
return 'Email sent successfully'
except Exception as e:
return 'Email sending failed %s' % e
def _run(self, content: str) -> str:
load_dotenv()
result = self.send_email(content)
return result
-
SendYuqueDocTool: This tool is used to publish the weekly report in Markdown format to the Yuque knowledge base. It uses the Yuque API to create new documents and uses the report content as the document body. The input for the tool is the Markdown formatted report content, and the output is the success or failure message of the publishing process.
from crewai_tools import BaseTool
from dotenv import load_dotenv
import os
import requests
class SendYuqueDocTool(BaseTool):
name: str = "Send Yuque Document Tool"
description: str = "Tool for sending or publishing Yuque documents to the Yuque knowledge base"
def get_this_friday(self):
import datetime
today = datetime.date.today()
today_weekday = today.weekday()
print(today_weekday)
if today_weekday == 4:
return today
elif today_weekday > 4:
return today - datetime.timedelta(days=(today_weekday-4) % 7)
else:
return today + datetime.timedelta(days=(4 - today_weekday) % 7)
def _run(self, content: str) -> str:
load_dotenv()
auth_token = os.getenv("YUQUE_AUTH_TOKEN")
login = os.getenv("YUQUE_LOGIN")
slug = os.getenv("YUQUE_SLUG")
# Get the UUID of the directory where the report is located
get_toc_url = f"https://www.yuque.com/api/v2/repos/{login}/{slug}/toc"
header = {"X-Auth-Token": auth_token}
res_toc = requests.get(get_toc_url, headers=header)
toc = res_toc.json()
this_friday = self.get_this_friday().strftime("%Y%m%d")
print(this_friday)
target_uuid = ""
for item in toc["data"]:
if item["type"] == "TITLE" and item["title"] == this_friday:
target_uuid = item["uuid"]
break
print(target_uuid)
# Need to separately call the update directory interface to update the document to the directory
if target_uuid == "":
return "Weekly report directory not found"
create_doc_url = f"https://www.yuque.com/api/v2/repos/{login}/{slug}/docs"
header = {"X-Auth-Token": auth_token}
data = {
"title": "Department Weekly Report",
"format": "markdown",
"body": content
}
created_article = requests.post(create_doc_url, headers=header, data=data)
update_toc_url = f"https://www.yuque.com/api/v2/repos/{login}/{slug}/toc"
data = {
"action": "appendNode",
"action_mode": "child",
"type": "DOC",
"doc_ids": [created_article.json()["data"]["id"]],
"target_uuid": target_uuid
}
response = requests.put(update_toc_url, headers=header, json=data)
return "Yuque document created successfully!"
Execution Process:
-
Retrieve Weekly Reports: The writer
agent first uses theGetWeeklyReportsTool
to retrieve the personal weekly reports from Yuque. -
Summarize Weekly Reports: Then, the writer
agent summarizes this information into a complete team weekly report, formatting it according to the predefined Markdown template. -
Send Weekly Reports: After confirming the report content is correct, the sender
agent uses theSendEmailTool
to send the report via email to the leaders and uses theSendYuqueDocTool
to publish the report to the Yuque knowledge base.
Pitfall Guide:
-
If you are not using OpenAI’s LLM, you need to specify the LLM you are using. -
If using domestic LLMs, be sure to specify a foreign LLM as function_calling_llm
to avoid potential errors. -
Although the current tasks are sequential, using hierarchical
process mode is more effective thansequential
. -
For generated content, it is best to provide a clear template to ensure accuracy and consistency.
Through the steps outlined above, we successfully built an automated secretary team capable of efficiently organizing, summarizing, and sending weekly reports. This not only saves a significant amount of human resources but also improves work efficiency and accuracy. I hope this article can help you apply AI technology in your actual work to automate workflows.
Due to space limitations, I cannot provide a detailed explanation of the code. If you are interested in this topic or need further assistance, feel free to add me on WeChat for communication. If you are interested in the complete source code, please follow my WeChat account and contact me.