diff --git a/python/Makefile b/python/Makefile index fc49fb4d33..4ec7cfea06 100644 --- a/python/Makefile +++ b/python/Makefile @@ -19,7 +19,7 @@ lint: .PHONY: test test: update generate-test-certs - uv run pytest ./packages/**/tests/ + uv run pytest ./packages/**/tests/ ./samples/crewai/research-crew/tests/ ./samples/crewai/poem_flow/tests/ .PHONY: build build: update format diff --git a/python/samples/crewai/poem_flow/Dockerfile b/python/samples/crewai/poem_flow/Dockerfile index 64406faeac..d6e91d5a8f 100644 --- a/python/samples/crewai/poem_flow/Dockerfile +++ b/python/samples/crewai/poem_flow/Dockerfile @@ -46,4 +46,4 @@ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ CMD curl -f http://localhost:8080/health || exit 1 # Run the application -CMD ["python", "samples/crewai/poem_flow/src/poem_flow/main.py"] +CMD ["uv", "run", "--package", "poem_flow", "poem-flow"] diff --git a/python/samples/crewai/poem_flow/pyproject.toml b/python/samples/crewai/poem_flow/pyproject.toml index b2f6ca1107..2e462cb0d6 100644 --- a/python/samples/crewai/poem_flow/pyproject.toml +++ b/python/samples/crewai/poem_flow/pyproject.toml @@ -8,6 +8,9 @@ dependencies = [ "kagent-crewai", ] +[project.scripts] +poem-flow = "poem_flow.main:main" + [build-system] requires = ["setuptools>=83.0.0", "wheel>=0.47.0"] build-backend = "setuptools.build_meta" diff --git a/python/samples/crewai/poem_flow/src/poem_flow/main.py b/python/samples/crewai/poem_flow/src/poem_flow/main.py index 225309f5eb..de31bc5b32 100644 --- a/python/samples/crewai/poem_flow/src/poem_flow/main.py +++ b/python/samples/crewai/poem_flow/src/poem_flow/main.py @@ -75,14 +75,18 @@ def plot(): # To integrate with Kagent, just replace the kickoff above with the KAgentApp code below -def main(): - """Main entry point to run the KAgent CrewAI server.""" +def build_app(): + """Build the poem flow ASGI application.""" with open(os.path.join(os.path.dirname(__file__), "agent-card.json"), "r") as f: agent_card = json.load(f) - app = KAgentApp(crew=PoemFlow(), agent_card=agent_card) + return KAgentApp(crew=PoemFlow(), agent_card=agent_card).build() + + +def main(): + """Main entry point to run the KAgent CrewAI server.""" + server = build_app() - server = app.build() port = int(os.getenv("PORT", "8080")) host = os.getenv("HOST", "0.0.0.0") diff --git a/python/samples/crewai/poem_flow/tests/test_poem_flow_main.py b/python/samples/crewai/poem_flow/tests/test_poem_flow_main.py new file mode 100644 index 0000000000..4865aa42f1 --- /dev/null +++ b/python/samples/crewai/poem_flow/tests/test_poem_flow_main.py @@ -0,0 +1,21 @@ +"""Regression tests for the poem flow console entry point.""" + +import importlib + +from fastapi.testclient import TestClient + + +def test_main_passes_healthy_app_to_uvicorn(monkeypatch): + monkeypatch.setenv("OPENAI_API_KEY", "fake") + monkeypatch.setenv("KAGENT_API_URL", "http://localhost:8083") + monkeypatch.setenv("KAGENT_GATEWAY_URL", "http://localhost:8083") + monkeypatch.setenv("KAGENT_NAME", "poem-flow") + monkeypatch.setenv("KAGENT_NAMESPACE", "default") + module = importlib.import_module("poem_flow.main") + captured = {} + monkeypatch.setattr(module.uvicorn, "run", lambda app, **kwargs: captured.update(app=app, kwargs=kwargs)) + + module.main() + + assert TestClient(captured["app"]).get("/health").text == "OK" + assert captured["kwargs"] == {"host": "0.0.0.0", "port": 8080, "log_level": "info"} diff --git a/python/samples/crewai/research-crew/Dockerfile b/python/samples/crewai/research-crew/Dockerfile index 271eead58f..6dcffb20aa 100644 --- a/python/samples/crewai/research-crew/Dockerfile +++ b/python/samples/crewai/research-crew/Dockerfile @@ -46,4 +46,4 @@ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ CMD curl -f http://localhost:8080/health || exit 1 # Run the application -CMD ["python", "samples/crewai/research-crew/src/research_crew/main.py"] +CMD ["uv", "run", "--package", "research-crew", "research-crew"] diff --git a/python/samples/crewai/research-crew/pyproject.toml b/python/samples/crewai/research-crew/pyproject.toml index c79a4bc25c..cc08528cda 100644 --- a/python/samples/crewai/research-crew/pyproject.toml +++ b/python/samples/crewai/research-crew/pyproject.toml @@ -8,6 +8,9 @@ dependencies = [ "kagent-crewai", ] +[project.scripts] +research-crew = "research_crew.main:main" + [build-system] requires = ["setuptools>=83.0.0", "wheel>=0.47.0"] build-backend = "setuptools.build_meta" diff --git a/python/samples/crewai/research-crew/src/research_crew/agent-card.json b/python/samples/crewai/research-crew/src/research_crew/agent-card.json index f89bbe6af7..6ced77eec1 100644 --- a/python/samples/crewai/research-crew/src/research_crew/agent-card.json +++ b/python/samples/crewai/research-crew/src/research_crew/agent-card.json @@ -12,7 +12,7 @@ "id": "research-crew", "name": "Research Crew", "description": "Can conduct research and analysis by providing a topic as input", - "example": "{\"input\": \"Latest advancements in AI\"}", + "examples": ["{\"input\": \"Latest advancements in AI\"}"], "tags": ["research", "analysis"] } ] diff --git a/python/samples/crewai/research-crew/src/research_crew/main.py b/python/samples/crewai/research-crew/src/research_crew/main.py index 27b906f437..0200fe22b1 100644 --- a/python/samples/crewai/research-crew/src/research_crew/main.py +++ b/python/samples/crewai/research-crew/src/research_crew/main.py @@ -13,17 +13,20 @@ logger = logging.getLogger(__name__) -def main(): - """Main entry point to run the KAgent CrewAI server.""" +def build_app(): + """Build the research crew ASGI application.""" # 1. Load the agent card or define it inline with open(os.path.join(os.path.dirname(__file__), "agent-card.json"), "r") as f: agent_card = json.load(f) # 2. Load the Crew, then create the kagent app - app = KAgentApp(crew=ResearchCrew().crew(), agent_card=agent_card) + return KAgentApp(crew=ResearchCrew().crew(), agent_card=agent_card).build() + + +def main(): + """Main entry point to run the KAgent CrewAI server.""" + server = build_app() - # 3. Build the FastAPI app and run the server - server = app.build() port = int(os.getenv("PORT", "8080")) host = os.getenv("HOST", "0.0.0.0") logger.info(f"Starting server on {host}:{port}") diff --git a/python/samples/crewai/research-crew/tests/test_research_crew_main.py b/python/samples/crewai/research-crew/tests/test_research_crew_main.py new file mode 100644 index 0000000000..9ecdaddb14 --- /dev/null +++ b/python/samples/crewai/research-crew/tests/test_research_crew_main.py @@ -0,0 +1,21 @@ +"""Regression tests for the research crew console entry point.""" + +import importlib + +from fastapi.testclient import TestClient + + +def test_main_passes_healthy_app_to_uvicorn(monkeypatch): + monkeypatch.setenv("OPENAI_API_KEY", "fake") + monkeypatch.setenv("KAGENT_API_URL", "http://localhost:8083") + monkeypatch.setenv("KAGENT_GATEWAY_URL", "http://localhost:8083") + monkeypatch.setenv("KAGENT_NAME", "research-crew") + monkeypatch.setenv("KAGENT_NAMESPACE", "default") + module = importlib.import_module("research_crew.main") + captured = {} + monkeypatch.setattr(module.uvicorn, "run", lambda app, **kwargs: captured.update(app=app, kwargs=kwargs)) + + module.main() + + assert TestClient(captured["app"]).get("/health").text == "OK" + assert captured["kwargs"] == {"host": "0.0.0.0", "port": 8080, "log_level": "info"}