Skip to content

Commit 9004ea3

Browse files
fix(examples): fix crewai examples (#179)
## Summary Fixed all CrewAI example `setup_controls.py` scripts to use the correct control definition schema (`selector`/`evaluator` nested under `condition`), which was causing 422 errors against the updated server API. Updated all example `pyproject.toml` files and READMEs to handle the `pydantic` version conflict between `agent-control-sdk` and `crewai`. ## Scope **User-facing/API changes:** - Updated install instructions in all four CrewAI example READMEs to use a two-step install workaround for the `pydantic` conflict (`crewai` caps at `<2.12`, `agent-control-evaluators` requires `>=2.12.4`) - Removed `agent-control-sdk` from all four example `pyproject.toml` dependency lists so `uv pip install -e .` resolves cleanly **Internal changes:** - Fixed `selector`/`evaluator` schema in all four `setup_controls.py` scripts — wrapped in `condition` key to match server API (`content_publishing_flow`, `evaluator_showcase`, `secure_research_crew`, `steering_financial_agent`) - Fixed `data["evaluator"]` reference in `evaluator_showcase/setup_controls.py` to `data["condition"]["evaluator"]` after the schema fix - Added response body logging to `create_control_safe` error handler in `content_publishing_flow/setup_controls.py` for easier debugging **Out of scope:** - No changes to SDK or server source code - Root cause of pydantic conflict (`agent-control-evaluators` as a hard dependency in the SDK) is not fixed here — tracked as a follow-up ## Risk and Rollout **Risk level:** low — changes are confined to example scripts and READMEs, no production code touched. **Rollback plan:** Revert example files. No server or SDK changes to roll back. ## Testing - [ ] Added or updated automated tests - [ ] Ran `make check` (not applicable — example scripts only) - [x] Manually verified behavior — `setup_controls.py` progressed past 422 after schema fix; install steps validated against `content_publishing_flow` ## Checklist - [ ] Linked issue/spec (if applicable) - [x] Updated docs/examples for user-facing changes - [x] Included any required follow-up tasks — make `agent-control-evaluators` an optional dependency in the SDK to permanently resolve the pydantic conflict
1 parent 248a307 commit 9004ea3

12 files changed

Lines changed: 394 additions & 313 deletions

File tree

examples/crewai/content_publishing_flow/README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,18 @@ curl http://localhost:8000/health
8080

8181
### 2. Install Dependencies
8282

83+
`agent-control-sdk` and `crewai` have an incompatible transitive dependency on `pydantic` (crewai caps at `<2.12`, the SDK evaluators require `>=2.12.4`). Install in two steps to work around this:
84+
8385
```bash
8486
cd examples/crewai/content_publishing_flow
85-
uv pip install -e . --upgrade
87+
88+
# Install crewai and all other deps via normal resolver
89+
uv pip install -e .
90+
91+
# Install agent-control-sdk separately, skipping the conflicting evaluators dep
92+
# (this example uses server-mode execution and does not need evaluators locally)
93+
uv pip install agent-control-sdk==7.5.0 --no-deps
94+
uv pip install httpx pydantic-settings docstring-parser google-re2 jsonschema
8695
```
8796

8897
### 3. Set Environment Variables

examples/crewai/content_publishing_flow/pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ version = "0.1.0"
44
description = "CrewAI Flow with routing, embedded crews, and Agent Control guardrails"
55
requires-python = ">=3.12"
66
dependencies = [
7-
"agent-control-sdk>=6.3.0",
87
"crewai[tools]>=1.10.1",
98
"openai>=1.0.0",
109
"python-dotenv>=1.0.0",

examples/crewai/content_publishing_flow/setup_controls.py

Lines changed: 127 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ async def create_control_safe(
4646
print(f" ! Could not find existing control '{name}'")
4747
raise SystemExit(1)
4848
else:
49-
print(f" ! Error creating control '{name}': {e}")
49+
detail = getattr(getattr(e, "response", None), "text", "")
50+
print(f" ! Error creating control '{name}': {e}\n ! Response body: {detail}")
5051
raise
5152

5253

@@ -108,13 +109,15 @@ async def setup_publishing_controls():
108109
"step_names": ["validate_request"],
109110
"stages": ["pre"],
110111
},
111-
"selector": {
112-
"path": "input.request",
113-
},
114-
"evaluator": {
115-
"name": "json",
116-
"config": {
117-
"required_fields": ["topic", "audience", "content_type"],
112+
"condition": {
113+
"selector": {
114+
"path": "input.request",
115+
},
116+
"evaluator": {
117+
"name": "json",
118+
"config": {
119+
"required_fields": ["topic", "audience", "content_type"],
120+
},
118121
},
119122
},
120123
"action": {"decision": "deny"},
@@ -134,22 +137,24 @@ async def setup_publishing_controls():
134137
"step_names": ["research_topic"],
135138
"stages": ["post"],
136139
},
137-
"selector": {
138-
"path": "output",
139-
},
140-
"evaluator": {
141-
"name": "list",
142-
"config": {
143-
"values": [
144-
"infowars.com",
145-
"naturalcures.com",
146-
"conspiracydaily.net",
147-
"fakenews.org",
148-
"unverifiedsource.com",
149-
],
150-
"logic": "any",
151-
"match_mode": "contains",
152-
"case_sensitive": False,
140+
"condition": {
141+
"selector": {
142+
"path": "output",
143+
},
144+
"evaluator": {
145+
"name": "list",
146+
"config": {
147+
"values": [
148+
"infowars.com",
149+
"naturalcures.com",
150+
"conspiracydaily.net",
151+
"fakenews.org",
152+
"unverifiedsource.com",
153+
],
154+
"logic": "any",
155+
"match_mode": "contains",
156+
"case_sensitive": False,
157+
},
153158
},
154159
},
155160
"action": {"decision": "deny"},
@@ -169,18 +174,20 @@ async def setup_publishing_controls():
169174
"step_names": ["fact_check"],
170175
"stages": ["post"],
171176
},
172-
"selector": {
173-
"path": "output",
174-
},
175-
"evaluator": {
176-
"name": "regex",
177-
"config": {
178-
"pattern": (
179-
r"(?i)"
180-
r"(?:UNVERIFIED|UNCONFIRMED|DEBUNKED|RETRACTED|FABRICATED)"
181-
r"|(?:no\s+credible\s+source)"
182-
r"|(?:cannot\s+be\s+verified)"
183-
),
177+
"condition": {
178+
"selector": {
179+
"path": "output",
180+
},
181+
"evaluator": {
182+
"name": "regex",
183+
"config": {
184+
"pattern": (
185+
r"(?i)"
186+
r"(?:UNVERIFIED|UNCONFIRMED|DEBUNKED|RETRACTED|FABRICATED)"
187+
r"|(?:no\s+credible\s+source)"
188+
r"|(?:cannot\s+be\s+verified)"
189+
),
190+
},
184191
},
185192
},
186193
"action": {"decision": "deny"},
@@ -200,19 +207,21 @@ async def setup_publishing_controls():
200207
"step_names": ["write_draft"],
201208
"stages": ["post"],
202209
},
203-
"selector": {
204-
"path": "output",
205-
},
206-
"evaluator": {
207-
"name": "regex",
208-
"config": {
209-
"pattern": (
210-
r"(?:"
211-
r"\b\d{3}-\d{2}-\d{4}\b" # SSN
212-
r"|[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}" # Email
213-
r"|\b\d{3}[-.]?\d{3}[-.]?\d{4}\b" # Phone
214-
r")"
215-
),
210+
"condition": {
211+
"selector": {
212+
"path": "output",
213+
},
214+
"evaluator": {
215+
"name": "regex",
216+
"config": {
217+
"pattern": (
218+
r"(?:"
219+
r"\b\d{3}-\d{2}-\d{4}\b" # SSN
220+
r"|[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}" # Email
221+
r"|\b\d{3}[-.]?\d{3}[-.]?\d{4}\b" # Phone
222+
r")"
223+
),
224+
},
216225
},
217226
},
218227
"action": {"decision": "deny"},
@@ -232,22 +241,24 @@ async def setup_publishing_controls():
232241
"step_names": ["write_draft"],
233242
"stages": ["post"],
234243
},
235-
"selector": {
236-
"path": "output",
237-
},
238-
"evaluator": {
239-
"name": "list",
240-
"config": {
241-
"values": [
242-
"insider trading",
243-
"market manipulation",
244-
"ponzi scheme",
245-
"money laundering",
246-
"classified information",
247-
],
248-
"logic": "any",
249-
"match_mode": "contains",
250-
"case_sensitive": False,
244+
"condition": {
245+
"selector": {
246+
"path": "output",
247+
},
248+
"evaluator": {
249+
"name": "list",
250+
"config": {
251+
"values": [
252+
"insider trading",
253+
"market manipulation",
254+
"ponzi scheme",
255+
"money laundering",
256+
"classified information",
257+
],
258+
"logic": "any",
259+
"match_mode": "contains",
260+
"case_sensitive": False,
261+
},
251262
},
252263
},
253264
"action": {"decision": "deny"},
@@ -267,13 +278,15 @@ async def setup_publishing_controls():
267278
"step_names": ["legal_review"],
268279
"stages": ["post"],
269280
},
270-
"selector": {
271-
"path": "output",
272-
},
273-
"evaluator": {
274-
"name": "json",
275-
"config": {
276-
"required_fields": ["disclaimer", "legal_reviewed"],
281+
"condition": {
282+
"selector": {
283+
"path": "output",
284+
},
285+
"evaluator": {
286+
"name": "json",
287+
"config": {
288+
"required_fields": ["disclaimer", "legal_reviewed"],
289+
},
277290
},
278291
},
279292
"action": {"decision": "deny"},
@@ -293,19 +306,21 @@ async def setup_publishing_controls():
293306
"step_names": ["edit_content"],
294307
"stages": ["post"],
295308
},
296-
"selector": {
297-
"path": "output",
298-
},
299-
"evaluator": {
300-
"name": "regex",
301-
"config": {
302-
"pattern": (
303-
r"(?:"
304-
r"\b\d{3}-\d{2}-\d{4}\b"
305-
r"|[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"
306-
r"|\b\d{3}[-.]?\d{3}[-.]?\d{4}\b"
307-
r")"
308-
),
309+
"condition": {
310+
"selector": {
311+
"path": "output",
312+
},
313+
"evaluator": {
314+
"name": "regex",
315+
"config": {
316+
"pattern": (
317+
r"(?:"
318+
r"\b\d{3}-\d{2}-\d{4}\b"
319+
r"|[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"
320+
r"|\b\d{3}[-.]?\d{3}[-.]?\d{4}\b"
321+
r")"
322+
),
323+
},
309324
},
310325
},
311326
"action": {"decision": "deny"},
@@ -330,16 +345,18 @@ async def setup_publishing_controls():
330345
"step_names": ["request_human_review"],
331346
"stages": ["pre"],
332347
},
333-
"selector": {
334-
"path": "input.content_type",
335-
},
336-
"evaluator": {
337-
"name": "list",
338-
"config": {
339-
"values": ["internal_memo"],
340-
"logic": "any",
341-
"match_mode": "exact",
342-
"case_sensitive": False,
348+
"condition": {
349+
"selector": {
350+
"path": "input.content_type",
351+
},
352+
"evaluator": {
353+
"name": "list",
354+
"config": {
355+
"values": ["internal_memo"],
356+
"logic": "any",
357+
"match_mode": "exact",
358+
"case_sensitive": False,
359+
},
343360
},
344361
},
345362
"action": {
@@ -364,19 +381,21 @@ async def setup_publishing_controls():
364381
"step_names": ["publish_content"],
365382
"stages": ["pre"],
366383
},
367-
"selector": {
368-
"path": "input.content",
369-
},
370-
"evaluator": {
371-
"name": "regex",
372-
"config": {
373-
"pattern": (
374-
r"(?:"
375-
r"\b\d{3}-\d{2}-\d{4}\b"
376-
r"|[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"
377-
r"|\b\d{3}[-.]?\d{3}[-.]?\d{4}\b"
378-
r")"
379-
),
384+
"condition": {
385+
"selector": {
386+
"path": "input.content",
387+
},
388+
"evaluator": {
389+
"name": "regex",
390+
"config": {
391+
"pattern": (
392+
r"(?:"
393+
r"\b\d{3}-\d{2}-\d{4}\b"
394+
r"|[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"
395+
r"|\b\d{3}[-.]?\d{3}[-.]?\d{4}\b"
396+
r")"
397+
),
398+
},
380399
},
381400
},
382401
"action": {"decision": "deny"},

examples/crewai/evaluator_showcase/README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,14 @@ make sync
6666
cd examples/crewai/evaluator_showcase
6767

6868
# Install example dependencies
69-
uv pip install -e . --upgrade
69+
# Note: agent-control-sdk and crewai have an incompatible transitive dependency on pydantic
70+
# (crewai caps at <2.12, the SDK evaluators require >=2.12.4). Install in two steps:
71+
uv pip install -e .
72+
73+
# Install agent-control-sdk separately, skipping the conflicting evaluators dep
74+
# (this example uses server-mode execution and does not need evaluators locally)
75+
uv pip install agent-control-sdk==7.5.0 --no-deps
76+
uv pip install httpx pydantic-settings docstring-parser google-re2 jsonschema
7077

7178
# Set your OpenAI key (optional for SQL/LIST/REGEX scenarios)
7279
export OPENAI_API_KEY="your-key"

examples/crewai/evaluator_showcase/pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ version = "0.1.0"
44
description = "CrewAI agent demonstrating all built-in evaluators: regex, list, json, and sql"
55
requires-python = ">=3.12"
66
dependencies = [
7-
"agent-control-sdk>=6.3.0",
87
"crewai[tools]>=1.10.1",
98
"openai>=1.0.0",
109
"python-dotenv>=1.0.0",

0 commit comments

Comments
 (0)