첫 번째 CrewAI 에이전트 만들기
주제나 주제에 대해 연구
하고 보고서
를 작성하는 간단한 크루를 만들어보자. 이를 통해 최신 AI 개발 동향
을 파악할 수 있다.
시작하기 전에 crewai
와 crewai-tools
가 설치되어 있는지 확인한다. 아직 설치하지 않았다면 설치 가이드를 참고해 설치한다.
아래 단계를 따라 크루를 만들어보자! 🚣♂️
크루 생성
터미널에서 다음 커맨드를 실행해 새로운 크루 프로젝트를 생성한다. 이 명령어는 latest-ai-development
라는 디렉토리를 만들고 기본 구조를 구성한다.
`agents.yaml` 파일 수정
필요에 따라 에이전트를 수정하거나 그대로 프로젝트에 복사해 사용할 수 있다. agents.yaml
과 tasks.yaml
파일에서 {topic}
과 같은 변수는 main.py
파일의 값으로 대체된다.
# src/latest_ai_development/config/agents.yaml
researcher:
role: >
{topic} Senior Data Researcher
goal: >
Uncover cutting-edge developments in {topic}
backstory: >
You're a seasoned researcher with a knack for uncovering the latest
developments in {topic}. Known for your ability to find the most relevant
information and present it in a clear and concise manner.
reporting_analyst:
role: >
{topic} Reporting Analyst
goal: >
Create detailed reports based on {topic} data analysis and research findings
backstory: >
You're a meticulous analyst with a keen eye for detail. You're known for
your ability to turn complex data into clear and concise reports, making
it easy for others to understand and act on the information you provide.
`tasks.yaml` 파일 수정
# src/latest_ai_development/config/tasks.yaml
research_task:
description: >
Conduct a thorough research about {topic}
Make sure you find any interesting and relevant information given
the current year is 2025.
expected_output: >
A list with 10 bullet points of the most relevant information about {topic}
agent: researcher
reporting_task:
description: >
Review the context you got and expand each topic into a full section for a report.
Make sure the report is detailed and contains any and all relevant information.
expected_output: >
A fully fledge reports with the mains topics, each with a full section of information.
Formatted as markdown without '```'
agent: reporting_analyst
output_file: report.md
`crew.py` 파일 수정
# src/latest_ai_development/crew.py
from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task
from crewai_tools import SerperDevTool
@CrewBase
class LatestAiDevelopmentCrew():
"""LatestAiDevelopment crew"""
@agent
def researcher(self) -> Agent:
return Agent(
config=self.agents_config['researcher'],
verbose=True,
tools=[SerperDevTool()]
)
@agent
def reporting_analyst(self) -> Agent:
return Agent(
config=self.agents_config['reporting_analyst'],
verbose=True
)
@task
def research_task(self) -> Task:
return Task(
config=self.tasks_config['research_task'],
)
@task
def reporting_task(self) -> Task:
return Task(
config=self.tasks_config['reporting_task'],
output_file='output/report.md' # This is the file that will be contain the final report.
)
@crew
def crew(self) -> Crew:
"""Creates the LatestAiDevelopment 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=True,
)
[선택 사항] 크루 실행 전후 함수 추가
# src/latest_ai_development/crew.py
from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task, before_kickoff, after_kickoff
from crewai_tools import SerperDevTool
@CrewBase
class LatestAiDevelopmentCrew():
"""LatestAiDevelopment crew"""
@before_kickoff
def before_kickoff_function(self, inputs):
print(f"Before kickoff function with inputs: {inputs}")
return inputs # You can return the inputs or modify them as needed
@after_kickoff
def after_kickoff_function(self, result):
print(f"After kickoff function with result: {result}")
return result # You can return the result or modify it as needed
# ... remaining code
크루에 커스텀 입력 전달
예를 들어 topic
입력을 전달해 연구와 보고서를 커스터마이즈할 수 있다.
#!/usr/bin/env python
# src/latest_ai_development/main.py
import sys
from latest_ai_development.crew import LatestAiDevelopmentCrew
def run():
"""
Run the crew.
"""
inputs = {
'topic': 'AI Agents'
}
LatestAiDevelopmentCrew().crew().kickoff(inputs=inputs)
환경 변수 설정
크루를 실행하기 전에 .env
파일에 다음 키를 환경 변수로 설정한다:
의존성 잠금 및 설치
프로젝트 디렉토리로 이동한 후 CLI 커맨드를 사용해 의존성을 잠그고 설치한다:
크루 실행
프로젝트 루트에서 다음 커맨드를 실행해 크루를 실행한다:
최종 보고서 확인
콘솔에서 출력을 확인하고 프로젝트 루트에 report.md
파일이 생성된다. 이 파일에 최종 보고서가 저장된다.
보고서 예시는 다음과 같다:
이름의 일관성에 대한 주의 사항
YAML 파일(agents.yaml
과 tasks.yaml
)에서 사용하는 이름은 Python 코드의 메서드 이름과 일치해야 한다. 예를 들어, tasks.yaml
파일에서 특정 작업에 대한 에이전트를 참조할 수 있다. 이렇게 이름을 일관되게 유지하면 CrewAI가 자동으로 설정과 코드를 연결할 수 있다. 그렇지 않으면 작업이 참조를 제대로 인식하지 못할 수 있다.
예제 참조
agents.yaml
파일의 에이전트 이름(email_summarizer
)과 crew.py
파일의 메서드 이름(email_summarizer
)이 동일하게 사용된 점을 확인하자.
email_summarizer:
role: >
이메일 요약 담당자
goal: >
이메일을 간결하고 명확한 요약으로 정리
backstory: >
보고서를 5개의 불릿 포인트로 요약
llm: openai/gpt-4o
tasks.yaml
파일의 태스크 이름(email_summarizer_task
)과 crew.py
파일의 메서드 이름(email_summarizer_task
)이 동일하게 사용된 점을 확인하자.
email_summarizer_task:
description: >
이메일을 5개의 불릿 포인트로 요약
expected_output: >
이메일의 5개 불릿 포인트 요약
agent: email_summarizer
context:
- reporting_task
- research_task
crew.py
파일에서 에이전트와 태스크를 올바르게 참조하려면 주석을 활용한다.
주석 사용법
다음은 CrewAI 프로젝트에서 각 주석을 어떻게 사용하는지, 그리고 언제 사용해야 하는지에 대한 예시이다:
@agent
특정 역할을 가진 전문 AI 에이전트를 정의할 때 사용한다. 다음 상황에서 활용할 수 있다:
- 특정 역할을 가진 전문 AI 에이전트를 생성해야 할 때
- 에이전트를 자동으로 수집하고 관리하고자 할 때
- 여러 작업에서 동일한 에이전트 설정을 재사용해야 할 때
@agent
def research_agent(self) -> Agent:
return Agent(
role="Research Analyst",
goal="Conduct thorough research on given topics",
backstory="Expert researcher with years of experience in data analysis",
tools=[SerperDevTool()],
verbose=True
)
@task
에이전트가 실행할 수 있는 작업을 정의할 때 사용한다. 다음 상황에서 활용한다:
- 에이전트에게 특정 작업을 정의할 필요가 있을 때
- 작업을 자동으로 순서화하고 관리하려고 할 때
- 서로 다른 작업 간의 의존성을 설정해야 할 때
@task
def research_task(self) -> Task:
return Task(
description="AI 기술의 최신 동향을 조사한다",
expected_output="AI 발전 상황에 대한 종합 보고서",
agent=self.research_agent(),
output_file="output/research.md"
)
@crew
크루 구성을 정의할 때 사용한다. 다음 상황에서 활용한다:
- 모든 @agent와 @task 정의를 자동으로 수집하고자 할 때
- 작업을 순차적으로 처리할지 계층적으로 처리할지 지정해야 할 때
- 크루 전체 설정을 구성하고자 할 때
@crew
def research_crew(self) -> Crew:
return Crew(
agents=self.agents, # @agent 메서드에서 자동으로 수집됨
tasks=self.tasks, # @task 메서드에서 자동으로 수집됨
process=Process.sequential,
verbose=True
)
에이전트에게 특정 기능을 제공하기 위해 커스텀 도구를 생성할 때 사용한다. 다음과 같은 경우에 활용할 수 있다:
- 에이전트에게 웹 검색이나 데이터 분석 같은 특정 기능이 필요할 때
- 외부 API 호출이나 복잡한 작업을 캡슐화하고 싶을 때
- 여러 에이전트 간에 기능을 공유해야 할 때
@tool
def web_search_tool(query: str, max_results: int = 5) -> list[str]:
"""
웹에서 정보를 검색한다.
Args:
query: 검색어
max_results: 반환할 결과의 최대 개수
Returns:
검색 결과 리스트
"""
# 검색 로직을 구현한다
return [f"Result {i} for: {query}" for i in range(max_results)]
@before_kickoff
크루가 시작하기 전에 로직을 실행할 때 사용한다. 다음과 같은 경우에 활용한다:
- 입력 데이터를 검증하거나 전처리해야 할 때
- 실행 전에 리소스나 설정을 준비해야 할 때
- 초기화 로직을 수행해야 할 때
@before_kickoff
def validate_inputs(self, inputs: Optional[Dict[str, Any]]) -> Optional[Dict[str, Any]]:
"""크루가 시작하기 전에 입력 데이터를 검증하고 전처리한다."""
if inputs is None:
return None
if 'topic' not in inputs:
raise ValueError("토픽은 필수 입력값입니다.")
# 추가 컨텍스트를 포함시킨다
inputs['timestamp'] = datetime.now().isoformat()
inputs['topic'] = inputs['topic'].strip().lower()
return inputs
@after_kickoff
크루 작업이 완료된 후 결과를 처리할 때 사용한다. 다음 상황에서 활용한다:
- 최종 출력을 형식화하거나 변환해야 할 때
- 정리 작업을 수행해야 할 때
- 특정 방식으로 결과를 저장하거나 로깅해야 할 때
@after_kickoff
def process_results(self, result: CrewOutput) -> CrewOutput:
"""크루 작업 완료 후 결과를 처리하고 형식화한다."""
result.raw = result.raw.strip()
result.raw = f"""
# 연구 결과
생성 시간: {datetime.now().isoformat()}
{result.raw}
"""
return result
@callback
이벤트를 처리하기 위해 사용한다. 다음 상황에서 활용할 수 있다:
- 작업 진행 상황을 모니터링해야 할 때
- 중간 결과를 기록하고 싶을 때
- 커스텀 진행 상황 추적이나 메트릭을 구현해야 할 때
@callback
def log_task_completion(self, task: Task, output: str):
"""모니터링을 위해 작업 완료 세부 사항을 기록한다."""
print(f"작업 '{task.description}' 완료")
print(f"출력 길이: {len(output)} 문자")
print(f"사용한 에이전트: {task.agent.role}")
print("-" * 50)
@cache_handler
테스크 결과에 대한 커스텀 캐싱을 구현할 때 사용한다. 다음 상황에서 활용할 수 있다:
- 비용이 많이 드는 작업을 반복하지 않으려 할 때
- 커스텀 캐시 저장소 또는 만료 로직을 구현해야 할 때
- 실행 간에 결과를 유지하고 싶을 때
@cache_handler
def custom_cache(self, key: str) -> Optional[str]:
"""테스크 결과를 저장하기 위한 커스텀 캐시 구현."""
cache_file = f"cache/{key}.json"
if os.path.exists(cache_file):
with open(cache_file, 'r') as f:
data = json.load(f)
# 캐시가 아직 유효한지 확인 (예: 만료되지 않았는지)
if datetime.fromisoformat(data['timestamp']) > datetime.now() - timedelta(days=1):
return data['result']
return None
이 데코레이터는 CrewAI 프레임워크의 일부로, 에이전트와 테스크를 자동으로 수집하고 다양한 라이프사이클 이벤트를 처리함으로써 크루 구조를 조직화하는 데 도움을 준다.
@CrewBase
로 데코레이트된 클래스 내에서 사용해야 한다.
최신 크루 킥오프 작업 재실행
CrewAI는 이제 마지막 실행에서 작업 목록을 확인하고 특정 작업부터 재실행할 수 있는 기능을 제공한다. 이 기능을 사용하려면 다음 명령어를 실행한다.
<task_id>
부분에 재실행하려는 작업의 ID를 입력한다.
크루 메모리 초기화
다시 실행하기 전에 크루의 메모리를 초기화해야 한다면, 메모리 초기화 기능을 호출하면 된다:
crewai reset-memories --all
이 명령어를 실행하면 크루의 메모리가 초기화되어 새로운 시작을 할 수 있다.
프로젝트 배포하기
여러분의 프로젝트를 가장 간단하게 배포하는 방법은 CrewAI Enterprise를 이용하는 것이다. CrewAI Enterprise에서는 클릭 몇 번으로 프로젝트를 배포할 수 있다.