Свое первое знакомство с JSON Crew Project (на Ubuntu 24.04 LTS Server + LLM ollama) я начал с дефолтного создания, как crewai create crew
mkdir ~/project
cd ~/project
crewai create crew ai

Но судя по содержимому файла AGENTS.md существует еще классическое создание проекта, где мастер самостоятельно формирует структуру файлов. Хочу попробовать, может это для меня будет проще. Хотя проще оно станет после того, как набьешь руку в настройке инструмента, а то сейчас я даже и не знаю, как подступиться к своим задумкам.
Шаг №1: Устанавливаю в систему Python3:
ekzorchik@srv-s2404a:~$ sudo apt install -y software-properties-common
ekzorchik@srv-s2404a:~$ sudo add-apt-repository ppa:deadsnakes/ppa
ekzorchik@srv-s2404a:~$ sudo apt install -y python3.13 python3.13-venv python3.13-dev
ekzorchik@srv-s2404a:~$ python3.13 --version
Python 3.13.15
На заметку: я не буду устанавливать crew через утилиту uv, а сделаю это в каталоге проекта через pip
Шаг №2: Создаю каталог под проект:
На заметку: Проект — это получение информации о времени работы текущей Linux-системы.
ekzorchik@srv-s2404a:~$ mkdir project
ekzorchik@srv-s2404a:~$ python3.13 -m venv ~/project/
ekzorchik@srv-s2404a:~$ cd project/
ekzorchik@srv-s2404a:~/project$ source bin/activate
(project) ekzorchik@srv-s2404a:~/project$
(project) ekzorchik@srv-s2404a:~/project$ python -V
Python 3.13.15
(project) ekzorchik@srv-s2404a:~/project$ python -m ensurepip --upgrade
Looking in links: /tmp/tmpstov2f3u
Requirement already satisfied: pip in ./lib/python3.13/site-packages (26.2.1)
(project) ekzorchik@srv-s2404a:~/project$
(project) ekzorchik@srv-s2404a:~/project$ python -m pip install --upgrade pip
Requirement already satisfied: pip in ./lib/python3.13/site-packages (26.2.1)
(project) ekzorchik@srv-s2404a:~/project$
(project) ekzorchik@srv-s2404a:~/project$ python -m pip install crewai
Шаг №3: Отобразить список установленных библиотек в виртуальном окружении:
(project) ekzorchik@srv-s2404a:~/project$ pip list
Шаг №4: Сохранить список всех установленных библиотек в requirements.txt
(crewai) ekzorchik@srv-s2404a:~/project$ python -m pip freeze > requiremenets.txt
Шаг №5: Где находится установленный crewai:
(project) ekzorchik@srv-s2404a:~/project$ whereis crewai
crewai: /home/ekzorchik/project/bin/crewai
(project) ekzorchik@srv-s2404a:~/project$ crewai --version
crewai, version 1.15.22
(project) ekzorchik@srv-s2404a:~/project$
Шаг №6: Базовое использование строится на строке:
crewai [COMMAND] [OPTIONS] [ARGUMENTS]
Шаг №7: Cоздаем классический шаблон:
(project) ekzorchik@srv-s2404a:~/project$ crewai create crew my --classic
Creating folder my... (команда сделала за тебя первоначальную структуру проекта.)
Select a provider to set up:
1. openai
2. anthropic
3. gemini
4. nvidia_nim
5. groq
6. huggingface
7. ollama
8. watson
9. bedrock
10. azure
11. cerebras
12. sambanova
13. other
q. Quit
Enter the number of your choice or 'q' to quit: 7
Select a model to use for Ollama:
1. ollama/llama3.1
q. Quit
Enter the number of your choice or 'q' to quit: 1
API keys and model saved to .env file
Selected model: ollama/llama3.1
- Created my/.gitignore
- Created my/pyproject.toml
- Created my/README.md
- Created my/knowledge/user_preference.txt
- Created my/src/my/__init__.py
- Created my/src/my/main.py
- Created my/src/my/crew.py
- Created my/src/my/tools/custom_tool.py
- Created my/src/my/tools/__init__.py
- Created my/src/my/config/agents.yaml
- Created my/src/my/config/tasks.yaml
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint: git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint: git branch -m <name>
Initialized empty Git repository in /home/ekzorchik/project/my/.git/
Crew my created successfully!
(project) ekzorchik@srv-s2404a:~/project$
Т.е. внутри каталога project создается еще один каталог окружения проекта.
Шаг №8: С учетом действий выше сейчас у меня каркас:

src/my/crew.py — центральное место (Agent -> Task -> Crew)
src/my/main.py — точка запуска — он создалась мастером и в моем редактировании не нуждается.
Initialized empty Git repository in /home/ekzorchik/project/my/.git/ — создан Git-репозитарий
(project) ekzorchik@srv-s2404a:~/project$ cd my
Шаг №9: Обозначаю переменные окружения проекта:
(project) ekzorchik@srv-s2404a:~/project/my$ nano .env
MODEL=ollama/llama3.1:8b
API_BASE=http://localhost:11434
OPENAI_API_KEY=none
CREWAI_TRACING_ENABLED=false
Шаг №10: Небольшое пояснение себе по файлам:
(project) ekzorchik@srv-s2404a:~/project/my$ tree
.
├── AGENTS.md
├── CLAUDE.md
├── GEMINI.md
├── knowledge
│ └── user_preference.txt
├── pyproject.toml
├── README.md
├── src
│ └── my
│ ├── config
│ │ ├── agents.yaml
│ │ └── tasks.yaml
│ ├── crew.py
│ ├── __init__.py
│ ├── main.py
│ └── tools
│ ├── custom_tool.py
│ └── __init__.py
└── tests
7 directories, 13 files
(project) ekzorchik@srv-s2404a:~/project/my$
- src/my/config/agents.yaml — здесь описываем агента
- src/my/config/tasks.yaml — здесь описываем задачу
- src/tools/check_uptime.py — сюда создаем tools
- src/crew.py — здесь подключаем tool к Agent
Шаг №11: Создаем инструмент (находиться будет в каталоге tools) взаимодействия crew с выполняемой задачей:
(project) ekzorchik@srv-s2404a:~/project/my$ nano src/my/tools/check_uptime.py
from crewai.tools import BaseTool
import subprocess
class CheckUptimeTool(BaseTool):
name: str = "check_uptime"
description: str = (
"Информация о том как долго система работает"
)
def _run(self) -> str:
result = subprocess.run(
["uptime", "-p"],
capture_output=True,
text=True,
check=True,
)
return result.stdout.strip()
Шаг №12: Подключаем в crew.py агент:
(project) ekzorchik@srv-s2404a:~/project/my$ nano src/my/crew.py
from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task
from my.tools.check_uptime import CheckUptimeTool
@CrewBase
class My():
"""My crew"""
agents: list[Agent]
tasks: list[Task]
@agent
def check_uptime(self) -> Agent:
return Agent(
config=self.agents_config['check_uptime'],
tools=[CheckUptimeTool()],
verbose=True
)
@task
def check_uptime_task(self) -> Task:
return Task(
config=self.tasks_config['check_uptime_task'],
)
@crew
def crew(self) -> Crew:
"""Creates the My crew"""
return Crew(
agents=self.agents,
tasks=self.tasks,
process=Process.sequential,
verbose=True,
)
Шаг №13: Привожу для себя содержимое main.py — я его не редактировал — это мастер сам его создал:
(project) ekzorchik@srv-s2404a:~/project/my$ cat src/my/main.py
#!/usr/bin/env python
import sys
import warnings
from datetime import datetime
from my.crew import My
warnings.filterwarnings("ignore", category=SyntaxWarning, module="pysbd")
def run():
"""
Run the crew.
"""
inputs = {
'topic': 'AI LLMs',
'current_year': str(datetime.now().year)
}
try:
My().crew().kickoff(inputs=inputs)
except Exception as e:
raise Exception(f"An error occurred while running the crew: {e}")
def train():
"""
Train the crew for a given number of iterations.
"""
inputs = {
"topic": "AI LLMs",
'current_year': str(datetime.now().year)
}
try:
My().crew().train(n_iterations=int(sys.argv[1]), filename=sys.argv[2], inputs=inputs)
except Exception as e:
raise Exception(f"An error occurred while training the crew: {e}")
def replay():
"""
Replay the crew execution from a specific task.
"""
try:
My().crew().replay(task_id=sys.argv[1])
except Exception as e:
raise Exception(f"An error occurred while replaying the crew: {e}")
def test():
"""
Test the crew execution and returns the results.
"""
inputs = {
"topic": "AI LLMs",
"current_year": str(datetime.now().year)
}
try:
My().crew().test(n_iterations=int(sys.argv[1]), eval_llm=sys.argv[2], inputs=inputs)
except Exception as e:
raise Exception(f"An error occurred while testing the crew: {e}")
def run_with_trigger():
"""
Run the crew with trigger payload.
"""
import json
if len(sys.argv) < 2:
raise Exception("No trigger payload provided. Please provide JSON payload as argument.")
try:
trigger_payload = json.loads(sys.argv[1])
except json.JSONDecodeError:
raise Exception("Invalid JSON payload provided as argument")
inputs = {
"crewai_trigger_payload": trigger_payload,
"topic": "",
"current_year": ""
}
try:
result = My().crew().kickoff(inputs=inputs)
return result
except Exception as e:
raise Exception(f"An error occurred while running the crew with trigger: {e}")
(project) ekzorchik@srv-s2404a:~/project/my$
Шаг №14: Изменяем содержимое agents.yaml (убираем двух демонстративных агентов researcher и reporting_analyst и оставляем одного агента check_uptime, которому в crew.py мы уже подключили CheckUptimeTool()):
(project) ekzorchik@srv-s2404a:~/project/my$ nano src/my/config/agents.yaml
check_uptime:
role: >
Linux System Administrator
goal: >
Получить время работы текущей Linux-системы
backstory: >
Ты системный администратор Linux.
Для получения времени работы системы используй инструмент check_uptime.
Не придумывай значение uptime, а используй результат инструмента.
Шаг №15: Изменяем tasks.yaml под единственный инструмент tool:
(project) ekzorchik@srv-s2404a:~/project/my$ nano src/my/config/tasks.yaml
check_uptime_task:
description: >
Получи время работы текущей Linux-системы,
используя инструмент check_uptime.
Не придумывай результат, используй значение,
которое вернул инструмент.
expected_output: >
Точное значение uptime, возвращённое инструментом check_uptime.
agent: check_uptime
Здесь важно соответствие имен:
• check_uptime_task → совпадает с self.tasks_config[‘check_uptime_task’] в crew.py
• agent: check_uptime → совпадает с агентом check_uptime в agents.yaml
• check_uptime → имя инструмента, который подключается через CheckUptimeTool() в crew.py
Шаг №16: Запускаем проект:
(project) ekzorchik@srv-s2404a:~/project/my$ crewai run


Отработало. Да это было не легко, и я до сих пор не понимаю пошаговость.
(project) ekzorchik@srv-s2404a:~/project/my$ deactivate
ekzorchik@srv-s2404a:~/project/my$ cd ~
ekzorchik@srv-s2404a:~$
Шаг №17: Обратил внимание что я же создал виртуальное окружение под Python3.13, а в выводе выше после запуска зацепил взглядом, то используется CPython 3.12.3
То есть происходит примерно так:
~/project/
└── bin/ ← твоё активное venv, Python 3.13
└── crewai
~/project/my/
└── .venv/ ← CrewAI создал отдельное окружение
└── Python 3.12.3
(project) ekzorchik@srv-s2404a:~/project/my$ cat .venv/bin/p
pdf2txt.py pybase64 pygmentize pymupdf pyproject-build python3 pytube
pdfplumber pydoc.bat pyjson5 pypdfium2 python python3.12
(project) ekzorchik@srv-s2404a:~/project/my$ .venv/bin/python3 --version
Python 3.12.3
(project) ekzorchik@srv-s2404a:~/project/my$
У меня сейчас две разные среды:
~/project/
└── bin/python → Python 3.13
~/project/my1/
└── .venv/python → Python 3.12.3
И crewai run выбирает ".venv" проекта.
Шаг №18: С учетом проанализированного, предполагаю, что лучше не заставлять crewai автоматически менять архитектуру, лучше создать проект и явно создать uv, какую среду использовать (чтобы из нее бралась используемая версия Python3.13), вот только переменные окружения ".env" нужно располагать в каталоге указанной в UV_PROJECT_ENVIRONMENT это стоит не забыть:
ekzorchik@srv-s2404a:~$ export UV_PROJECT_ENVIRONMENT="$HOME/project"
ekzorchik@srv-s2404a:~$ source ~/.bashrc
ekzorchik@srv-s2404a:~$ mkdir ~/project
ekzorchik@srv-s2404a:~$ python3.13 -m venv ~/project/
ekzorchik@srv-s2404a:~$ cd project/
ekzorchik@srv-s2404a:~/project$ nano .env
MODEL=ollama/llama3.1:8b
API_BASE=http://localhost:11434
OPENAI_API_KEY=none
CREWAI_TRACING_ENABLED=false
ekzorchik@srv-s2404a:~/project$ source bin/activate
(project) ekzorchik@srv-s2404a:~/project$ python -m ensurepip --upgrade
(project) ekzorchik@srv-s2404a:~/project$ python -m pip install --upgrade pip
(project) ekzorchik@srv-s2404a:~/project$ python -m pip install crewai
(project) ekzorchik@srv-s2404a:~/project$ crewai create crew my --classic
Creating folder my...
Select a provider to set up:
1. openai
2. anthropic
3. gemini
4. nvidia_nim
5. groq
6. huggingface
7. ollama
8. watson
9. bedrock
10. azure
11. cerebras
12. sambanova
13. other
q. Quit
Enter the number of your choice or 'q' to quit: 7
Select a model to use for Ollama:
1. ollama/llama3.1
2. ollama/mixtral
q. Quit
Enter the number of your choice or 'q' to quit: 1
API keys and model saved to .env file
Selected model: ollama/llama3.1
- Created my/.gitignore
- Created my/pyproject.toml
- Created my/README.md
- Created my/knowledge/user_preference.txt
- Created my/src/my/__init__.py
- Created my/src/my/main.py
- Created my/src/my/crew.py
- Created my/src/my/tools/custom_tool.py
- Created my/src/my/tools/__init__.py
- Created my/src/my/config/agents.yaml
- Created my/src/my/config/tasks.yaml
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint: git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint: git branch -m <name>
Initialized empty Git repository in /home/ekzorchik/project/my/.git/
Crew my created successfully!
(project) ekzorchik@srv-s2404a:~/project$
(project) ekzorchik@srv-s2404a:~/project$ cd my
(project) ekzorchik@srv-s2404a:~/project/my$ python --version
Python 3.13.15
(project) ekzorchik@srv-s2404a:~/project/my$
Вот что я хотел, чтобы все было стандартизировано
ну а дальше берем наполнение из выше представленных шагов.
Короче я пока не знаю, что лучше делать самим или использовать мастер. Ладно продолжаю свое изучение crewai.
На этом пока все, с уважением автор блога ekzorchik.