| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 |
- """
- lambdagent_guard.crewai — CrewAI guard wrapper (I12).
- Usage:
- from lambdagent_guard import guard_crewai
- crew = Crew(agents=[researcher, writer], tasks=[...])
- guarded = guard_crewai(crew, cost_budget=10.0)
- result = guarded.kickoff()
- Catches: CrewAI #3847 (max_iter broken), #737 (tool result lost), #1355 (10x cost)
- """
- from __future__ import annotations
- from typing import Any, Callable, Optional
- from .core import GuardConfig, RuntimeMonitor, run_compile_checks
- import warnings
- def guard_crewai(
- crew,
- cost_budget: float = float("inf"),
- parallel_safety: bool = True,
- terminate_check: bool = True,
- loop_detection: bool = True,
- cost_alert: Optional[Callable[[float], None]] = None,
- ):
- """
- Wrap a CrewAI Crew with lambdagent safety guards.
- Args:
- crew: CrewAI Crew object
- cost_budget: Max cost in USD
- parallel_safety: Check agent store independence
- terminate_check: Verify termination conditions exist
- """
- guard_cfg = GuardConfig(
- cost_budget=cost_budget,
- parallel_safety=parallel_safety,
- terminate_check=terminate_check,
- loop_detection=loop_detection,
- cost_alert=cost_alert,
- )
- # Phase 1: Compile-time checks
- try:
- from lambdagent.extractors import extract_config
- config = extract_config(crew, framework="crewai")
- issues = run_compile_checks(config, guard_cfg)
- for issue in issues:
- warnings.warn(f"[lambdagent-guard] {issue}")
- except Exception as e:
- warnings.warn(f"[lambdagent-guard] Compile check skipped: {e}")
- # Phase 2: Runtime hooks — wrap kickoff()
- monitor = RuntimeMonitor(guard_cfg)
- original_kickoff = crew.kickoff
- def guarded_kickoff(*args, **kwargs):
- # Hook into each agent's execution
- for agent in getattr(crew, 'agents', []):
- _hook_crewai_agent(agent, monitor)
- result = original_kickoff(*args, **kwargs)
- return result
- crew.kickoff = guarded_kickoff
- crew._lambdagent_monitor = monitor
- return crew
- def _hook_crewai_agent(agent, monitor: RuntimeMonitor):
- """Hook into a CrewAI agent's execute_task if available."""
- if hasattr(agent, 'execute_task'):
- original = agent.execute_task
- def guarded_execute(*args, **kwargs):
- result = original(*args, **kwargs)
- monitor.on_step({
- "output": str(result)[:500],
- "tokens": 0,
- })
- return result
- agent.execute_task = guarded_execute
|