aegis-security-sdk 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. aegis_security_sdk-0.1.0/PKG-INFO +95 -0
  2. aegis_security_sdk-0.1.0/README.md +65 -0
  3. aegis_security_sdk-0.1.0/aegis_security_sdk.egg-info/PKG-INFO +95 -0
  4. aegis_security_sdk-0.1.0/aegis_security_sdk.egg-info/SOURCES.txt +82 -0
  5. aegis_security_sdk-0.1.0/aegis_security_sdk.egg-info/dependency_links.txt +1 -0
  6. aegis_security_sdk-0.1.0/aegis_security_sdk.egg-info/requires.txt +29 -0
  7. aegis_security_sdk-0.1.0/aegis_security_sdk.egg-info/top_level.txt +1 -0
  8. aegis_security_sdk-0.1.0/packages/__init__.py +1 -0
  9. aegis_security_sdk-0.1.0/packages/adapters/__init__.py +4 -0
  10. aegis_security_sdk-0.1.0/packages/adapters/base/__init__.py +3 -0
  11. aegis_security_sdk-0.1.0/packages/adapters/base/adapter.py +26 -0
  12. aegis_security_sdk-0.1.0/packages/adapters/crewai/adapter.py +263 -0
  13. aegis_security_sdk-0.1.0/packages/adapters/langgraph/__init__.py +3 -0
  14. aegis_security_sdk-0.1.0/packages/adapters/langgraph/adapter.py +169 -0
  15. aegis_security_sdk-0.1.0/packages/aegis.py +780 -0
  16. aegis_security_sdk-0.1.0/packages/config.py +20 -0
  17. aegis_security_sdk-0.1.0/packages/context.py +36 -0
  18. aegis_security_sdk-0.1.0/packages/layers/__init__.py +1 -0
  19. aegis_security_sdk-0.1.0/packages/layers/layer1/__init__.py +1 -0
  20. aegis_security_sdk-0.1.0/packages/layers/layer1/base.py +19 -0
  21. aegis_security_sdk-0.1.0/packages/layers/layer1/exceptions.py +11 -0
  22. aegis_security_sdk-0.1.0/packages/layers/layer1/keys.py +27 -0
  23. aegis_security_sdk-0.1.0/packages/layers/layer1/stages/__init__.py +1 -0
  24. aegis_security_sdk-0.1.0/packages/layers/layer1/stages/capability_detector.py +87 -0
  25. aegis_security_sdk-0.1.0/packages/layers/layer1/stages/intent_analysis.py +66 -0
  26. aegis_security_sdk-0.1.0/packages/layers/layer1/stages/memory_validation.py +135 -0
  27. aegis_security_sdk-0.1.0/packages/layers/layer1/stages/request_analyzer.py +174 -0
  28. aegis_security_sdk-0.1.0/packages/layers/layer1/stages/request_validation.py +76 -0
  29. aegis_security_sdk-0.1.0/packages/layers/layer1/stages/risk_engine.py +71 -0
  30. aegis_security_sdk-0.1.0/packages/layers/layer2/__init__.py +1 -0
  31. aegis_security_sdk-0.1.0/packages/layers/layer2/audit.py +38 -0
  32. aegis_security_sdk-0.1.0/packages/layers/layer2/engine.py +83 -0
  33. aegis_security_sdk-0.1.0/packages/layers/layer2/validators.py +108 -0
  34. aegis_security_sdk-0.1.0/packages/layers/layer5/__init__.py +1 -0
  35. aegis_security_sdk-0.1.0/packages/layers/layer5/consumer.py +23 -0
  36. aegis_security_sdk-0.1.0/packages/memory/__init__.py +1 -0
  37. aegis_security_sdk-0.1.0/packages/memory/adapters/__init__.py +1 -0
  38. aegis_security_sdk-0.1.0/packages/memory/adapters/langgraph_adapter.py +64 -0
  39. aegis_security_sdk-0.1.0/packages/memory/conversation.py +36 -0
  40. aegis_security_sdk-0.1.0/packages/memory/manager.py +128 -0
  41. aegis_security_sdk-0.1.0/packages/memory/policies.py +42 -0
  42. aegis_security_sdk-0.1.0/packages/memory/provider.py +49 -0
  43. aegis_security_sdk-0.1.0/packages/memory/registry.py +44 -0
  44. aegis_security_sdk-0.1.0/packages/memory/retrieval.py +64 -0
  45. aegis_security_sdk-0.1.0/packages/memory/semantic.py +35 -0
  46. aegis_security_sdk-0.1.0/packages/models.py +173 -0
  47. aegis_security_sdk-0.1.0/packages/observability/__init__.py +4 -0
  48. aegis_security_sdk-0.1.0/packages/observability/models.py +549 -0
  49. aegis_security_sdk-0.1.0/packages/observability/store.py +175 -0
  50. aegis_security_sdk-0.1.0/packages/policy/__init__.py +1 -0
  51. aegis_security_sdk-0.1.0/packages/policy/base.py +33 -0
  52. aegis_security_sdk-0.1.0/packages/policy/nl_policy.py +162 -0
  53. aegis_security_sdk-0.1.0/packages/providers.py +148 -0
  54. aegis_security_sdk-0.1.0/packages/runtime/__init__.py +1 -0
  55. aegis_security_sdk-0.1.0/packages/runtime/events/__init__.py +1 -0
  56. aegis_security_sdk-0.1.0/packages/runtime/events/bus.py +62 -0
  57. aegis_security_sdk-0.1.0/packages/runtime/events/models.py +107 -0
  58. aegis_security_sdk-0.1.0/packages/runtime/factory.py +56 -0
  59. aegis_security_sdk-0.1.0/packages/runtime/graph.py +53 -0
  60. aegis_security_sdk-0.1.0/packages/runtime/hooks/__init__.py +1 -0
  61. aegis_security_sdk-0.1.0/packages/runtime/hooks/base.py +75 -0
  62. aegis_security_sdk-0.1.0/packages/runtime/hooks/policy.py +37 -0
  63. aegis_security_sdk-0.1.0/packages/runtime/kernel/__init__.py +1 -0
  64. aegis_security_sdk-0.1.0/packages/runtime/kernel/kernel.py +501 -0
  65. aegis_security_sdk-0.1.0/packages/runtime/kernel/state.py +12 -0
  66. aegis_security_sdk-0.1.0/packages/runtime/managers/__init__.py +1 -0
  67. aegis_security_sdk-0.1.0/packages/runtime/managers/executor.py +80 -0
  68. aegis_security_sdk-0.1.0/packages/runtime/managers/kill_switch.py +44 -0
  69. aegis_security_sdk-0.1.0/packages/runtime/managers/monitor.py +36 -0
  70. aegis_security_sdk-0.1.0/packages/runtime/managers/normalizer.py +78 -0
  71. aegis_security_sdk-0.1.0/packages/runtime/managers/provider_executor.py +83 -0
  72. aegis_security_sdk-0.1.0/packages/runtime/managers/provider_registry.py +71 -0
  73. aegis_security_sdk-0.1.0/packages/runtime/managers/registry.py +67 -0
  74. aegis_security_sdk-0.1.0/packages/runtime/managers/retry.py +47 -0
  75. aegis_security_sdk-0.1.0/packages/runtime/managers/sanitizer.py +116 -0
  76. aegis_security_sdk-0.1.0/packages/runtime/managers/streaming.py +48 -0
  77. aegis_security_sdk-0.1.0/packages/runtime/managers/supervisor.py +61 -0
  78. aegis_security_sdk-0.1.0/packages/runtime/managers/timeout.py +42 -0
  79. aegis_security_sdk-0.1.0/packages/runtime/managers/tracker.py +50 -0
  80. aegis_security_sdk-0.1.0/packages/runtime/nodes/__init__.py +1 -0
  81. aegis_security_sdk-0.1.0/packages/runtime/nodes/executor.py +296 -0
  82. aegis_security_sdk-0.1.0/packages/runtime/nodes/planner.py +79 -0
  83. aegis_security_sdk-0.1.0/pyproject.toml +41 -0
  84. aegis_security_sdk-0.1.0/setup.cfg +4 -0
@@ -0,0 +1,95 @@
1
+ Metadata-Version: 2.4
2
+ Name: aegis-security-sdk
3
+ Version: 0.1.0
4
+ Summary: Aegis AI Security & Governance SDK
5
+ Requires-Python: >=3.11
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: langchain-core>=0.3.0
8
+ Requires-Dist: langchain-groq>=0.2.0
9
+ Requires-Dist: langgraph>=0.2.0
10
+ Requires-Dist: pydantic>=2.0.0
11
+ Requires-Dist: python-dotenv>=1.0.0
12
+ Requires-Dist: httpx>=0.27.0
13
+ Provides-Extra: openai
14
+ Requires-Dist: langchain-openai>=0.2.0; extra == "openai"
15
+ Provides-Extra: anthropic
16
+ Requires-Dist: langchain-anthropic>=0.3.0; extra == "anthropic"
17
+ Provides-Extra: google
18
+ Requires-Dist: langchain-google-genai>=2.0.0; extra == "google"
19
+ Provides-Extra: nvidia
20
+ Requires-Dist: langchain-nvidia-ai-endpoints>=0.3.0; extra == "nvidia"
21
+ Provides-Extra: crewai
22
+ Requires-Dist: crewai>=0.80.0; extra == "crewai"
23
+ Requires-Dist: crewai-tools>=0.14.0; extra == "crewai"
24
+ Provides-Extra: all
25
+ Requires-Dist: aegis-security-sdk[openai]; extra == "all"
26
+ Requires-Dist: aegis-security-sdk[anthropic]; extra == "all"
27
+ Requires-Dist: aegis-security-sdk[google]; extra == "all"
28
+ Requires-Dist: aegis-security-sdk[nvidia]; extra == "all"
29
+ Requires-Dist: aegis-security-sdk[crewai]; extra == "all"
30
+
31
+ # 🛡️ Aegis SDK — Enterprise AI Security & Governance
32
+
33
+ Aegis is a multi-layered security, governance, and policy engine for AI agents and LLM applications. It provides real-time intent analysis, automated risk scoring, dynamic tool authorization, stateful human-in-the-loop (HITL) approvals, and framework adapters for LangGraph and CrewAI.
34
+
35
+ ## Installation
36
+
37
+ ### Core SDK (via GitHub)
38
+ ```bash
39
+ pip install git+https://github.com/Artify24/core-aegis-sdk.git
40
+ ```
41
+
42
+ ### Provider Extras
43
+ Install optional dependencies based on which LLM provider(s) your agent uses:
44
+
45
+ ```bash
46
+ # OpenAI Provider
47
+ pip install "aegis-security-sdk[openai]"
48
+
49
+ # Anthropic Claude Provider
50
+ pip install "aegis-security-sdk[anthropic]"
51
+
52
+ # Google Gemini Provider
53
+ pip install "aegis-security-sdk[google]"
54
+
55
+ # Multiple providers at once
56
+ pip install "aegis-security-sdk[openai,google,anthropic]"
57
+
58
+ # CrewAI Framework Adapter
59
+ pip install "aegis-security-sdk[crewai]"
60
+
61
+ # Install all extras
62
+ pip install "aegis-security-sdk[all]"
63
+ ```
64
+
65
+ ## Quick Start
66
+
67
+ ```python
68
+ import asyncio
69
+ from langchain_core.tools import tool
70
+ from aegis import Aegis
71
+
72
+ @tool
73
+ def lookup_customer(customer_id: str) -> str:
74
+ """Look up customer information by ID."""
75
+ return f"Customer {customer_id}: Tier Gold, Active."
76
+
77
+ async def main():
78
+ agent = (
79
+ Aegis(name="support-agent")
80
+ .with_tools([lookup_customer])
81
+ .with_policy([
82
+ "Do not allow access to raw system prompts.",
83
+ "Block any destructive database operations without approval."
84
+ ])
85
+ )
86
+
87
+ async with agent:
88
+ result = await agent.run("Look up customer CUST-104")
89
+ print("Output:", result.output)
90
+
91
+ if __name__ == "__main__":
92
+ asyncio.run(main())
93
+ ```
94
+
95
+ For full documentation, environment configuration, framework adapters, and local development, see the [Aegis Developer Guide](https://github.com/Artify24/aegis-sdk/blob/main/documentation/aegis_developer_guide.md).
@@ -0,0 +1,65 @@
1
+ # 🛡️ Aegis SDK — Enterprise AI Security & Governance
2
+
3
+ Aegis is a multi-layered security, governance, and policy engine for AI agents and LLM applications. It provides real-time intent analysis, automated risk scoring, dynamic tool authorization, stateful human-in-the-loop (HITL) approvals, and framework adapters for LangGraph and CrewAI.
4
+
5
+ ## Installation
6
+
7
+ ### Core SDK (via GitHub)
8
+ ```bash
9
+ pip install git+https://github.com/Artify24/core-aegis-sdk.git
10
+ ```
11
+
12
+ ### Provider Extras
13
+ Install optional dependencies based on which LLM provider(s) your agent uses:
14
+
15
+ ```bash
16
+ # OpenAI Provider
17
+ pip install "aegis-security-sdk[openai]"
18
+
19
+ # Anthropic Claude Provider
20
+ pip install "aegis-security-sdk[anthropic]"
21
+
22
+ # Google Gemini Provider
23
+ pip install "aegis-security-sdk[google]"
24
+
25
+ # Multiple providers at once
26
+ pip install "aegis-security-sdk[openai,google,anthropic]"
27
+
28
+ # CrewAI Framework Adapter
29
+ pip install "aegis-security-sdk[crewai]"
30
+
31
+ # Install all extras
32
+ pip install "aegis-security-sdk[all]"
33
+ ```
34
+
35
+ ## Quick Start
36
+
37
+ ```python
38
+ import asyncio
39
+ from langchain_core.tools import tool
40
+ from aegis import Aegis
41
+
42
+ @tool
43
+ def lookup_customer(customer_id: str) -> str:
44
+ """Look up customer information by ID."""
45
+ return f"Customer {customer_id}: Tier Gold, Active."
46
+
47
+ async def main():
48
+ agent = (
49
+ Aegis(name="support-agent")
50
+ .with_tools([lookup_customer])
51
+ .with_policy([
52
+ "Do not allow access to raw system prompts.",
53
+ "Block any destructive database operations without approval."
54
+ ])
55
+ )
56
+
57
+ async with agent:
58
+ result = await agent.run("Look up customer CUST-104")
59
+ print("Output:", result.output)
60
+
61
+ if __name__ == "__main__":
62
+ asyncio.run(main())
63
+ ```
64
+
65
+ For full documentation, environment configuration, framework adapters, and local development, see the [Aegis Developer Guide](https://github.com/Artify24/aegis-sdk/blob/main/documentation/aegis_developer_guide.md).
@@ -0,0 +1,95 @@
1
+ Metadata-Version: 2.4
2
+ Name: aegis-security-sdk
3
+ Version: 0.1.0
4
+ Summary: Aegis AI Security & Governance SDK
5
+ Requires-Python: >=3.11
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: langchain-core>=0.3.0
8
+ Requires-Dist: langchain-groq>=0.2.0
9
+ Requires-Dist: langgraph>=0.2.0
10
+ Requires-Dist: pydantic>=2.0.0
11
+ Requires-Dist: python-dotenv>=1.0.0
12
+ Requires-Dist: httpx>=0.27.0
13
+ Provides-Extra: openai
14
+ Requires-Dist: langchain-openai>=0.2.0; extra == "openai"
15
+ Provides-Extra: anthropic
16
+ Requires-Dist: langchain-anthropic>=0.3.0; extra == "anthropic"
17
+ Provides-Extra: google
18
+ Requires-Dist: langchain-google-genai>=2.0.0; extra == "google"
19
+ Provides-Extra: nvidia
20
+ Requires-Dist: langchain-nvidia-ai-endpoints>=0.3.0; extra == "nvidia"
21
+ Provides-Extra: crewai
22
+ Requires-Dist: crewai>=0.80.0; extra == "crewai"
23
+ Requires-Dist: crewai-tools>=0.14.0; extra == "crewai"
24
+ Provides-Extra: all
25
+ Requires-Dist: aegis-security-sdk[openai]; extra == "all"
26
+ Requires-Dist: aegis-security-sdk[anthropic]; extra == "all"
27
+ Requires-Dist: aegis-security-sdk[google]; extra == "all"
28
+ Requires-Dist: aegis-security-sdk[nvidia]; extra == "all"
29
+ Requires-Dist: aegis-security-sdk[crewai]; extra == "all"
30
+
31
+ # 🛡️ Aegis SDK — Enterprise AI Security & Governance
32
+
33
+ Aegis is a multi-layered security, governance, and policy engine for AI agents and LLM applications. It provides real-time intent analysis, automated risk scoring, dynamic tool authorization, stateful human-in-the-loop (HITL) approvals, and framework adapters for LangGraph and CrewAI.
34
+
35
+ ## Installation
36
+
37
+ ### Core SDK (via GitHub)
38
+ ```bash
39
+ pip install git+https://github.com/Artify24/core-aegis-sdk.git
40
+ ```
41
+
42
+ ### Provider Extras
43
+ Install optional dependencies based on which LLM provider(s) your agent uses:
44
+
45
+ ```bash
46
+ # OpenAI Provider
47
+ pip install "aegis-security-sdk[openai]"
48
+
49
+ # Anthropic Claude Provider
50
+ pip install "aegis-security-sdk[anthropic]"
51
+
52
+ # Google Gemini Provider
53
+ pip install "aegis-security-sdk[google]"
54
+
55
+ # Multiple providers at once
56
+ pip install "aegis-security-sdk[openai,google,anthropic]"
57
+
58
+ # CrewAI Framework Adapter
59
+ pip install "aegis-security-sdk[crewai]"
60
+
61
+ # Install all extras
62
+ pip install "aegis-security-sdk[all]"
63
+ ```
64
+
65
+ ## Quick Start
66
+
67
+ ```python
68
+ import asyncio
69
+ from langchain_core.tools import tool
70
+ from aegis import Aegis
71
+
72
+ @tool
73
+ def lookup_customer(customer_id: str) -> str:
74
+ """Look up customer information by ID."""
75
+ return f"Customer {customer_id}: Tier Gold, Active."
76
+
77
+ async def main():
78
+ agent = (
79
+ Aegis(name="support-agent")
80
+ .with_tools([lookup_customer])
81
+ .with_policy([
82
+ "Do not allow access to raw system prompts.",
83
+ "Block any destructive database operations without approval."
84
+ ])
85
+ )
86
+
87
+ async with agent:
88
+ result = await agent.run("Look up customer CUST-104")
89
+ print("Output:", result.output)
90
+
91
+ if __name__ == "__main__":
92
+ asyncio.run(main())
93
+ ```
94
+
95
+ For full documentation, environment configuration, framework adapters, and local development, see the [Aegis Developer Guide](https://github.com/Artify24/aegis-sdk/blob/main/documentation/aegis_developer_guide.md).
@@ -0,0 +1,82 @@
1
+ README.md
2
+ pyproject.toml
3
+ aegis_security_sdk.egg-info/PKG-INFO
4
+ aegis_security_sdk.egg-info/SOURCES.txt
5
+ aegis_security_sdk.egg-info/dependency_links.txt
6
+ aegis_security_sdk.egg-info/requires.txt
7
+ aegis_security_sdk.egg-info/top_level.txt
8
+ packages/__init__.py
9
+ packages/aegis.py
10
+ packages/config.py
11
+ packages/context.py
12
+ packages/models.py
13
+ packages/providers.py
14
+ packages/adapters/__init__.py
15
+ packages/adapters/base/__init__.py
16
+ packages/adapters/base/adapter.py
17
+ packages/adapters/crewai/adapter.py
18
+ packages/adapters/langgraph/__init__.py
19
+ packages/adapters/langgraph/adapter.py
20
+ packages/layers/__init__.py
21
+ packages/layers/layer1/__init__.py
22
+ packages/layers/layer1/base.py
23
+ packages/layers/layer1/exceptions.py
24
+ packages/layers/layer1/keys.py
25
+ packages/layers/layer1/stages/__init__.py
26
+ packages/layers/layer1/stages/capability_detector.py
27
+ packages/layers/layer1/stages/intent_analysis.py
28
+ packages/layers/layer1/stages/memory_validation.py
29
+ packages/layers/layer1/stages/request_analyzer.py
30
+ packages/layers/layer1/stages/request_validation.py
31
+ packages/layers/layer1/stages/risk_engine.py
32
+ packages/layers/layer2/__init__.py
33
+ packages/layers/layer2/audit.py
34
+ packages/layers/layer2/engine.py
35
+ packages/layers/layer2/validators.py
36
+ packages/layers/layer5/__init__.py
37
+ packages/layers/layer5/consumer.py
38
+ packages/memory/__init__.py
39
+ packages/memory/conversation.py
40
+ packages/memory/manager.py
41
+ packages/memory/policies.py
42
+ packages/memory/provider.py
43
+ packages/memory/registry.py
44
+ packages/memory/retrieval.py
45
+ packages/memory/semantic.py
46
+ packages/memory/adapters/__init__.py
47
+ packages/memory/adapters/langgraph_adapter.py
48
+ packages/observability/__init__.py
49
+ packages/observability/models.py
50
+ packages/observability/store.py
51
+ packages/policy/__init__.py
52
+ packages/policy/base.py
53
+ packages/policy/nl_policy.py
54
+ packages/runtime/__init__.py
55
+ packages/runtime/factory.py
56
+ packages/runtime/graph.py
57
+ packages/runtime/events/__init__.py
58
+ packages/runtime/events/bus.py
59
+ packages/runtime/events/models.py
60
+ packages/runtime/hooks/__init__.py
61
+ packages/runtime/hooks/base.py
62
+ packages/runtime/hooks/policy.py
63
+ packages/runtime/kernel/__init__.py
64
+ packages/runtime/kernel/kernel.py
65
+ packages/runtime/kernel/state.py
66
+ packages/runtime/managers/__init__.py
67
+ packages/runtime/managers/executor.py
68
+ packages/runtime/managers/kill_switch.py
69
+ packages/runtime/managers/monitor.py
70
+ packages/runtime/managers/normalizer.py
71
+ packages/runtime/managers/provider_executor.py
72
+ packages/runtime/managers/provider_registry.py
73
+ packages/runtime/managers/registry.py
74
+ packages/runtime/managers/retry.py
75
+ packages/runtime/managers/sanitizer.py
76
+ packages/runtime/managers/streaming.py
77
+ packages/runtime/managers/supervisor.py
78
+ packages/runtime/managers/timeout.py
79
+ packages/runtime/managers/tracker.py
80
+ packages/runtime/nodes/__init__.py
81
+ packages/runtime/nodes/executor.py
82
+ packages/runtime/nodes/planner.py
@@ -0,0 +1,29 @@
1
+ langchain-core>=0.3.0
2
+ langchain-groq>=0.2.0
3
+ langgraph>=0.2.0
4
+ pydantic>=2.0.0
5
+ python-dotenv>=1.0.0
6
+ httpx>=0.27.0
7
+
8
+ [all]
9
+ aegis-security-sdk[openai]
10
+ aegis-security-sdk[anthropic]
11
+ aegis-security-sdk[google]
12
+ aegis-security-sdk[nvidia]
13
+ aegis-security-sdk[crewai]
14
+
15
+ [anthropic]
16
+ langchain-anthropic>=0.3.0
17
+
18
+ [crewai]
19
+ crewai>=0.80.0
20
+ crewai-tools>=0.14.0
21
+
22
+ [google]
23
+ langchain-google-genai>=2.0.0
24
+
25
+ [nvidia]
26
+ langchain-nvidia-ai-endpoints>=0.3.0
27
+
28
+ [openai]
29
+ langchain-openai>=0.2.0
@@ -0,0 +1 @@
1
+ # Aegis internal subpackages module
@@ -0,0 +1,4 @@
1
+ from .base.adapter import FrameworkAdapter
2
+ from .langgraph.adapter import LangGraphAdapter
3
+
4
+ __all__ = ["FrameworkAdapter", "LangGraphAdapter"]
@@ -0,0 +1,3 @@
1
+ from .adapter import FrameworkAdapter
2
+
3
+ __all__ = ["FrameworkAdapter"]
@@ -0,0 +1,26 @@
1
+ from typing import Protocol, Any
2
+ from ...context import ExecutionContext
3
+ from ...observability.models import ExecutionReport
4
+ from ...models import ExecutionResult
5
+
6
+ class FrameworkAdapter(Protocol):
7
+ """
8
+ Protocol for plugging an external agent framework into the Aegis Runtime.
9
+ Adapters handle Layer 3 (Execution) while keeping Layer 1, 2, and 4 intact.
10
+ """
11
+ async def execute(
12
+ self,
13
+ context: ExecutionContext,
14
+ inputs: dict[str, Any],
15
+ report: ExecutionReport
16
+ ) -> ExecutionResult:
17
+ """
18
+ Execute the external framework.
19
+
20
+ The adapter is responsible for:
21
+ 1. Invoking the framework's runtime.
22
+ 2. Intercepting telemetry (tool calls, tokens, latency, steps).
23
+ 3. Populating the `ExecutionReport` with the captured telemetry.
24
+ 4. Returning a standardized `ExecutionResult`.
25
+ """
26
+ ...
@@ -0,0 +1,263 @@
1
+ import time
2
+ from typing import Any, Dict
3
+ from langchain_core.callbacks import BaseCallbackHandler
4
+ from langchain_core.messages import AIMessage
5
+ from crewai import Crew
6
+
7
+ from ...context import ExecutionContext
8
+ from ...observability.models import ExecutionReport, ToolCallRecord, ExecutionPlanStep
9
+ from ...models import ExecutionResult
10
+ from ..base.adapter import FrameworkAdapter
11
+
12
+ import uuid
13
+
14
+ class CrewAITelemetryHandler(BaseCallbackHandler):
15
+ """
16
+ Captures synchronous and asynchronous callbacks from CrewAI execution.
17
+ CrewAI internally uses LangChain tools and LLMs, so these callbacks will fire.
18
+ """
19
+ def __init__(self, report: ExecutionReport):
20
+ self.report = report
21
+ self.tool_starts: dict[str, dict[str, Any]] = {}
22
+ self.llm_starts: dict[str, float] = {}
23
+ self.step_counter = 0
24
+
25
+ def on_llm_start(self, serialized: dict[str, Any], prompts: list[str], **kwargs: Any) -> None:
26
+ run_id = str(kwargs.get("run_id", ""))
27
+ self.llm_starts[run_id] = time.time()
28
+ self.report.metrics.resources.llm_calls += 1
29
+
30
+ async def on_llm_start_async(self, serialized: dict[str, Any], prompts: list[str], **kwargs: Any) -> None:
31
+ self.on_llm_start(serialized, prompts, **kwargs)
32
+
33
+ def on_llm_end(self, response: Any, **kwargs: Any) -> None:
34
+ run_id = str(kwargs.get("run_id", ""))
35
+ start = self.llm_starts.get(run_id, time.time())
36
+ latency = (time.time() - start) * 1000
37
+ self.report.planner.latency_ms += latency
38
+
39
+ # Check for tool calls to populate execution plan
40
+ if hasattr(response, "generations"):
41
+ for gen_list in response.generations:
42
+ for gen in gen_list:
43
+ msg = getattr(gen, "message", None)
44
+ if isinstance(msg, AIMessage) and hasattr(msg, "tool_calls") and msg.tool_calls:
45
+ self.report.planner.planning_iterations += 1
46
+ for tc in msg.tool_calls:
47
+ self.step_counter += 1
48
+ tool_name = tc.get("name", "unknown")
49
+ args = tc.get("args", {})
50
+ arg_keys = list(args.keys())[:3]
51
+ purpose_hint = ", ".join(arg_keys)
52
+ self.report.execution_plan.append(ExecutionPlanStep(
53
+ step=self.step_counter,
54
+ tool=tool_name,
55
+ purpose=f"Execute {tool_name}" + (f" ({purpose_hint})" if purpose_hint else ""),
56
+ ))
57
+
58
+ async def on_llm_end_async(self, response: Any, **kwargs: Any) -> None:
59
+ self.on_llm_end(response, **kwargs)
60
+
61
+ def on_tool_start(self, serialized: dict[str, Any], input_str: str, **kwargs: Any) -> None:
62
+ run_id = str(kwargs.get("run_id", ""))
63
+ self.tool_starts[run_id] = {
64
+ "start": time.time(),
65
+ "name": serialized.get("name", "unknown") if serialized else "unknown",
66
+ "input": input_str
67
+ }
68
+
69
+ async def on_tool_start_async(self, serialized: dict[str, Any], input_str: str, **kwargs: Any) -> None:
70
+ self.on_tool_start(serialized, input_str, **kwargs)
71
+
72
+ def on_tool_end(self, output: str, **kwargs: Any) -> None:
73
+ run_id = str(kwargs.get("run_id", ""))
74
+ tdata = self.tool_starts.get(run_id)
75
+ if tdata:
76
+ duration = (time.time() - tdata["start"]) * 1000
77
+ tc = ToolCallRecord(
78
+ tool_call_id=run_id,
79
+ tool=tdata["name"],
80
+ status="SUCCESS",
81
+ duration_ms=round(duration, 2),
82
+ input_summary=tdata["input"],
83
+ output_summary=str(output)
84
+ )
85
+ self.report.tool_calls.append(tc)
86
+ self.report.add_timeline_event(
87
+ "Runtime",
88
+ f"Tool Executed: {tdata['name']}",
89
+ metadata={"tool_call_id": run_id, "status": "SUCCESS", "duration_ms": duration}
90
+ )
91
+
92
+ async def on_tool_end_async(self, output: str, **kwargs: Any) -> None:
93
+ self.on_tool_end(output, **kwargs)
94
+
95
+ def on_tool_error(self, error: BaseException, **kwargs: Any) -> None:
96
+ run_id = str(kwargs.get("run_id", ""))
97
+ tdata = self.tool_starts.get(run_id)
98
+ if tdata:
99
+ duration = (time.time() - tdata["start"]) * 1000
100
+ tc = ToolCallRecord(
101
+ tool_call_id=run_id,
102
+ tool=tdata["name"],
103
+ status="FAILED",
104
+ duration_ms=round(duration, 2),
105
+ input_summary=tdata["input"],
106
+ error=str(error)
107
+ )
108
+ self.report.tool_calls.append(tc)
109
+ self.report.add_timeline_event(
110
+ "Runtime",
111
+ f"Tool Failed: {tdata['name']}",
112
+ metadata={"tool_call_id": run_id, "status": "FAILED", "duration_ms": duration}
113
+ )
114
+
115
+ async def on_tool_error_async(self, error: BaseException, **kwargs: Any) -> None:
116
+ self.on_tool_error(error, **kwargs)
117
+
118
+
119
+ class CrewAIAdapter(FrameworkAdapter):
120
+ """
121
+ Adapter for executing CrewAI crews through Aegis.
122
+ """
123
+ def __init__(self, crew: Crew):
124
+ self.crew = crew
125
+
126
+ def _wrap_tool(self, tool: Any, report: ExecutionReport) -> Any:
127
+ tool_name = getattr(tool, "name", str(tool))
128
+ orig_run = getattr(tool, "_run", None) or getattr(tool, "run", None) or getattr(tool, "func", None)
129
+ if not orig_run or getattr(tool, "_aegis_wrapped", False):
130
+ return tool
131
+
132
+ step_counter = [len(report.execution_plan) + 1]
133
+
134
+ def wrapped_run(*args: Any, **kwargs: Any) -> Any:
135
+ t_start = time.time()
136
+ tool_id = str(uuid.uuid4())
137
+ input_summary = str(kwargs) if kwargs else (str(args) if args else "")
138
+
139
+ report.execution_plan.append(ExecutionPlanStep(
140
+ step=step_counter[0],
141
+ tool=tool_name,
142
+ purpose=f"Execute {tool_name}"
143
+ ))
144
+ step_counter[0] += 1
145
+
146
+ status = "SUCCESS"
147
+ error_msg = None
148
+ result = None
149
+ try:
150
+ result = orig_run(*args, **kwargs)
151
+ return result
152
+ except Exception as e:
153
+ status = "FAILED"
154
+ error_msg = str(e)
155
+ raise e
156
+ finally:
157
+ duration_ms = round((time.time() - t_start) * 1000, 2)
158
+ output_str = str(result) if result is not None else (error_msg or "")
159
+
160
+ tc = ToolCallRecord(
161
+ tool_call_id=tool_id,
162
+ tool=tool_name,
163
+ status=status,
164
+ duration_ms=duration_ms,
165
+ input_summary=input_summary[:300],
166
+ output_summary=output_str[:300],
167
+ error=error_msg
168
+ )
169
+ report.tool_calls.append(tc)
170
+ report.add_timeline_event(
171
+ "Runtime",
172
+ f"Tool Executed: {tool_name}" if status == "SUCCESS" else f"Tool Failed: {tool_name}",
173
+ metadata={"tool_call_id": tool_id, "status": status, "duration_ms": duration_ms}
174
+ )
175
+
176
+ if hasattr(tool, "_run"):
177
+ tool._run = wrapped_run
178
+ elif hasattr(tool, "run"):
179
+ tool.run = wrapped_run
180
+ elif hasattr(tool, "func"):
181
+ tool.func = wrapped_run
182
+
183
+ setattr(tool, "_aegis_wrapped", True)
184
+ return tool
185
+
186
+ async def execute(
187
+ self,
188
+ context: ExecutionContext,
189
+ inputs: dict[str, Any],
190
+ report: ExecutionReport
191
+ ) -> ExecutionResult:
192
+
193
+ # 1. Setup Telemetry Handler
194
+ handler = CrewAITelemetryHandler(report)
195
+
196
+ # 2. Inject handler & wrap tools for telemetry capture
197
+ for agent in self.crew.agents:
198
+ if getattr(agent, "callbacks", None) is None:
199
+ agent.callbacks = []
200
+ agent.callbacks.append(handler)
201
+
202
+ if hasattr(agent, "tools") and agent.tools:
203
+ wrapped_tools = []
204
+ for tool in agent.tools:
205
+ wrapped_tools.append(self._wrap_tool(tool, report))
206
+ agent.tools = wrapped_tools
207
+
208
+ report.add_timeline_event("Planner", "CrewAI Execution Started")
209
+ start_time = time.time()
210
+
211
+ # 3. Clean Inputs
212
+ clean_inputs = {}
213
+ if "messages" in inputs and inputs["messages"]:
214
+ prompt = inputs["messages"][-1].content
215
+ clean_inputs["prompt"] = prompt
216
+ else:
217
+ clean_inputs["prompt"] = context.request.prompt
218
+
219
+ # 4. Invoke Crew
220
+ crew_output = await self.crew.kickoff_async(inputs=clean_inputs)
221
+
222
+ elapsed = (time.time() - start_time) * 1000
223
+ report.add_timeline_event("Planner", "CrewAI Execution Finished")
224
+
225
+ output_str = crew_output.raw if hasattr(crew_output, "raw") else str(crew_output)
226
+
227
+ # 5. Extract token usage if available from CrewOutput
228
+ if hasattr(crew_output, "token_usage") and crew_output.token_usage:
229
+ usage = crew_output.token_usage
230
+ if isinstance(usage, dict):
231
+ p_tokens = usage.get("prompt_tokens", 0) or usage.get("input_tokens", 0)
232
+ c_tokens = usage.get("completion_tokens", 0) or usage.get("output_tokens", 0)
233
+ t_tokens = usage.get("total_tokens", 0) or (p_tokens + c_tokens)
234
+ llm_calls = usage.get("successful_requests", 1)
235
+ else:
236
+ p_tokens = getattr(usage, "prompt_tokens", 0) or getattr(usage, "input_tokens", 0)
237
+ c_tokens = getattr(usage, "completion_tokens", 0) or getattr(usage, "output_tokens", 0)
238
+ t_tokens = getattr(usage, "total_tokens", 0) or (p_tokens + c_tokens)
239
+ llm_calls = getattr(usage, "successful_requests", 1)
240
+
241
+ report.planner.input_tokens = p_tokens
242
+ report.planner.output_tokens = c_tokens
243
+ report.planner.total_tokens = t_tokens
244
+ report.planner.total_llm_calls = llm_calls if llm_calls else 1
245
+ report.planner.planning_iterations = max(len(report.execution_plan), 1)
246
+ report.metrics.resources.llm_calls = report.planner.total_llm_calls
247
+
248
+ report.metrics.cost.input_tokens = p_tokens
249
+ report.metrics.cost.output_tokens = c_tokens
250
+ report.metrics.cost.total_tokens = t_tokens
251
+
252
+ # 6. Finalize tool metrics
253
+ report.metrics.resources.tool_calls = len(report.tool_calls)
254
+ total_tool_latency = sum(tc.duration_ms for tc in report.tool_calls)
255
+ report.metrics.performance.tool_latency_ms = round(total_tool_latency, 2)
256
+
257
+ return ExecutionResult(
258
+ output=output_str,
259
+ tool_calls=[tc.tool for tc in report.tool_calls],
260
+ tokens_used=report.planner.total_tokens,
261
+ execution_time=elapsed,
262
+ metadata={"layer1": getattr(context, "layer1", {})}
263
+ )
@@ -0,0 +1,3 @@
1
+ from .adapter import LangGraphAdapter
2
+
3
+ __all__ = ["LangGraphAdapter"]