correctover-ccs 1.0.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.
@@ -0,0 +1,236 @@
1
+ Metadata-Version: 2.4
2
+ Name: correctover-ccs
3
+ Version: 1.0.0
4
+ Summary: Correctover Conformance Standard (CCS) v1.0 — Synchronous interceptor governance for AI Agent frameworks
5
+ Author-email: Correctover Standards <wangguigui@correctover.com>
6
+ License: CC BY 4.0
7
+ Project-URL: Homepage, https://correctover.com
8
+ Project-URL: Paper, https://doi.org/10.5281/zenodo.21271910
9
+ Project-URL: Standard, https://github.com/Correctover/standards
10
+ Keywords: ai,agent,governance,security,conformance,mcp
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
14
+ Classifier: Topic :: Security
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown
20
+ Provides-Extra: mcp
21
+ Requires-Dist: mcp>=1.0.0; extra == "mcp"
22
+
23
+ # CCS — Correctover Conformance Standard v1.0
24
+
25
+ Synchronous interceptor-based governance for AI Agent frameworks.
26
+
27
+ ## Why CCS?
28
+
29
+ Every major Agent framework (CrewAI AGT, AutoGen, LangGraph) uses **observer-pattern hooks** for governance. These hooks are structurally vulnerable to **fail-open bypass** — when the governance layer throws an exception, the framework defaults to allowing tool execution.
30
+
31
+ **This is not a bug. It's an architectural flaw.** (CWE-636, CVSS 9.1)
32
+
33
+ CCS uses **function decorators** instead of hooks. The decorator owns the execution path — if governance fails, the tool is BLOCKED. Never allowed.
34
+
35
+ ```
36
+ Observer hooks: governance_crash → exception caught → hook_blocked=False → tool EXECUTES ❌
37
+ CCS decorators: governance_crash → exception caught → tool NEVER CALLED ✅
38
+ ```
39
+
40
+ ## Installation
41
+
42
+ ```bash
43
+ pip install ccs
44
+ ```
45
+
46
+ ## Quick Start (3 lines)
47
+
48
+ ```python
49
+ from ccs import govern
50
+
51
+ @govern(policy="default")
52
+ def my_tool(args: dict) -> str:
53
+ return "result"
54
+
55
+ # Governance evaluation happens BEFORE the function runs
56
+ # If denied → PermissionError, function never executes
57
+ ```
58
+
59
+ ## Framework Adapters
60
+
61
+ Adapters intercept at the framework's tool execution entry point.
62
+ Once installed, ALL tool calls go through CCS governance.
63
+
64
+ ### CrewAI
65
+ ```python
66
+ from ccs.adapters import crewai_adapter
67
+ crewai_adapter.install() # patches BaseTool.run globally
68
+ # All CrewAI tool calls now governed by CCS
69
+ crewai_adapter.uninstall() # restore original
70
+ ```
71
+
72
+ ### AutoGen (async)
73
+ ```python
74
+ from ccs.adapters import autogen_adapter
75
+ autogen_adapter.install() # patches FunctionTool.run
76
+ autogen_adapter.uninstall()
77
+ ```
78
+
79
+ ### LangGraph / LangChain
80
+ ```python
81
+ from ccs.adapters import langgraph_adapter
82
+ langgraph_adapter.install() # patches LCBaseTool.run
83
+ langgraph_adapter.uninstall()
84
+ ```
85
+
86
+ ### Verified Against
87
+ | Framework | Version | Interception Point | Pattern |
88
+ |-----------|---------|--------------------|---------|
89
+ | CrewAI | >= 0.1.0 | `BaseTool.run()` | sync |
90
+ | AutoGen | >= 0.7.0 | `FunctionTool.run()` | async |
91
+ | LangGraph | >= 0.2.0 | `LCBaseTool.run()` | sync |
92
+
93
+ ## Custom Policies
94
+
95
+ ```python
96
+ from ccs import CCSPolicy, GovernanceResult, govern
97
+
98
+ class CompliancePolicy(CCSPolicy):
99
+ def evaluate(self, tool_name: str, tool_input: dict) -> GovernanceResult:
100
+ if "delete" in tool_name.lower():
101
+ return GovernanceResult.DENY
102
+ return GovernanceResult.ALLOW
103
+
104
+ from ccs.core import get_runtime
105
+ runtime = get_runtime()
106
+ runtime.register_policy("compliance", CompliancePolicy())
107
+
108
+ @govern(policy="compliance")
109
+ def delete_user(user_id: str):
110
+ ... # This will never execute — policy denies it
111
+ ```
112
+
113
+ ## Fail-Closed Guarantee
114
+
115
+ The fundamental difference from observer-pattern hooks:
116
+
117
+ | | Observer Hooks (AGT) | CCS Decorators |
118
+ |---|---|---|
119
+ | Integration | Framework catches hook exception | Decorator owns execution path |
120
+ | On governance crash | `hook_blocked` stays `False` → tool executes | Exception propagates → tool never called |
121
+ | Fail mode | **FAIL-OPEN** ❌ | **FAIL-CLOSED** ✅ |
122
+ | CWE | CWE-636 (Not Failing Securely) | Structurally immune |
123
+
124
+ ## Performance
125
+
126
+ CANON benchmark (50,000 traces):
127
+ - **P50 latency: 22µs**
128
+ - **P99 latency: 99µs**
129
+
130
+ ## Test Results
131
+
132
+ Verified on 2026-07-09 with real framework installations:
133
+
134
+ ```
135
+ CrewAI Adapter: BaseTool.run intercepted → fail-closed ✅
136
+ AutoGen Adapter: FunctionTool.run intercepted → fail-closed ✅
137
+ LangGraph Adapter: LCBaseTool.run intercepted → fail-closed ✅
138
+ All adapters support install/uninstall lifecycle ✅
139
+ ```
140
+
141
+ Performance (10,000 iterations, decorator + policy evaluation):
142
+ ```
143
+ P50: 6.2µs
144
+ P99: 15.0µs
145
+ P999: 53.0µs
146
+ ```
147
+
148
+ ## MCP Server
149
+
150
+ CCS is available as a [Model Context Protocol](https://modelcontextprotocol.io) server, enabling any MCP-compatible agent (Claude Desktop, Cursor, Cline) to validate tool calls against CCS governance.
151
+
152
+ ```bash
153
+ pip install ccs[mcp]
154
+ python -m ccs.mcp_server
155
+ ```
156
+
157
+ Configure in Claude Desktop:
158
+ ```json
159
+ {
160
+ "mcpServers": {
161
+ "ccs": {
162
+ "command": "python",
163
+ "args": ["-m", "ccs.mcp_server"]
164
+ }
165
+ }
166
+ }
167
+ ```
168
+
169
+ ### MCP Tools
170
+ | Tool | Description |
171
+ |------|-------------|
172
+ | `ccs_govern` | Evaluate a tool call against a policy → allow/deny |
173
+ | `ccs_status` | Runtime stats, policies, latency metrics |
174
+ | `ccs_register_deny_rule` | Register custom deny rules by tool name/pattern |
175
+ | `ccs_audit_log` | Recent governance audit traces |
176
+
177
+ ## TypeScript SDK
178
+
179
+ ```bash
180
+ npm install correctover-ccs
181
+ ```
182
+
183
+ ```typescript
184
+ import { govern, GovernanceResult, CCSPolicy } from "correctover-ccs";
185
+
186
+ const governedSearch = govern(searchWeb, { policy: "default" });
187
+ governedSearch({ query: "test" }); // Throws PermissionError if denied
188
+ ```
189
+
190
+ Source: [`ts/`](./ts) | [npm package](https://www.npmjs.com/package/correctover-ccs)
191
+
192
+ ## Go SDK
193
+
194
+ ```bash
195
+ go get github.com/Correctover/ccs-sdk/go
196
+ ```
197
+
198
+ ```go
199
+ rt := ccs.NewRuntime()
200
+ governed := ccs.Govern(searchFn, "default", rt)
201
+ result, err := governed(ccs.ToolInput{"query": "CCS standard"})
202
+ // err = *PermissionError if denied — fn NEVER called
203
+ ```
204
+
205
+ Source: [`go/`](./go)
206
+
207
+ ## Repository Structure
208
+
209
+ ```
210
+ ccs-sdk/
211
+ ├── ccs/ # Python SDK (core + adapters + MCP server)
212
+ │ ├── core.py # Governance runtime
213
+ │ ├── adapters.py # CrewAI/AutoGen/LangGraph adapters
214
+ │ └── mcp_server/ # MCP server (stdio transport)
215
+ ├── ts/ # TypeScript SDK (npm: correctover-ccs)
216
+ │ ├── src/ # Source
217
+ │ └── dist/ # Built output
218
+ ├── go/ # Go SDK
219
+ │ └── ccs/ # Core package
220
+ ├── strict_9test.py # Python 9-test verification suite
221
+ └── pyproject.toml
222
+ ```
223
+
224
+ ## SDK Versions
225
+
226
+ | SDK | Version | Package |
227
+ |-----|---------|---------|
228
+ | Python | 1.0.0 | `pip install ccs` |
229
+ | TypeScript | 1.0.0 | `npm install correctover-ccs` |
230
+ | Go | 1.0.0 | `go get github.com/Correctover/ccs-sdk/go` |
231
+
232
+ ## References
233
+
234
+ - CCS v1.0 Standard: https://doi.org/10.5281/zenodo.21271910
235
+ - CVE Audit (CWE-636 in AGT): https://gist.github.com/Correctover/9cfb97bcf374f79b793fd0bacd4e9d62
236
+ - Correctover: https://correctover.com
@@ -0,0 +1,214 @@
1
+ # CCS — Correctover Conformance Standard v1.0
2
+
3
+ Synchronous interceptor-based governance for AI Agent frameworks.
4
+
5
+ ## Why CCS?
6
+
7
+ Every major Agent framework (CrewAI AGT, AutoGen, LangGraph) uses **observer-pattern hooks** for governance. These hooks are structurally vulnerable to **fail-open bypass** — when the governance layer throws an exception, the framework defaults to allowing tool execution.
8
+
9
+ **This is not a bug. It's an architectural flaw.** (CWE-636, CVSS 9.1)
10
+
11
+ CCS uses **function decorators** instead of hooks. The decorator owns the execution path — if governance fails, the tool is BLOCKED. Never allowed.
12
+
13
+ ```
14
+ Observer hooks: governance_crash → exception caught → hook_blocked=False → tool EXECUTES ❌
15
+ CCS decorators: governance_crash → exception caught → tool NEVER CALLED ✅
16
+ ```
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ pip install ccs
22
+ ```
23
+
24
+ ## Quick Start (3 lines)
25
+
26
+ ```python
27
+ from ccs import govern
28
+
29
+ @govern(policy="default")
30
+ def my_tool(args: dict) -> str:
31
+ return "result"
32
+
33
+ # Governance evaluation happens BEFORE the function runs
34
+ # If denied → PermissionError, function never executes
35
+ ```
36
+
37
+ ## Framework Adapters
38
+
39
+ Adapters intercept at the framework's tool execution entry point.
40
+ Once installed, ALL tool calls go through CCS governance.
41
+
42
+ ### CrewAI
43
+ ```python
44
+ from ccs.adapters import crewai_adapter
45
+ crewai_adapter.install() # patches BaseTool.run globally
46
+ # All CrewAI tool calls now governed by CCS
47
+ crewai_adapter.uninstall() # restore original
48
+ ```
49
+
50
+ ### AutoGen (async)
51
+ ```python
52
+ from ccs.adapters import autogen_adapter
53
+ autogen_adapter.install() # patches FunctionTool.run
54
+ autogen_adapter.uninstall()
55
+ ```
56
+
57
+ ### LangGraph / LangChain
58
+ ```python
59
+ from ccs.adapters import langgraph_adapter
60
+ langgraph_adapter.install() # patches LCBaseTool.run
61
+ langgraph_adapter.uninstall()
62
+ ```
63
+
64
+ ### Verified Against
65
+ | Framework | Version | Interception Point | Pattern |
66
+ |-----------|---------|--------------------|---------|
67
+ | CrewAI | >= 0.1.0 | `BaseTool.run()` | sync |
68
+ | AutoGen | >= 0.7.0 | `FunctionTool.run()` | async |
69
+ | LangGraph | >= 0.2.0 | `LCBaseTool.run()` | sync |
70
+
71
+ ## Custom Policies
72
+
73
+ ```python
74
+ from ccs import CCSPolicy, GovernanceResult, govern
75
+
76
+ class CompliancePolicy(CCSPolicy):
77
+ def evaluate(self, tool_name: str, tool_input: dict) -> GovernanceResult:
78
+ if "delete" in tool_name.lower():
79
+ return GovernanceResult.DENY
80
+ return GovernanceResult.ALLOW
81
+
82
+ from ccs.core import get_runtime
83
+ runtime = get_runtime()
84
+ runtime.register_policy("compliance", CompliancePolicy())
85
+
86
+ @govern(policy="compliance")
87
+ def delete_user(user_id: str):
88
+ ... # This will never execute — policy denies it
89
+ ```
90
+
91
+ ## Fail-Closed Guarantee
92
+
93
+ The fundamental difference from observer-pattern hooks:
94
+
95
+ | | Observer Hooks (AGT) | CCS Decorators |
96
+ |---|---|---|
97
+ | Integration | Framework catches hook exception | Decorator owns execution path |
98
+ | On governance crash | `hook_blocked` stays `False` → tool executes | Exception propagates → tool never called |
99
+ | Fail mode | **FAIL-OPEN** ❌ | **FAIL-CLOSED** ✅ |
100
+ | CWE | CWE-636 (Not Failing Securely) | Structurally immune |
101
+
102
+ ## Performance
103
+
104
+ CANON benchmark (50,000 traces):
105
+ - **P50 latency: 22µs**
106
+ - **P99 latency: 99µs**
107
+
108
+ ## Test Results
109
+
110
+ Verified on 2026-07-09 with real framework installations:
111
+
112
+ ```
113
+ CrewAI Adapter: BaseTool.run intercepted → fail-closed ✅
114
+ AutoGen Adapter: FunctionTool.run intercepted → fail-closed ✅
115
+ LangGraph Adapter: LCBaseTool.run intercepted → fail-closed ✅
116
+ All adapters support install/uninstall lifecycle ✅
117
+ ```
118
+
119
+ Performance (10,000 iterations, decorator + policy evaluation):
120
+ ```
121
+ P50: 6.2µs
122
+ P99: 15.0µs
123
+ P999: 53.0µs
124
+ ```
125
+
126
+ ## MCP Server
127
+
128
+ CCS is available as a [Model Context Protocol](https://modelcontextprotocol.io) server, enabling any MCP-compatible agent (Claude Desktop, Cursor, Cline) to validate tool calls against CCS governance.
129
+
130
+ ```bash
131
+ pip install ccs[mcp]
132
+ python -m ccs.mcp_server
133
+ ```
134
+
135
+ Configure in Claude Desktop:
136
+ ```json
137
+ {
138
+ "mcpServers": {
139
+ "ccs": {
140
+ "command": "python",
141
+ "args": ["-m", "ccs.mcp_server"]
142
+ }
143
+ }
144
+ }
145
+ ```
146
+
147
+ ### MCP Tools
148
+ | Tool | Description |
149
+ |------|-------------|
150
+ | `ccs_govern` | Evaluate a tool call against a policy → allow/deny |
151
+ | `ccs_status` | Runtime stats, policies, latency metrics |
152
+ | `ccs_register_deny_rule` | Register custom deny rules by tool name/pattern |
153
+ | `ccs_audit_log` | Recent governance audit traces |
154
+
155
+ ## TypeScript SDK
156
+
157
+ ```bash
158
+ npm install correctover-ccs
159
+ ```
160
+
161
+ ```typescript
162
+ import { govern, GovernanceResult, CCSPolicy } from "correctover-ccs";
163
+
164
+ const governedSearch = govern(searchWeb, { policy: "default" });
165
+ governedSearch({ query: "test" }); // Throws PermissionError if denied
166
+ ```
167
+
168
+ Source: [`ts/`](./ts) | [npm package](https://www.npmjs.com/package/correctover-ccs)
169
+
170
+ ## Go SDK
171
+
172
+ ```bash
173
+ go get github.com/Correctover/ccs-sdk/go
174
+ ```
175
+
176
+ ```go
177
+ rt := ccs.NewRuntime()
178
+ governed := ccs.Govern(searchFn, "default", rt)
179
+ result, err := governed(ccs.ToolInput{"query": "CCS standard"})
180
+ // err = *PermissionError if denied — fn NEVER called
181
+ ```
182
+
183
+ Source: [`go/`](./go)
184
+
185
+ ## Repository Structure
186
+
187
+ ```
188
+ ccs-sdk/
189
+ ├── ccs/ # Python SDK (core + adapters + MCP server)
190
+ │ ├── core.py # Governance runtime
191
+ │ ├── adapters.py # CrewAI/AutoGen/LangGraph adapters
192
+ │ └── mcp_server/ # MCP server (stdio transport)
193
+ ├── ts/ # TypeScript SDK (npm: correctover-ccs)
194
+ │ ├── src/ # Source
195
+ │ └── dist/ # Built output
196
+ ├── go/ # Go SDK
197
+ │ └── ccs/ # Core package
198
+ ├── strict_9test.py # Python 9-test verification suite
199
+ └── pyproject.toml
200
+ ```
201
+
202
+ ## SDK Versions
203
+
204
+ | SDK | Version | Package |
205
+ |-----|---------|---------|
206
+ | Python | 1.0.0 | `pip install ccs` |
207
+ | TypeScript | 1.0.0 | `npm install correctover-ccs` |
208
+ | Go | 1.0.0 | `go get github.com/Correctover/ccs-sdk/go` |
209
+
210
+ ## References
211
+
212
+ - CCS v1.0 Standard: https://doi.org/10.5281/zenodo.21271910
213
+ - CVE Audit (CWE-636 in AGT): https://gist.github.com/Correctover/9cfb97bcf374f79b793fd0bacd4e9d62
214
+ - Correctover: https://correctover.com
@@ -0,0 +1,31 @@
1
+ """
2
+ Correctover Conformance Standard (CCS) v1.0 — Python SDK
3
+
4
+ Synchronous interceptor-based governance for AI Agent frameworks.
5
+ Eliminates architectural fail-open bypasses inherent to observer-pattern hooks.
6
+
7
+ Usage:
8
+ from ccs import govern
9
+
10
+ @govern(policy="default")
11
+ def my_tool(args):
12
+ ...
13
+ """
14
+
15
+ __version__ = "1.0.0"
16
+ __author__ = "Correctover Standards"
17
+
18
+ from ccs.core import govern, GovernanceResult, CCSConfig, CCSPolicy, CCSRuntime, get_runtime
19
+ from ccs.adapters import crewai_adapter, autogen_adapter, langgraph_adapter
20
+
21
+ __all__ = [
22
+ "govern",
23
+ "GovernanceResult",
24
+ "CCSConfig",
25
+ "CCSPolicy",
26
+ "CCSRuntime",
27
+ "get_runtime",
28
+ "crewai_adapter",
29
+ "autogen_adapter",
30
+ "langgraph_adapter",
31
+ ]
@@ -0,0 +1,195 @@
1
+ """
2
+ CCS Framework Adapters — Verified interception for CrewAI, AutoGen, LangGraph.
3
+
4
+ Each adapter replaces the framework's observer-pattern hooks with CCS
5
+ synchronous interceptor decorators, eliminating CWE-636 fail-open vulnerabilities.
6
+
7
+ Verified against:
8
+ - CrewAI >= 0.1.0 (BaseTool.run sync interception)
9
+ - AutoGen >= 0.7.0 (FunctionTool.run async interception)
10
+ - LangGraph >= 0.2.0 (LCBaseTool.run sync interception)
11
+
12
+ Reference: CCS v1.0 Standard, Section 3 — Formal Framework
13
+ DOI: 10.5281/zenodo.21271910
14
+ """
15
+
16
+ from typing import Any, Optional
17
+
18
+
19
+ class CrewAIAdapter:
20
+ """
21
+ CCS adapter for CrewAI.
22
+
23
+ Intercepts crewai.tools.base_tool.BaseTool.run() — the single
24
+ entry point for ALL CrewAI tool executions. If CCS governance
25
+ denies or crashes, the tool is NEVER invoked (fail-closed).
26
+
27
+ Usage:
28
+ from ccs.adapters import crewai_adapter
29
+ crewai_adapter.install() # patches BaseTool.run globally
30
+ crewai_adapter.uninstall() # restores original
31
+ """
32
+
33
+ _original_run = None
34
+ _installed = False
35
+
36
+ @staticmethod
37
+ def install(policy: str = "default"):
38
+ """Install CCS governance on CrewAI's BaseTool.run."""
39
+ from crewai.tools.base_tool import BaseTool
40
+ from ccs.core import get_runtime, GovernanceResult
41
+
42
+ if CrewAIAdapter._installed:
43
+ return # Already installed
44
+
45
+ runtime = get_runtime()
46
+ CrewAIAdapter._original_run = BaseTool.run
47
+
48
+ def ccs_governed_run(self, *args, **kwargs):
49
+ tool_input = {"args": args, "kwargs": kwargs}
50
+ result, latency = runtime.evaluate(
51
+ tool_name=getattr(self, "name", type(self).__name__),
52
+ tool_input=tool_input,
53
+ policy_name=policy,
54
+ )
55
+ if result != GovernanceResult.ALLOW:
56
+ raise PermissionError(
57
+ f"CCS DENIED: {getattr(self, 'name', 'unknown')} "
58
+ f"(policy={policy}, latency={latency}µs)"
59
+ )
60
+ return CrewAIAdapter._original_run(self, *args, **kwargs)
61
+
62
+ BaseTool.run = ccs_governed_run
63
+ CrewAIAdapter._installed = True
64
+
65
+ @staticmethod
66
+ def uninstall():
67
+ """Restore original CrewAI BaseTool.run."""
68
+ if not CrewAIAdapter._installed:
69
+ return
70
+ from crewai.tools.base_tool import BaseTool
71
+ BaseTool.run = CrewAIAdapter._original_run
72
+ CrewAIAdapter._installed = False
73
+ CrewAIAdapter._original_run = None
74
+
75
+
76
+ class AutoGenAdapter:
77
+ """
78
+ CCS adapter for Microsoft AutoGen.
79
+
80
+ Intercepts autogen_core.tools.FunctionTool.run() — the async
81
+ entry point for all AutoGen function tool executions.
82
+
83
+ Note: AutoGen 0.7+ uses async run(args, cancellation_token).
84
+ The adapter preserves this async signature.
85
+
86
+ Usage:
87
+ from ccs.adapters import autogen_adapter
88
+ autogen_adapter.install()
89
+ autogen_adapter.uninstall()
90
+ """
91
+
92
+ _original_run = None
93
+ _installed = False
94
+
95
+ @staticmethod
96
+ def install(policy: str = "default"):
97
+ """Install CCS governance on AutoGen's FunctionTool.run."""
98
+ from autogen_core.tools import FunctionTool
99
+ from ccs.core import get_runtime, GovernanceResult
100
+
101
+ if AutoGenAdapter._installed:
102
+ return
103
+
104
+ runtime = get_runtime()
105
+ AutoGenAdapter._original_run = FunctionTool.run
106
+
107
+ async def ccs_governed_run(self, args, cancellation_token):
108
+ tool_input = {"args": str(args), "tool": self.name}
109
+ result, latency = runtime.evaluate(
110
+ tool_name=self.name,
111
+ tool_input=tool_input,
112
+ policy_name=policy,
113
+ )
114
+ if result != GovernanceResult.ALLOW:
115
+ raise PermissionError(
116
+ f"CCS DENIED: {self.name} "
117
+ f"(policy={policy}, latency={latency}µs)"
118
+ )
119
+ return await AutoGenAdapter._original_run(self, args, cancellation_token)
120
+
121
+ FunctionTool.run = ccs_governed_run
122
+ AutoGenAdapter._installed = True
123
+
124
+ @staticmethod
125
+ def uninstall():
126
+ """Restore original AutoGen FunctionTool.run."""
127
+ if not AutoGenAdapter._installed:
128
+ return
129
+ from autogen_core.tools import FunctionTool
130
+ FunctionTool.run = AutoGenAdapter._original_run
131
+ AutoGenAdapter._installed = False
132
+ AutoGenAdapter._original_run = None
133
+
134
+
135
+ class LangGraphAdapter:
136
+ """
137
+ CCS adapter for LangGraph / LangChain.
138
+
139
+ Intercepts langchain_core.tools.BaseTool.run() — the sync
140
+ entry point for all LangChain/LangGraph tool executions.
141
+ Also covers invoke() since it delegates to run().
142
+
143
+ Usage:
144
+ from ccs.adapters import langgraph_adapter
145
+ langgraph_adapter.install()
146
+ langgraph_adapter.uninstall()
147
+ """
148
+
149
+ _original_run = None
150
+ _installed = False
151
+
152
+ @staticmethod
153
+ def install(policy: str = "default"):
154
+ """Install CCS governance on LangChain's BaseTool.run."""
155
+ from langchain_core.tools import BaseTool as LCBaseTool
156
+ from ccs.core import get_runtime, GovernanceResult
157
+
158
+ if LangGraphAdapter._installed:
159
+ return
160
+
161
+ runtime = get_runtime()
162
+ LangGraphAdapter._original_run = LCBaseTool.run
163
+
164
+ def ccs_governed_run(self, tool_input, *args, **kwargs):
165
+ governance_input = {"tool_input": tool_input, "kwargs": kwargs}
166
+ result, latency = runtime.evaluate(
167
+ tool_name=getattr(self, "name", type(self).__name__),
168
+ tool_input=governance_input,
169
+ policy_name=policy,
170
+ )
171
+ if result != GovernanceResult.ALLOW:
172
+ raise PermissionError(
173
+ f"CCS DENIED: {getattr(self, 'name', 'unknown')} "
174
+ f"(policy={policy}, latency={latency}µs)"
175
+ )
176
+ return LangGraphAdapter._original_run(self, tool_input, *args, **kwargs)
177
+
178
+ LCBaseTool.run = ccs_governed_run
179
+ LangGraphAdapter._installed = True
180
+
181
+ @staticmethod
182
+ def uninstall():
183
+ """Restore original LangChain BaseTool.run."""
184
+ if not LangGraphAdapter._installed:
185
+ return
186
+ from langchain_core.tools import BaseTool as LCBaseTool
187
+ LCBaseTool.run = LangGraphAdapter._original_run
188
+ LangGraphAdapter._installed = False
189
+ LangGraphAdapter._original_run = None
190
+
191
+
192
+ # Convenience instances
193
+ crewai_adapter = CrewAIAdapter()
194
+ autogen_adapter = AutoGenAdapter()
195
+ langgraph_adapter = LangGraphAdapter()