from __future__ import annotations from pathlib import Path import runpy from click.testing import CliRunner from crewai.flow.visualization import build_flow_structure from pytest import MonkeyPatch import tomli from crewai_cli.cli import crewai from crewai_cli.create_flow import create_flow def test_create_flow_declarative_project_can_run( tmp_path: Path, monkeypatch: MonkeyPatch ): monkeypatch.chdir(tmp_path) create_flow("Research Flow", declarative=True) project_root = tmp_path / "research_flow" assert project_root.is_dir() pyproject = tomli.loads( (project_root / "pyproject.toml").read_text(encoding="utf-8") ) assert pyproject["project"]["name"] == "research_flow" assert pyproject["project"]["requires-python"] assert pyproject["project"]["dependencies"] assert (project_root / pyproject["tool"]["crewai"]["definition"]).is_file() agents_md = (project_root / "AGENTS.md").read_text(encoding="utf-8") assert "CrewAI Flow declaration" in agents_md assert "schema: crewai.flow/v1" in agents_md assert "do not assemble the string with CEL `+`" in agents_md assert "Agent prompt template. Insert Flow values with `${...}`" in agents_md assert "Runtime inputs passed to the Crew" in agents_md assert "call: expression" in agents_md assert "call: tool" not in agents_md assert "call: script" not in agents_md assert "call: each" not in agents_md assert "human_feedback" not in agents_md claude_md = (project_root / "CLAUDE.md").read_text(encoding="utf-8") assert "@AGENTS.md" in claude_md.splitlines() cursor_md = (project_root / "CURSOR.md").read_text(encoding="utf-8") assert "@AGENTS.md" in cursor_md.splitlines() gemini_md = (project_root / "GEMINI.md").read_text(encoding="utf-8") assert "@./AGENTS.md" in gemini_md.splitlines() monkeypatch.chdir(project_root) result = CliRunner().invoke(crewai, ["run"], env={"UV_RUN_RECURSION_DEPTH": "1"}) assert result.exit_code == 0 assert "Running the Flow" not in result.output assert "AI agents" in result.output def test_create_flow_scaffolds_assistant_instructions( tmp_path: Path, monkeypatch: MonkeyPatch ): monkeypatch.chdir(tmp_path) create_flow("Research Flow") project_root = tmp_path / "research_flow" agents_md = (project_root / "AGENTS.md").read_text(encoding="utf-8") assert "CrewAI Reference for AI Coding Assistants" in agents_md assert "Never disable, block, or silence CrewAI's built-in observability" in agents_md claude_md = (project_root / "CLAUDE.md").read_text(encoding="utf-8") assert "@AGENTS.md" in claude_md.splitlines() gemini_md = (project_root / "GEMINI.md").read_text(encoding="utf-8") assert "@./AGENTS.md" in gemini_md.splitlines() def test_scaffolded_flow_agents_md_tells_assistants_to_evaluate_with_crewai_eval( tmp_path: Path, monkeypatch: MonkeyPatch ): monkeypatch.chdir(tmp_path) create_flow("Research Flow") create_flow("Declared Flow", declarative=True) for project in ("research_flow", "declared_flow"): agents_md = (tmp_path / project / "AGENTS.md").read_text(encoding="utf-8") assert "## Evaluating this" in agents_md assert "Run `crewai eval` after a change" in agents_md assert "it prints a **markdown brief** after the verdict" in agents_md assert 'crewai eval --models "provider/model,…"' in agents_md assert "{{name}}" not in agents_md assert "crewai-eval:" not in agents_md def test_scaffolded_agents_md_routing_example_lets_plots_see_its_branches( tmp_path: Path, monkeypatch: MonkeyPatch ): monkeypatch.chdir(tmp_path) create_flow("Research Flow") agents_md = (tmp_path / "research_flow" / "AGENTS.md").read_text(encoding="utf-8") section = agents_md.split("### Conditional Routing", 1)[1] example = tmp_path / "routing_example.py" example.write_text(section.split("```python\n", 1)[1].split("```", 1)[0]) quality_flow = runpy.run_path(str(example), run_name="routing_example")["QualityFlow"] structure = build_flow_structure(quality_flow()) assert structure["nodes"]["check_quality"]["router_events"] == [ "high_quality", "needs_revision", ]