factoryflow / src /agents /orchestrator.py
oabolade23's picture
FactoryFlow demo — initial submission
8ad9950
Raw
History Blame Contribute Delete
1.97 kB
"""CrewAI orchestrator wiring Engineer → Procurement as a sequential Crew.
Run as a module for a one-shot end-to-end test:
python -m src.agents.orchestrator
"""
from __future__ import annotations
import json
import os
import structlog
from crewai import Crew, Process
from src.agents.engineer_agent import build_engineer_agent, build_engineer_task
from src.agents.procurement_agent import (
build_procurement_agent,
build_procurement_task,
)
from src.agents.tools import sensor_tool
log = structlog.get_logger()
def build_crew() -> Crew:
engineer = build_engineer_agent()
procurement = build_procurement_agent()
eng_task = build_engineer_task(engineer)
proc_task = build_procurement_task(procurement)
proc_task.context = [eng_task] # procurement reads engineer's output
return Crew(
agents=[engineer, procurement],
tasks=[eng_task, proc_task],
process=Process.sequential,
verbose=True,
)
def run_cycle(force_state: str | None = None) -> dict:
"""Run a single Engineer→Procurement cycle and return the merged result."""
if force_state:
sensor_tool.force_state(force_state)
crew = build_crew()
result = crew.kickoff()
payload = {
"engineer": _safe_json(result.tasks_output[0].raw if result.tasks_output else ""),
"procurement": _safe_json(
result.tasks_output[1].raw if len(result.tasks_output) > 1 else ""
),
}
log.info(
"crew_cycle_complete",
component="agents.orchestrator",
forced_state=force_state or "none",
)
return payload
def _safe_json(raw: str) -> dict:
try:
return json.loads(raw)
except (json.JSONDecodeError, TypeError):
return {"raw": raw}
def main() -> None:
state = os.getenv("DEMO_FORCE_STATE", "imminent_failure")
out = run_cycle(force_state=state)
print(json.dumps(out, indent=2))
if __name__ == "__main__":
main()