A production-style multi-agent software delivery crew built with CrewAI. You hand the crew a rough product idea and a team of specialized AI agents takes it from concept to a verified deliverable:
Rough idea
│
▼
Product Owner ──▶ Architect ──▶ Developer ──▶ QA Engineer ──▶ Verified output
(requirements) (tech stack) (implementation) (test report)
Each stage's output is persisted to the outputs/ directory as markdown.
| Agent | Role | Responsibility |
|---|---|---|
| Product Owner | Senior Product Owner | Turns a rough idea into a product brief: vision, scope, prioritized user stories, and open questions |
| Architect | Principal Software Architect | Designs the architecture and selects a justified tech stack with trade-offs |
| Developer | Senior Full-Stack Developer | Implements a working first version following the architecture |
| QA Engineer | Senior QA Engineer | Verifies the implementation against acceptance criteria and issues a PASS/FAIL report |
Agents run in a sequential process: each agent automatically receives the previous stages' outputs as context.
This project is intentionally config-driven so behavior can change without touching code:
config/llms.yaml— named LLM profiles (default,precise,creative) with model, endpoint, and temperature. Agents pick a profile by name.config/agents.yaml— each agent'srole,goal, andbackstory(prompts live as config, not hardcoded strings).config/tasks.yaml— each task'sdescription,expected_output, assignedagent, andoutput_file.crew.py— a thin wiring layer using CrewAI's@CrewBasepattern (@agent,@task,@crewdecorators).- Secrets via environment variables —
llms.yamlstores the name of the env var holding the API key (api_key_env), never the key itself.
EngCrew/
├── .env # NVIDIA_API_KEY (not committed)
├── pyproject.toml
├── outputs/ # generated artifacts (gitignored)
│ ├── 01_product_brief.md
│ ├── 02_architecture.md
│ ├── 03_implementation.md
│ └── 04_qa_report.md
└── src/engcrew/
├── __init__.py
├── config/
│ ├── llms.yaml # LLM profiles
│ ├── agents.yaml # agent personas
│ └── tasks.yaml # task definitions + output files
├── llm_factory.py # config-driven LLM factory
├── crew.py # @CrewBase: wires agents + tasks + process
├── main.py # entry point
├── verify_llm.py # smoke test: LLM connectivity
└── verify_agents.py # smoke test: agents instantiate
- Python >= 3.12
- uv for dependency management
- An NVIDIA API key with access to NVIDIA NIM (build.nvidia.com)
-
Install dependencies:
uv sync
-
Create a
.envfile in the project root:NVIDIA_API_KEY=nvapi-your-key-here
The crew uses NVIDIA NIM through CrewAI's OpenAI-compatible interface.
Profiles are defined in src/engcrew/config/llms.yaml:
| Profile | Temperature | Used by |
|---|---|---|
creative |
0.9 | Product Owner |
precise |
0.2 | Architect, Developer, QA |
default |
0.7 | general purpose |
To swap the model or tuning, edit llms.yaml — no code changes required.
Verify connectivity and agent setup first (cheap, minimal API usage):
uv run python -m engcrew.verify_llm # prints an LLM connection check
uv run python -m engcrew.verify_agents # prints OK for each of the 4 agentsRun the full delivery pipeline:
uv run python -m engcrew.mainThe rough idea is set in main.py:
idea = "a simple web app for roommates to split rent and shared bills"Edit that string to run the crew on your own idea. When the run completes, the
per-stage artifacts are written to outputs/.
main.pycallsEngCrew().crew().kickoff(inputs={"idea": ...}).- The
{idea}placeholder is injected into the Product Owner's task. - Each task runs in order; CrewAI feeds prior outputs forward as context.
- Each task writes its result to its configured
output_file. kickoff()returns aCrewOutput(.raw,.tasks_output,.token_usage).
- Config-driven LLM factory (NVIDIA NIM)
- Four agents defined in
agents.yaml - Sequential task pipeline with persisted outputs
- File-writing tool so the Developer scaffolds a real runnable project
- Human-in-the-loop for business decisions and clarifications
- Guardrails and structured output validation
- The NVIDIA free tier enforces rate limits; a full run makes several LLM calls
and may occasionally return
503 ResourceExhausted. Wait briefly and retry. outputs/is gitignored — generated artifacts are not committed.