Skip to content

Commit de13dec

Browse files
Adds adapter for crew AI
1 parent a98ba8e commit de13dec

24 files changed

Lines changed: 2798 additions & 1 deletion

.gitignore

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,48 @@
1-
__pycache__
1+
# Python
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
*.so
6+
.Python
7+
build/
8+
develop-eggs/
9+
dist/
10+
downloads/
11+
eggs/
12+
.eggs/
13+
lib/
14+
lib64/
15+
parts/
16+
sdist/
17+
var/
18+
wheels/
19+
*.egg-info/
20+
.installed.cfg
21+
*.egg
22+
23+
# Virtual environments
24+
.venv/
25+
venv/
26+
ENV/
27+
env/
28+
29+
# Env and secrets (do not commit API keys)
30+
.env
31+
.env.local
32+
.env.*.local
33+
34+
# IDE / editor
235
.claude
36+
.idea/
37+
.vscode/
38+
*.swp
39+
*.swo
40+
*~
41+
42+
# OS
43+
.DS_Store
44+
Thumbs.db
45+
46+
# Logs and local outputs
47+
*.log
48+
.oape-output/

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ ln -s oape-ai-e2e ~/.cursor/commands/oape-ai-e2e
4747
| ------------------------- | ---------------------------------------------- | --------------------------------------------------------------------------- |
4848
| **[oape](plugins/oape/)** | AI-driven OpenShift operator development tools | `/oape:init`, `/oape:api-generate`, `/oape:api-generate-tests`, `/oape:api-implement`, `/oape:analyze-rfe`, `/oape:e2e-generate`, `/oape:review`, `/oape:implement-review-fixes` |
4949

50+
## CrewAI Multi-Agent Workflow
51+
52+
A **project-agnostic** CrewAI setup lives in **[crewai/](crewai/)**. It runs a 9-task pipeline (design → design review → test cases → implementation outline → quality → code review → address review → write-up → customer doc) with four agents (SSE, PSE, SQE, Technical Writer). Agents take learnings from **skills** in `plugins/oape/skills/` (e.g. Effective Go). Scope is set at runtime via env or CLI—no project-specific context. See [crewai/README.md](crewai/README.md) for setup and usage.
53+
5054
## Commands
5155

5256
### `/oape:init` -- Clone an Operator Repository

crewai/README.md

Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
# OAPE Workflow (Adapter: CrewAI vs Claude SDK)
2+
3+
Project-agnostic workflow for OAPE with an **adapter design** so you can switch between two backends:
4+
5+
| Backend | What it does |
6+
|-------------|---------------|
7+
| **crewai** | Full 11-task pipeline: design → design review → test plan → implementation outline → **unit tests (SQE)****implementation (SSE)** → quality → code review → address review → write-up → customer doc. Code must compile when using `--apply-to-repo`. Uses skills from `plugins/oape/skills/`. |
8+
| **claude-sdk** | Calls the OAPE server (Claude Agent SDK) for **api-implement**: generate controller/reconciler code from an enhancement proposal. Requires server running and an EP URL. |
9+
10+
Same **scope** (context file, EP URL, env) and same **entrypoint** (`main.py`); switch via `--backend` or `OAPE_BACKEND`.
11+
12+
## Features
13+
14+
- **Adapter pattern:** One interface (`WorkflowAdapter.run(scope) -> WorkflowResult`), two implementations; switch backends without changing caller code.
15+
- **Project-agnostic:** Scope is set at runtime (env, CLI, context file, or EP URL).
16+
- **Skills-driven (CrewAI):** All `plugins/oape/skills/<name>/SKILL.md` are loaded and injected when using the CrewAI backend.
17+
18+
## Setup
19+
20+
From the **oape-ai-e2e** repo root:
21+
22+
```bash
23+
cd crewai
24+
pip install -r requirements.txt
25+
```
26+
27+
Set scope via env or CLI (see below). For OpenAI (default), set `OPENAI_API_KEY`. For Vertex Claude, set `OAPE_CREWAI_USE_VERTEX=1` and Vertex env vars (`ANTHROPIC_VERTEX_PROJECT_ID`, `CLOUD_ML_REGION`, optional `VERTEX_CLAUDE_MODEL`).
28+
29+
## Switching backends
30+
31+
- **CrewAI (default):** `python main.py ...` or `OAPE_BACKEND=crewai python main.py ...`
32+
- **Claude SDK:** Start the OAPE server (e.g. `cd server && uvicorn server:app`), set `OAPE_CLAUDE_SDK_SERVER_URL` if not `http://localhost:8000`, then:
33+
```bash
34+
python main.py --backend claude-sdk --ep-url https://github.com/openshift/enhancements/pull/1234 --project-name "My Operator" --repo-url https://github.com/openshift/my-operator
35+
```
36+
The Claude SDK backend requires an EP URL (via `--ep-url` or `OAPE_EP_URL` or in the context file). Operator repo path: `OAPE_OPERATOR_CWD`.
37+
38+
## Running
39+
40+
**Using environment variables:**
41+
42+
```bash
43+
export OAPE_PROJECT_NAME="My Operator"
44+
export OAPE_REPO_URL="https://github.com/openshift/my-operator"
45+
export OAPE_SCOPE_DESCRIPTION="Add a new CRD and controller for Foo resource; follow controller-runtime."
46+
# optional:
47+
export OAPE_EXTRA_CONTEXT="Link to enhancement: https://github.com/openshift/enhancements/pull/1234"
48+
49+
python main.py
50+
```
51+
52+
**Using CLI:**
53+
54+
```bash
55+
python main.py \
56+
--project-name "My Operator" \
57+
--repo-url "https://github.com/openshift/my-operator" \
58+
--scope "Add a new CRD and controller for Foo resource; follow controller-runtime."
59+
```
60+
61+
**Using a context file (e.g. scope.txt):**
62+
63+
The file can be plain text (entire file = scope description) or use optional headers:
64+
65+
```text
66+
PROJECT_NAME=My Operator
67+
REPO_URL=https://github.com/openshift/my-operator
68+
---
69+
Add a new CRD and controller for Foo resource. Follow controller-runtime.
70+
Include validation, reconciliation, and unit tests.
71+
```
72+
73+
Then:
74+
75+
```bash
76+
python main.py --context-file path/to/scope.txt
77+
```
78+
79+
**Using a local repo path (so the SSE uses real paths):**
80+
81+
If you have a local clone, pass its path so the workflow injects the **directory layout** into scope. The design and implementation outline will then suggest only files/packages that exist in that tree (no invented directories).
82+
83+
```bash
84+
python main.py --context-file scope.txt --repo-path /path/to/openshift-zero-trust-workload-identity-manager
85+
# or
86+
export OAPE_REPO_PATH=/path/to/your-repo
87+
python main.py --context-file scope.txt
88+
```
89+
90+
`OAPE_OPERATOR_CWD` is also read as a fallback for the repo path.
91+
92+
An example file is provided: `example_scope.txt`. You can also set `OAPE_CONTEXT_FILE=path/to/scope.txt` in the environment. If `PROJECT_NAME` and `REPO_URL` are omitted in the file, set them via env or CLI, or the default scope names are used.
93+
94+
**Using a GitHub Enhancement Proposal (EP) URL:**
95+
96+
Fetches the PR title and body from `openshift/enhancements` and adds it as extra context. Requires the [GitHub CLI](https://cli.github.com/) (`gh`) to be installed and authenticated (`gh auth login`).
97+
98+
```bash
99+
python main.py --ep-url https://github.com/openshift/enhancements/pull/1234 --project-name "My Operator" --repo-url https://github.com/openshift/my-operator
100+
```
101+
102+
You can combine **context file** and **EP URL**: e.g. `--context-file scope.txt --ep-url https://github.com/openshift/enhancements/pull/1234` uses the file for project/scope and appends the EP content as additional context. Env vars `OAPE_CONTEXT_FILE` and `OAPE_EP_URL` can be used instead of CLI flags.
103+
104+
If no scope is provided, a default example scope is used so the crew still runs (useful for testing).
105+
106+
## How to test
107+
108+
**Prerequisites (from `oape-ai-e2e/crewai`):**
109+
110+
```bash
111+
cd /path/to/oape-ai-e2e/crewai
112+
pip install -r requirements.txt
113+
export OPENAI_API_KEY=sk-... # or use Vertex: OAPE_CREWAI_USE_VERTEX=1 + ANTHROPIC_VERTEX_PROJECT_ID, CLOUD_ML_REGION
114+
```
115+
116+
**Quick test script (from `crewai/`):**
117+
118+
```bash
119+
./scripts/test_crewai.sh # smoke test (default scope)
120+
./scripts/test_crewai.sh context # with example_scope.txt
121+
./scripts/test_crewai.sh output-dir # write outputs to /tmp/oape-test
122+
REPO_PATH=/path/to/repo ./scripts/test_crewai.sh apply # apply to repo (branch + code + compile + commit)
123+
```
124+
125+
**1. Minimal smoke test (default scope, 11-task pipeline)**
126+
127+
No context file needed; uses built-in default scope. You should see reasoning, 11 tasks (design → review → test plan → outline → **unit tests****implementation** → quality → code review → address review → write-up → customer doc), and the TRACE section at the end.
128+
129+
```bash
130+
python main.py
131+
```
132+
133+
**2. Test with a context file**
134+
135+
```bash
136+
python main.py --context-file example_scope.txt
137+
```
138+
139+
**3. Test with ZTWIM scope and local repo**
140+
141+
Point at a local operator clone so the workflow uses real paths. SQE writes unit tests first, then SSE writes implementation; if you use `--apply-to-repo`, the code must compile before commit.
142+
143+
```bash
144+
# With repo path only (no apply):
145+
python main.py --context-file scope_ztwim_upstream_authority.txt --repo-path /path/to/your/operator-repo
146+
147+
# Write all task outputs to a directory:
148+
python main.py --context-file scope_ztwim_upstream_authority.txt --repo-path /path/to/repo --output-dir /tmp/oape-out
149+
150+
# Apply to repo: new branch, write code, verify compile, commit (requires Go/make):
151+
python main.py --context-file scope_ztwim_upstream_authority.txt --repo-path /path/to/repo --apply-to-repo
152+
```
153+
154+
Optional: `--branch-name oape/my-feature` and `OAPE_OUTPUT_DIR`, `OAPE_APPLY_TO_REPO`, `OAPE_BRANCH_NAME` as env equivalents.
155+
156+
**4. Avoid "prompt is too long" (200k token limit)**
157+
158+
Task outputs are truncated when used as context for later tasks so the total prompt stays under the model limit. Default: 8000 characters per task output. Override if needed:
159+
160+
```bash
161+
OAPE_CONTEXT_MAX_CHARS_PER_TASK=10000 python main.py --context-file scope_ztwim_upstream_authority.txt --repo-path /path/to/repo
162+
```
163+
164+
**5. More reasoning (debugging)**
165+
166+
Agents use `max_reasoning_attempts=20` by default. Override:
167+
168+
```bash
169+
OAPE_MAX_REASONING_ATTEMPTS=20 python main.py --context-file example_scope.txt
170+
```
171+
172+
**6. See full LLM request/response**
173+
174+
```bash
175+
CREWAI_DEBUG_LLM=1 python main.py --context-file example_scope.txt
176+
```
177+
178+
**7. See full reasoning plan before each task**
179+
180+
```bash
181+
CREWAI_DEBUG_REASONING=1 python main.py --context-file example_scope.txt
182+
```
183+
184+
**8. Test with CLI scope (no file)**
185+
186+
```bash
187+
python main.py --project-name "Test Operator" --repo-url "https://github.com/openshift/example" --scope "Add a simple CRD and reconciler for Bar resource."
188+
```
189+
190+
**9. Claude SDK backend (requires OAPE server running)**
191+
192+
In one terminal start the server (from `oape-ai-e2e`):
193+
194+
```bash
195+
cd server && uvicorn server:app --reload
196+
```
197+
198+
In another, from `oape-ai-e2e/crewai`:
199+
200+
```bash
201+
python main.py --backend claude-sdk --ep-url https://github.com/openshift/enhancements/pull/1234 --project-name "My Operator" --repo-url https://github.com/openshift/my-operator
202+
```
203+
204+
Set `OAPE_CLAUDE_SDK_SERVER_URL` if the server is not at `http://localhost:8000`.
205+
206+
## Trace ID and dashboard
207+
208+
To see **TraceID** and open the run in the CrewAI dashboard:
209+
210+
1. **Enable tracing**
211+
The CrewAI backend already uses `tracing=True`. You can also set:
212+
```bash
213+
export CREWAI_TRACING_ENABLED=true
214+
```
215+
216+
2. **Log in to CrewAI** (required for traces to be sent and viewable):
217+
```bash
218+
crewai login
219+
```
220+
Use a free account at [app.crewai.com](https://app.crewai.com).
221+
222+
3. **Run the workflow**
223+
After `crew.kickoff()` finishes, the run is sent to CrewAI AMP. You get:
224+
- **Trace ID (session ID)** – printed in the green “Trace batch finalized” panel by CrewAI, and also in our summary.
225+
- **Trace URL** – we put it in the result artifacts and print it at the end, e.g.:
226+
```
227+
Trace ID: <uuid>
228+
View trace: https://app.crewai.com/crewai_plus/trace_batches/<uuid>
229+
```
230+
231+
4. **View in the dashboard**
232+
Open the URL above, or go to [app.crewai.com](https://app.crewai.com) → Traces and select the run. You’ll see agent decisions, task order, LLM calls, and token usage.
233+
234+
If you don’t run `crewai login`, tracing still runs locally but no TraceID or URL is shown (the batch isn’t sent to the backend).
235+
236+
## Skills
237+
238+
Skills live under **`plugins/oape/skills/<name>/SKILL.md`**. Each `SKILL.md` is loaded and appended to a shared “skills context” that is injected into task descriptions. Agents are instructed to “apply the following skills and conventions where relevant.”
239+
240+
**Adding a new skill:**
241+
242+
1. Create a directory under `plugins/oape/skills/`, e.g. `plugins/oape/skills/api-conventions/`.
243+
2. Add `SKILL.md` with clear sections (Purpose, When This Skill Applies, Guidelines, References).
244+
3. Re-run the workflow; the new skill is picked up automatically.
245+
246+
No code changes are required in the CrewAI setup when you add a skill.
247+
248+
## Optional: Vertex AI
249+
250+
To use Claude on Vertex instead of OpenAI:
251+
252+
```bash
253+
export OAPE_CREWAI_USE_VERTEX=1
254+
export ANTHROPIC_VERTEX_PROJECT_ID=your-gcp-project
255+
export CLOUD_ML_REGION=us-east5
256+
export VERTEX_CLAUDE_MODEL=claude-3-5-haiku@20241022
257+
# authenticate
258+
gcloud auth application-default login
259+
python main.py ...
260+
```
261+
262+
## Layout
263+
264+
| File / dir | Purpose |
265+
|------------|--------|
266+
| `adapters/` | Adapter layer: `base.py` (WorkflowAdapter, WorkflowResult), `crewai_adapter.py`, `claude_sdk_adapter.py`, `factory.py` (get_adapter). |
267+
| `skills_loader.py` | Loads all `SKILL.md` from `plugins/oape/skills/` and returns a single context string. |
268+
| `context.py` | Project-agnostic scope (project name, repo URL, scope description, extra context). |
269+
| `personas.py` | Generic SSE, PSE, SQE, Technical Writer personas. |
270+
| `agents.py` | CrewAI agents (optionally with Vertex LLM). |
271+
| `tasks.py` | Builds the 9 tasks with scope and skills context injected. |
272+
| `main.py` | Entry point: parses scope and `--backend`, runs `get_adapter(backend).run(scope)`. |
273+
| `llm_vertex.py` | Optional Vertex Claude LLM for CrewAI. |
274+
275+
## Relation to OAPE commands
276+
277+
The existing OAPE slash commands (`/oape:api-generate`, `/oape:api-implement`, `/oape:review`, etc.) are single-command, single-agent runs that generate or review **code** in the repo. This CrewAI workflow is **document-focused** (design doc, test plan, implementation outline, customer doc) and **multi-agent** (four roles, nine tasks). It reuses the same **skills** so that conventions (e.g. Effective Go) apply consistently whether you use the slash commands or the CrewAI pipeline.

crewai/adapters/__init__.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"""
2+
Workflow adapters: switch between CrewAI and Claude SDK backends.
3+
4+
Use the same scope (ProjectScope) and get a WorkflowResult from either:
5+
- crewai: full 9-task document workflow (design -> review -> ... -> customer doc)
6+
- claude-sdk: Claude Agent SDK path (e.g. api-implement via server or slash commands)
7+
8+
Set OAPE_BACKEND=crewai | claude-sdk or pass --backend to main.py.
9+
"""
10+
11+
from .base import WorkflowAdapter, WorkflowResult
12+
from .factory import get_adapter
13+
14+
__all__ = ["WorkflowAdapter", "WorkflowResult", "get_adapter"]

0 commit comments

Comments
 (0)