xshieldai-langchain 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,113 @@
1
+ Metadata-Version: 2.4
2
+ Name: xshieldai-langchain
3
+ Version: 1.0.0
4
+ Summary: xShieldAI / AEGIS DAN gate callback for LangChain agents — pre-execution governance via @xshieldai/aegis
5
+ Author-email: "Capt. Anil Sharma" <capt.anil.sharma@powerpbox.org>
6
+ License: AGPL-3.0
7
+ Project-URL: Homepage, https://xshieldai.com
8
+ Project-URL: Repository, https://github.com/rocketlang/aegis/tree/main/packages/xshieldai-langchain
9
+ Project-URL: Documentation, https://xshieldai.com/docs/langchain
10
+ Keywords: langchain,xshieldai,aegis,ai-governance,agent-safety
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: GNU Affero General Public License v3
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Software Development :: Libraries
20
+ Classifier: Topic :: Security
21
+ Requires-Python: >=3.9
22
+ Description-Content-Type: text/markdown
23
+ Provides-Extra: langchain
24
+ Requires-Dist: langchain-core>=0.1.0; extra == "langchain"
25
+ Provides-Extra: dev
26
+ Requires-Dist: pytest>=7; extra == "dev"
27
+ Requires-Dist: langchain-core>=0.1.0; extra == "dev"
28
+
29
+ # xshieldai-langchain
30
+
31
+ KavachOS DAN gate callback for LangChain agents.
32
+
33
+ Intercepts every tool call through the AEGIS KAVACH gate before execution.
34
+ Zero agent code changes — add the callback and every tool invocation is governed.
35
+
36
+ ## Install
37
+
38
+ ```bash
39
+ pip install xshieldai-langchain
40
+ ```
41
+
42
+ ## Quick start
43
+
44
+ ```python
45
+ from xshieldai_langchain import KavachGateCallback
46
+
47
+ callback = KavachGateCallback(
48
+ base_url="http://localhost:4850", # AEGIS server
49
+ on_block="raise", # raise KavachGateError on DAN-3/4
50
+ dry_run=False,
51
+ )
52
+
53
+ # LangChain agent — pass callback in config
54
+ result = agent.invoke(
55
+ {"input": "summarise the quarterly report"},
56
+ config={"callbacks": [callback]},
57
+ )
58
+
59
+ # Or attach to a single tool:
60
+ result = my_tool.invoke("drop table users", config={"callbacks": [callback]})
61
+ ```
62
+
63
+ ## KavachGateCallback parameters
64
+
65
+ | Parameter | Default | Description |
66
+ |---|---|---|
67
+ | `base_url` | `http://localhost:4850` | AEGIS server URL |
68
+ | `token` | `$AEGIS_TOKEN` | Bearer auth token |
69
+ | `on_block` | `"raise"` | `"raise"` → KavachGateError · `"warn"` → print + continue |
70
+ | `dry_run` | `False` | Classify only — no notification, no human-in-loop polling |
71
+ | `tool_name` | `"langchain"` | Label appearing in audit records |
72
+ | `session_id` | auto-generated | Audit grouping key (one per agent session) |
73
+
74
+ ## Direct client
75
+
76
+ ```python
77
+ from xshieldai_langchain import AegisClient
78
+
79
+ client = AegisClient(base_url="http://localhost:4850")
80
+
81
+ # Pre-flight budget check
82
+ state = client.state()
83
+ if state["budget"]["breached"]:
84
+ raise RuntimeError("Daily budget breached — halt")
85
+
86
+ # Manual gate call
87
+ result = client.gate(command="rm -rf /var/postgres", tool_name="my-agent")
88
+ print(result) # {"allow": false, "level": 4, "reason": "DAN-4 catastrophic..."}
89
+
90
+ # Audit query
91
+ records = client.audit(session_id="lc-abc123", status="stop", limit=20)
92
+ ```
93
+
94
+ ## How it works
95
+
96
+ `KavachGateCallback.on_tool_start()` fires before any tool execution.
97
+ It POSTs to `POST /api/v1/kavach/gate` on the AEGIS server.
98
+
99
+ - **DAN-1/2**: allowed immediately, logged.
100
+ - **DAN-3**: notify approver via Telegram/WhatsApp, wait for ALLOW/STOP.
101
+ - **DAN-4**: blocked immediately, `KavachGateError` raised.
102
+
103
+ All policy is in AEGIS — the callback is a thin HTTP relay.
104
+
105
+ ## AEGIS server
106
+
107
+ Run with: `bun /root/aegis/src/dashboard/server.ts`
108
+ Default port: `4850`
109
+ Gate endpoint: `POST /api/v1/kavach/gate`
110
+
111
+ ## License
112
+
113
+ AGPL-3.0 — see [LICENSE](../../LICENSE).
@@ -0,0 +1,85 @@
1
+ # xshieldai-langchain
2
+
3
+ KavachOS DAN gate callback for LangChain agents.
4
+
5
+ Intercepts every tool call through the AEGIS KAVACH gate before execution.
6
+ Zero agent code changes — add the callback and every tool invocation is governed.
7
+
8
+ ## Install
9
+
10
+ ```bash
11
+ pip install xshieldai-langchain
12
+ ```
13
+
14
+ ## Quick start
15
+
16
+ ```python
17
+ from xshieldai_langchain import KavachGateCallback
18
+
19
+ callback = KavachGateCallback(
20
+ base_url="http://localhost:4850", # AEGIS server
21
+ on_block="raise", # raise KavachGateError on DAN-3/4
22
+ dry_run=False,
23
+ )
24
+
25
+ # LangChain agent — pass callback in config
26
+ result = agent.invoke(
27
+ {"input": "summarise the quarterly report"},
28
+ config={"callbacks": [callback]},
29
+ )
30
+
31
+ # Or attach to a single tool:
32
+ result = my_tool.invoke("drop table users", config={"callbacks": [callback]})
33
+ ```
34
+
35
+ ## KavachGateCallback parameters
36
+
37
+ | Parameter | Default | Description |
38
+ |---|---|---|
39
+ | `base_url` | `http://localhost:4850` | AEGIS server URL |
40
+ | `token` | `$AEGIS_TOKEN` | Bearer auth token |
41
+ | `on_block` | `"raise"` | `"raise"` → KavachGateError · `"warn"` → print + continue |
42
+ | `dry_run` | `False` | Classify only — no notification, no human-in-loop polling |
43
+ | `tool_name` | `"langchain"` | Label appearing in audit records |
44
+ | `session_id` | auto-generated | Audit grouping key (one per agent session) |
45
+
46
+ ## Direct client
47
+
48
+ ```python
49
+ from xshieldai_langchain import AegisClient
50
+
51
+ client = AegisClient(base_url="http://localhost:4850")
52
+
53
+ # Pre-flight budget check
54
+ state = client.state()
55
+ if state["budget"]["breached"]:
56
+ raise RuntimeError("Daily budget breached — halt")
57
+
58
+ # Manual gate call
59
+ result = client.gate(command="rm -rf /var/postgres", tool_name="my-agent")
60
+ print(result) # {"allow": false, "level": 4, "reason": "DAN-4 catastrophic..."}
61
+
62
+ # Audit query
63
+ records = client.audit(session_id="lc-abc123", status="stop", limit=20)
64
+ ```
65
+
66
+ ## How it works
67
+
68
+ `KavachGateCallback.on_tool_start()` fires before any tool execution.
69
+ It POSTs to `POST /api/v1/kavach/gate` on the AEGIS server.
70
+
71
+ - **DAN-1/2**: allowed immediately, logged.
72
+ - **DAN-3**: notify approver via Telegram/WhatsApp, wait for ALLOW/STOP.
73
+ - **DAN-4**: blocked immediately, `KavachGateError` raised.
74
+
75
+ All policy is in AEGIS — the callback is a thin HTTP relay.
76
+
77
+ ## AEGIS server
78
+
79
+ Run with: `bun /root/aegis/src/dashboard/server.ts`
80
+ Default port: `4850`
81
+ Gate endpoint: `POST /api/v1/kavach/gate`
82
+
83
+ ## License
84
+
85
+ AGPL-3.0 — see [LICENSE](../../LICENSE).
@@ -0,0 +1,39 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "xshieldai-langchain"
7
+ version = "1.0.0"
8
+ description = "xShieldAI / AEGIS DAN gate callback for LangChain agents — pre-execution governance via @xshieldai/aegis"
9
+ readme = "README.md"
10
+ license = { text = "AGPL-3.0" }
11
+ authors = [{ name = "Capt. Anil Sharma", email = "capt.anil.sharma@powerpbox.org" }]
12
+ keywords = ["langchain", "xshieldai", "aegis", "ai-governance", "agent-safety"]
13
+ classifiers = [
14
+ "Development Status :: 4 - Beta",
15
+ "Intended Audience :: Developers",
16
+ "License :: OSI Approved :: GNU Affero General Public License v3",
17
+ "Programming Language :: Python :: 3",
18
+ "Programming Language :: Python :: 3.9",
19
+ "Programming Language :: Python :: 3.10",
20
+ "Programming Language :: Python :: 3.11",
21
+ "Programming Language :: Python :: 3.12",
22
+ "Topic :: Software Development :: Libraries",
23
+ "Topic :: Security",
24
+ ]
25
+ requires-python = ">=3.9"
26
+ dependencies = []
27
+
28
+ [project.optional-dependencies]
29
+ langchain = ["langchain-core>=0.1.0"]
30
+ dev = ["pytest>=7", "langchain-core>=0.1.0"]
31
+
32
+ [project.urls]
33
+ Homepage = "https://xshieldai.com"
34
+ Repository = "https://github.com/rocketlang/aegis/tree/main/packages/xshieldai-langchain"
35
+ Documentation = "https://xshieldai.com/docs/langchain"
36
+
37
+ [tool.setuptools.packages.find]
38
+ where = ["."]
39
+ include = ["xshieldai_langchain*"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,10 @@
1
+ # SPDX-License-Identifier: AGPL-3.0-only
2
+ # xshieldai-langchain — KavachOS governance callbacks for LangChain agents
3
+ # @rule:AEG-012 framework-agnostic: thin HTTP client, all policy in aegis
4
+ # @rule:KAV-001 every dangerous action intercepted before execution
5
+ # @rule:INF-KAV-025 LangChain callback intercepts tool calls at on_tool_start
6
+
7
+ from .gate import KavachGateCallback, KavachGateError, AegisClient
8
+
9
+ __all__ = ["KavachGateCallback", "KavachGateError", "AegisClient"]
10
+ __version__ = "1.0.0"
@@ -0,0 +1,232 @@
1
+ # SPDX-License-Identifier: AGPL-3.0-only
2
+ # @rule:KAV-001 every dangerous action intercepted before execution
3
+ # @rule:AEG-011 framework-agnostic: thin HTTP client, all policy in aegis
4
+ # @rule:AEG-012 LangChain adapter is the deployment surface for aegis governance
5
+ # @rule:INF-KAV-025 on_tool_start fires before any tool execution — correct interception point
6
+ from __future__ import annotations
7
+
8
+ import json
9
+ import os
10
+ import time
11
+ import uuid
12
+ from typing import Any, Dict, Optional, Union
13
+ from urllib.request import Request, urlopen
14
+ from urllib.error import URLError, HTTPError
15
+
16
+
17
+ class KavachGateError(Exception):
18
+ """Raised when the KAVACH gate blocks an action."""
19
+
20
+ def __init__(self, command: str, level: int, reason: str, approval_id: Optional[str] = None):
21
+ self.command = command
22
+ self.level = level
23
+ self.reason = reason
24
+ self.approval_id = approval_id
25
+ super().__init__(
26
+ f"KAVACH blocked (DAN-{level}): {reason}"
27
+ + (f" [approval_id={approval_id}]" if approval_id else "")
28
+ )
29
+
30
+
31
+ class AegisClient:
32
+ """Thin HTTP client for the AEGIS KAVACH gate API.
33
+
34
+ All policy is enforced in the AEGIS server — this client just relays calls.
35
+ stdlib only: no httpx/requests dependency.
36
+ """
37
+
38
+ def __init__(
39
+ self,
40
+ base_url: str = "http://localhost:4850",
41
+ token: Optional[str] = None,
42
+ timeout: int = 30,
43
+ ):
44
+ self.base_url = base_url.rstrip("/")
45
+ self.token = token or os.environ.get("AEGIS_TOKEN")
46
+ self.timeout = timeout
47
+
48
+ def _headers(self) -> Dict[str, str]:
49
+ h = {"Content-Type": "application/json"}
50
+ if self.token:
51
+ h["Authorization"] = f"Bearer {self.token}"
52
+ return h
53
+
54
+ def _post(self, path: str, payload: Dict[str, Any]) -> Dict[str, Any]:
55
+ url = f"{self.base_url}{path}"
56
+ data = json.dumps(payload).encode()
57
+ req = Request(url, data=data, headers=self._headers(), method="POST")
58
+ try:
59
+ with urlopen(req, timeout=self.timeout) as resp:
60
+ return json.loads(resp.read())
61
+ except HTTPError as e:
62
+ body = e.read().decode(errors="replace")
63
+ raise RuntimeError(f"Aegis HTTP {e.code} at {url}: {body}") from e
64
+ except URLError as e:
65
+ raise RuntimeError(f"Cannot reach Aegis at {url}: {e.reason}") from e
66
+
67
+ def _get(self, path: str, params: Optional[Dict[str, str]] = None) -> Dict[str, Any]:
68
+ qs = ""
69
+ if params:
70
+ from urllib.parse import urlencode
71
+ qs = "?" + urlencode({k: v for k, v in params.items() if v is not None})
72
+ url = f"{self.base_url}{path}{qs}"
73
+ req = Request(url, headers={k: v for k, v in self._headers().items() if k != "Content-Type"})
74
+ try:
75
+ with urlopen(req, timeout=self.timeout) as resp:
76
+ return json.loads(resp.read())
77
+ except HTTPError as e:
78
+ body = e.read().decode(errors="replace")
79
+ raise RuntimeError(f"Aegis HTTP {e.code} at {url}: {body}") from e
80
+ except URLError as e:
81
+ raise RuntimeError(f"Cannot reach Aegis at {url}: {e.reason}") from e
82
+
83
+ def gate(
84
+ self,
85
+ command: str,
86
+ tool_name: str = "langchain",
87
+ session_id: Optional[str] = None,
88
+ dry_run: bool = False,
89
+ ) -> Dict[str, Any]:
90
+ """POST /api/v1/kavach/gate — returns gate result dict."""
91
+ return self._post(
92
+ "/api/v1/kavach/gate",
93
+ {
94
+ "command": command,
95
+ "tool_name": tool_name,
96
+ "session_id": session_id,
97
+ "dry_run": dry_run,
98
+ },
99
+ )
100
+
101
+ def health(self) -> Dict[str, Any]:
102
+ return self._get("/api/v1/kavach/health")
103
+
104
+ def state(self) -> Dict[str, Any]:
105
+ return self._get("/api/v1/kavach/state")
106
+
107
+ def audit(
108
+ self,
109
+ session_id: Optional[str] = None,
110
+ status: Optional[str] = None,
111
+ level: Optional[int] = None,
112
+ limit: int = 50,
113
+ ) -> Dict[str, Any]:
114
+ params: Dict[str, str] = {"limit": str(limit)}
115
+ if session_id:
116
+ params["session_id"] = session_id
117
+ if status:
118
+ params["status"] = status
119
+ if level is not None:
120
+ params["level"] = str(level)
121
+ return self._get("/api/v1/kavach/audit", params)
122
+
123
+
124
+ class KavachGateCallback:
125
+ """LangChain callback handler that intercepts tool calls through the KAVACH DAN gate.
126
+
127
+ Drop-in: pass an instance in ``callbacks=[KavachGateCallback()]`` on any LangChain
128
+ agent or tool invocation. No agent code changes needed beyond adding the callback.
129
+
130
+ Usage::
131
+
132
+ from xshieldai_langchain import KavachGateCallback
133
+
134
+ callback = KavachGateCallback(
135
+ base_url="http://localhost:4850",
136
+ on_block="raise", # or "warn"
137
+ dry_run=False,
138
+ )
139
+
140
+ result = agent.invoke({"input": "drop all backups"}, config={"callbacks": [callback]})
141
+ """
142
+
143
+ def __init__(
144
+ self,
145
+ base_url: str = "http://localhost:4850",
146
+ token: Optional[str] = None,
147
+ on_block: str = "raise",
148
+ dry_run: bool = False,
149
+ tool_name: str = "langchain",
150
+ session_id: Optional[str] = None,
151
+ ):
152
+ """
153
+ Args:
154
+ base_url: AEGIS server URL.
155
+ token: Bearer token (or set AEGIS_TOKEN env var).
156
+ on_block: ``"raise"`` (raise KavachGateError) or ``"warn"`` (print warning, continue).
157
+ dry_run: Classify only — no notification, no polling.
158
+ tool_name: Label appearing in audit records.
159
+ session_id: Audit grouping key. Auto-generated per callback instance if not set.
160
+ """
161
+ if on_block not in ("raise", "warn"):
162
+ raise ValueError("on_block must be 'raise' or 'warn'")
163
+ self.client = AegisClient(base_url=base_url, token=token)
164
+ self.on_block = on_block
165
+ self.dry_run = dry_run
166
+ self.tool_name = tool_name
167
+ self.session_id = session_id or f"lc-{uuid.uuid4().hex[:12]}"
168
+
169
+ # ---- LangChain BaseCallbackHandler interface (duck-typed) ----
170
+
171
+ def on_tool_start(
172
+ self,
173
+ serialized: Dict[str, Any],
174
+ input_str: str,
175
+ *,
176
+ run_id: Any = None,
177
+ parent_run_id: Any = None,
178
+ tags: Optional[list] = None,
179
+ metadata: Optional[Dict[str, Any]] = None,
180
+ inputs: Optional[Dict[str, Any]] = None,
181
+ **kwargs: Any,
182
+ ) -> None:
183
+ """Intercept tool invocation before execution — the correct KAVACH gate point."""
184
+ tool_name = serialized.get("name", self.tool_name) if serialized else self.tool_name
185
+ command = input_str if isinstance(input_str, str) else json.dumps(input_str)
186
+
187
+ try:
188
+ result = self.client.gate(
189
+ command=command,
190
+ tool_name=tool_name,
191
+ session_id=self.session_id,
192
+ dry_run=self.dry_run,
193
+ )
194
+ except RuntimeError as e:
195
+ # Aegis unreachable — fail open (log only) to avoid blocking all tooling
196
+ import warnings
197
+ warnings.warn(f"[KavachGateCallback] Aegis unreachable — proceeding unguarded: {e}", stacklevel=2)
198
+ return
199
+
200
+ if not result.get("allow", True):
201
+ level = result.get("level", 0)
202
+ reason = result.get("reason", "blocked")
203
+ approval_id = result.get("approval_id")
204
+
205
+ if self.on_block == "raise":
206
+ raise KavachGateError(command=command, level=level, reason=reason, approval_id=approval_id)
207
+ else:
208
+ import warnings
209
+ warnings.warn(
210
+ f"[KavachGateCallback] KAVACH blocked DAN-{level}: {reason} — continuing (on_block=warn)",
211
+ stacklevel=2,
212
+ )
213
+
214
+ def on_tool_end(
215
+ self,
216
+ output: str,
217
+ *,
218
+ run_id: Any = None,
219
+ parent_run_id: Any = None,
220
+ **kwargs: Any,
221
+ ) -> None:
222
+ pass # post-execution hook — reserved for future telemetry
223
+
224
+ def on_tool_error(
225
+ self,
226
+ error: Union[Exception, KeyboardInterrupt],
227
+ *,
228
+ run_id: Any = None,
229
+ parent_run_id: Any = None,
230
+ **kwargs: Any,
231
+ ) -> None:
232
+ pass # error path — no gate action needed
@@ -0,0 +1,113 @@
1
+ Metadata-Version: 2.4
2
+ Name: xshieldai-langchain
3
+ Version: 1.0.0
4
+ Summary: xShieldAI / AEGIS DAN gate callback for LangChain agents — pre-execution governance via @xshieldai/aegis
5
+ Author-email: "Capt. Anil Sharma" <capt.anil.sharma@powerpbox.org>
6
+ License: AGPL-3.0
7
+ Project-URL: Homepage, https://xshieldai.com
8
+ Project-URL: Repository, https://github.com/rocketlang/aegis/tree/main/packages/xshieldai-langchain
9
+ Project-URL: Documentation, https://xshieldai.com/docs/langchain
10
+ Keywords: langchain,xshieldai,aegis,ai-governance,agent-safety
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: GNU Affero General Public License v3
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Software Development :: Libraries
20
+ Classifier: Topic :: Security
21
+ Requires-Python: >=3.9
22
+ Description-Content-Type: text/markdown
23
+ Provides-Extra: langchain
24
+ Requires-Dist: langchain-core>=0.1.0; extra == "langchain"
25
+ Provides-Extra: dev
26
+ Requires-Dist: pytest>=7; extra == "dev"
27
+ Requires-Dist: langchain-core>=0.1.0; extra == "dev"
28
+
29
+ # xshieldai-langchain
30
+
31
+ KavachOS DAN gate callback for LangChain agents.
32
+
33
+ Intercepts every tool call through the AEGIS KAVACH gate before execution.
34
+ Zero agent code changes — add the callback and every tool invocation is governed.
35
+
36
+ ## Install
37
+
38
+ ```bash
39
+ pip install xshieldai-langchain
40
+ ```
41
+
42
+ ## Quick start
43
+
44
+ ```python
45
+ from xshieldai_langchain import KavachGateCallback
46
+
47
+ callback = KavachGateCallback(
48
+ base_url="http://localhost:4850", # AEGIS server
49
+ on_block="raise", # raise KavachGateError on DAN-3/4
50
+ dry_run=False,
51
+ )
52
+
53
+ # LangChain agent — pass callback in config
54
+ result = agent.invoke(
55
+ {"input": "summarise the quarterly report"},
56
+ config={"callbacks": [callback]},
57
+ )
58
+
59
+ # Or attach to a single tool:
60
+ result = my_tool.invoke("drop table users", config={"callbacks": [callback]})
61
+ ```
62
+
63
+ ## KavachGateCallback parameters
64
+
65
+ | Parameter | Default | Description |
66
+ |---|---|---|
67
+ | `base_url` | `http://localhost:4850` | AEGIS server URL |
68
+ | `token` | `$AEGIS_TOKEN` | Bearer auth token |
69
+ | `on_block` | `"raise"` | `"raise"` → KavachGateError · `"warn"` → print + continue |
70
+ | `dry_run` | `False` | Classify only — no notification, no human-in-loop polling |
71
+ | `tool_name` | `"langchain"` | Label appearing in audit records |
72
+ | `session_id` | auto-generated | Audit grouping key (one per agent session) |
73
+
74
+ ## Direct client
75
+
76
+ ```python
77
+ from xshieldai_langchain import AegisClient
78
+
79
+ client = AegisClient(base_url="http://localhost:4850")
80
+
81
+ # Pre-flight budget check
82
+ state = client.state()
83
+ if state["budget"]["breached"]:
84
+ raise RuntimeError("Daily budget breached — halt")
85
+
86
+ # Manual gate call
87
+ result = client.gate(command="rm -rf /var/postgres", tool_name="my-agent")
88
+ print(result) # {"allow": false, "level": 4, "reason": "DAN-4 catastrophic..."}
89
+
90
+ # Audit query
91
+ records = client.audit(session_id="lc-abc123", status="stop", limit=20)
92
+ ```
93
+
94
+ ## How it works
95
+
96
+ `KavachGateCallback.on_tool_start()` fires before any tool execution.
97
+ It POSTs to `POST /api/v1/kavach/gate` on the AEGIS server.
98
+
99
+ - **DAN-1/2**: allowed immediately, logged.
100
+ - **DAN-3**: notify approver via Telegram/WhatsApp, wait for ALLOW/STOP.
101
+ - **DAN-4**: blocked immediately, `KavachGateError` raised.
102
+
103
+ All policy is in AEGIS — the callback is a thin HTTP relay.
104
+
105
+ ## AEGIS server
106
+
107
+ Run with: `bun /root/aegis/src/dashboard/server.ts`
108
+ Default port: `4850`
109
+ Gate endpoint: `POST /api/v1/kavach/gate`
110
+
111
+ ## License
112
+
113
+ AGPL-3.0 — see [LICENSE](../../LICENSE).
@@ -0,0 +1,9 @@
1
+ README.md
2
+ pyproject.toml
3
+ xshieldai_langchain/__init__.py
4
+ xshieldai_langchain/gate.py
5
+ xshieldai_langchain.egg-info/PKG-INFO
6
+ xshieldai_langchain.egg-info/SOURCES.txt
7
+ xshieldai_langchain.egg-info/dependency_links.txt
8
+ xshieldai_langchain.egg-info/requires.txt
9
+ xshieldai_langchain.egg-info/top_level.txt
@@ -0,0 +1,7 @@
1
+
2
+ [dev]
3
+ pytest>=7
4
+ langchain-core>=0.1.0
5
+
6
+ [langchain]
7
+ langchain-core>=0.1.0
@@ -0,0 +1 @@
1
+ xshieldai_langchain