authbinder 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,56 @@
1
+ Metadata-Version: 2.4
2
+ Name: authbinder
3
+ Version: 1.0.0
4
+ Summary: AI agent audit platform SDK. Captures telemetry from LangChain, CrewAI, AutoGen, LlamaIndex, and Haystack agents.
5
+ Author-email: AuthBinder <info@getauthbinder.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://authbinder.com
8
+ Keywords: ai,agents,audit,security,compliance,langchain,crewai,autogen
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Topic :: Security
14
+ Requires-Python: >=3.9
15
+ Description-Content-Type: text/markdown
16
+ Requires-Dist: httpx>=0.24.0
17
+
18
+ # AuthBinder SDK
19
+
20
+ AI agent audit platform. Automatically captures telemetry from your AI agents for risk scoring and compliance reporting.
21
+
22
+ ## Install
23
+
24
+ pip install authbinder
25
+
26
+ ## Usage
27
+
28
+ from authbinder import init, auto_instrument
29
+
30
+ init(
31
+ tenant_id="your-tenant-id",
32
+ api_key="ab_live_your-api-key",
33
+ package="baseline"
34
+ )
35
+ auto_instrument()
36
+
37
+ ## Supported frameworks
38
+
39
+ - LangChain
40
+ - CrewAI
41
+ - AutoGen
42
+ - LlamaIndex
43
+ - Haystack
44
+
45
+ ## Manual instrumentation
46
+
47
+ from authbinder import observe
48
+
49
+ @observe(destination="salesforce", action="read")
50
+ def crm_lookup(customer_id):
51
+ ...
52
+
53
+ ## Links
54
+
55
+ - Website: https://authbinder.com
56
+ - Support: info@getauthbinder.com
@@ -0,0 +1,39 @@
1
+ # AuthBinder SDK
2
+
3
+ AI agent audit platform. Automatically captures telemetry from your AI agents for risk scoring and compliance reporting.
4
+
5
+ ## Install
6
+
7
+ pip install authbinder
8
+
9
+ ## Usage
10
+
11
+ from authbinder import init, auto_instrument
12
+
13
+ init(
14
+ tenant_id="your-tenant-id",
15
+ api_key="ab_live_your-api-key",
16
+ package="baseline"
17
+ )
18
+ auto_instrument()
19
+
20
+ ## Supported frameworks
21
+
22
+ - LangChain
23
+ - CrewAI
24
+ - AutoGen
25
+ - LlamaIndex
26
+ - Haystack
27
+
28
+ ## Manual instrumentation
29
+
30
+ from authbinder import observe
31
+
32
+ @observe(destination="salesforce", action="read")
33
+ def crm_lookup(customer_id):
34
+ ...
35
+
36
+ ## Links
37
+
38
+ - Website: https://authbinder.com
39
+ - Support: info@getauthbinder.com
@@ -0,0 +1,236 @@
1
+ """
2
+ AuthBinder SDK v1.0
3
+ pip install authbinder
4
+ """
5
+ import os, time, uuid, hashlib, logging, functools, threading, queue
6
+ from datetime import datetime, timezone
7
+ from typing import Optional, Callable
8
+ from dataclasses import dataclass, field, asdict
9
+ import httpx
10
+
11
+ logger = logging.getLogger("authbinder")
12
+
13
+ @dataclass
14
+ class _Config:
15
+ tenant_id: str = ""
16
+ api_key: str = ""
17
+ api_url: str = "https://authbinder-prod-api.azurewebsites.net"
18
+ agent_id: str = "default-agent"
19
+ user_id: Optional[str] = None
20
+ batch_size: int = 50
21
+ flush_interval: float = 5.0
22
+ enabled: bool = False
23
+ debug: bool = False
24
+ package: str = "baseline"
25
+ expired: bool = False
26
+
27
+ _config = _Config()
28
+ _event_queue: queue.Queue = queue.Queue(maxsize=10000)
29
+ _flush_thread = None
30
+ _running = threading.Event()
31
+
32
+ def init(tenant_id=None, api_key=None, agent_id=None, api_url=None, package="baseline", debug=False):
33
+ global _config
34
+ _config.tenant_id = tenant_id or os.environ.get("AUTHBINDER_TENANT_ID", "")
35
+ _config.api_key = api_key or os.environ.get("AUTHBINDER_API_KEY", "")
36
+ _config.agent_id = agent_id or os.environ.get("AUTHBINDER_AGENT_ID", "default-agent")
37
+ _config.api_url = api_url or os.environ.get("AUTHBINDER_API_URL", "https://authbinder-prod-api.azurewebsites.net")
38
+ _config.package = package
39
+ _config.debug = debug
40
+ if not _config.tenant_id or not _config.api_key:
41
+ logger.warning("AuthBinder: credentials not set")
42
+ return
43
+ _config.enabled = True
44
+ _start_flush_thread()
45
+ logger.info(f"AuthBinder initialised - tenant={_config.tenant_id}")
46
+
47
+ def auto_instrument():
48
+ if not _config.enabled:
49
+ logger.warning("AuthBinder: call init() first")
50
+ return []
51
+ detected = []
52
+ if _patch_langchain(): detected.append("LangChain")
53
+ if _patch_crewai(): detected.append("CrewAI")
54
+ if _patch_autogen(): detected.append("AutoGen")
55
+ if _patch_llamaindex(): detected.append("LlamaIndex")
56
+ if _patch_haystack(): detected.append("Haystack")
57
+ logger.info(f"AuthBinder: instrumented {detected or 'none - use observe()'}")
58
+ return detected
59
+
60
+ def observe(func=None, *, tool_name=None, destination=None, action=None, approved=False):
61
+ def decorator(fn):
62
+ name = tool_name or fn.__name__
63
+ @functools.wraps(fn)
64
+ def wrapper(*args, **kwargs):
65
+ start = time.time()
66
+ success = True
67
+ try:
68
+ return fn(*args, **kwargs)
69
+ except Exception:
70
+ success = False
71
+ raise
72
+ finally:
73
+ _track(name, destination, action or _infer_action(name), approved, success, round((time.time()-start)*1000))
74
+ return wrapper
75
+ return decorator(func) if func is not None else decorator
76
+
77
+ def _patch_langchain():
78
+ try:
79
+ from langchain.tools import BaseTool
80
+ orig = BaseTool._run
81
+ @functools.wraps(orig)
82
+ def patched(self, *a, **kw):
83
+ start = time.time()
84
+ success = True
85
+ try: return orig(self, *a, **kw)
86
+ except Exception: success = False; raise
87
+ finally: _track(getattr(self,'name',self.__class__.__name__), _infer_destination_from_name(getattr(self,'name','')), _infer_action(getattr(self,'name','')), False, success, round((time.time()-start)*1000), "langchain")
88
+ BaseTool._run = patched
89
+ return True
90
+ except: return False
91
+
92
+ def _patch_crewai():
93
+ try:
94
+ from crewai.tools import BaseTool as T
95
+ orig = T._run
96
+ @functools.wraps(orig)
97
+ def patched(self, *a, **kw):
98
+ start = time.time()
99
+ success = True
100
+ try: return orig(self, *a, **kw)
101
+ except Exception: success = False; raise
102
+ finally: _track(getattr(self,'name',self.__class__.__name__), _infer_destination_from_name(getattr(self,'name','')), _infer_action(getattr(self,'name','')), False, success, round((time.time()-start)*1000), "crewai")
103
+ T._run = patched
104
+ return True
105
+ except: return False
106
+
107
+ def _patch_autogen():
108
+ try:
109
+ import autogen
110
+ orig = autogen.ConversableAgent._execute_tool_call
111
+ @functools.wraps(orig)
112
+ def patched(self, tool_call, *a, **kw):
113
+ start = time.time()
114
+ success = True
115
+ try: return orig(self, tool_call, *a, **kw)
116
+ except Exception: success = False; raise
117
+ finally:
118
+ fn = getattr(tool_call, 'function', {})
119
+ name = fn.name if hasattr(fn,'name') else fn.get('name','unknown') if isinstance(fn,dict) else str(fn)
120
+ _track(name, _infer_destination_from_name(name), _infer_action(name), False, success, round((time.time()-start)*1000), "autogen")
121
+ autogen.ConversableAgent._execute_tool_call = patched
122
+ return True
123
+ except: return False
124
+
125
+ def _patch_llamaindex():
126
+ try:
127
+ from llama_index.core.tools import BaseTool as T
128
+ orig = T.__call__
129
+ @functools.wraps(orig)
130
+ def patched(self, *a, **kw):
131
+ start = time.time()
132
+ success = True
133
+ try: return orig(self, *a, **kw)
134
+ except Exception: success = False; raise
135
+ finally:
136
+ meta = getattr(self,'metadata',None)
137
+ name = getattr(meta,'name',self.__class__.__name__) if meta else self.__class__.__name__
138
+ _track(name, _infer_destination_from_name(name), _infer_action(name), False, success, round((time.time()-start)*1000), "llamaindex")
139
+ T.__call__ = patched
140
+ return True
141
+ except: return False
142
+
143
+ def _patch_haystack():
144
+ try:
145
+ from haystack.core.component import Component
146
+ orig = Component.run
147
+ @functools.wraps(orig)
148
+ def patched(self, *a, **kw):
149
+ start = time.time()
150
+ success = True
151
+ try: return orig(self, *a, **kw)
152
+ except Exception: success = False; raise
153
+ finally: _track(self.__class__.__name__, _infer_destination_from_name(self.__class__.__name__), _infer_action(self.__class__.__name__), False, success, round((time.time()-start)*1000), "haystack")
154
+ Component.run = patched
155
+ return True
156
+ except: return False
157
+
158
+ def _infer_action(name):
159
+ n = name.lower()
160
+ if any(w in n for w in ["create","write","send","post","insert","add","upload"]): return "write"
161
+ if any(w in n for w in ["delete","remove","drop","destroy","purge"]): return "delete"
162
+ if any(w in n for w in ["update","patch","edit","modify"]): return "update"
163
+ return "read"
164
+
165
+ def _infer_destination_from_name(name):
166
+ n = name.lower()
167
+ for dest, keys in {"salesforce":["salesforce","crm"],"stripe":["stripe","payment"],"sendgrid":["email","smtp","mail"],"jira":["jira","ticket"],"github":["github","git"],"slack":["slack"],"postgres":["postgres","sql","database"],"s3":["s3","bucket","blob"],"openai":["openai","gpt"],"google":["google","gmail"]}.items():
168
+ if any(k in n for k in keys): return dest
169
+ return None
170
+
171
+ @dataclass
172
+ class _Event:
173
+ tenantId: str
174
+ agentId: str
175
+ tool: str
176
+ timestamp: str
177
+ userId: Optional[str] = None
178
+ destination: Optional[str] = None
179
+ action: Optional[str] = None
180
+ approved: bool = False
181
+ success: bool = True
182
+ durationMs: Optional[int] = None
183
+ framework: Optional[str] = None
184
+ metadata: dict = field(default_factory=dict)
185
+
186
+ def _track(tool, destination, action, approved, success, duration_ms, framework=None, metadata=None):
187
+ if not _config.enabled or _config.expired: return
188
+ try:
189
+ _event_queue.put_nowait(_Event(tenantId=_config.tenant_id, agentId=_config.agent_id, userId=_config.user_id, tool=tool, destination=destination, action=action, approved=approved, success=success, durationMs=duration_ms, framework=framework, timestamp=datetime.now(timezone.utc).isoformat(), metadata=metadata or {}))
190
+ except queue.Full:
191
+ logger.warning("AuthBinder: queue full")
192
+
193
+ def _flush():
194
+ if _event_queue.empty(): return
195
+ batch = []
196
+ while not _event_queue.empty() and len(batch) < _config.batch_size:
197
+ try: batch.append(_event_queue.get_nowait())
198
+ except queue.Empty: break
199
+ if not batch: return
200
+ try:
201
+ r = httpx.post(f"{_config.api_url}/events/batch", json={"events":[asdict(e) for e in batch]}, headers={"X-API-Key":_config.api_key}, timeout=10.0)
202
+ if r.status_code == 403: _config.expired = True; _running.clear(); return
203
+ r.raise_for_status()
204
+ except Exception as e:
205
+ logger.error(f"AuthBinder flush failed: {e}")
206
+ for ev in batch:
207
+ try: _event_queue.put_nowait(ev)
208
+ except queue.Full: pass
209
+
210
+ def _flush_loop():
211
+ while _running.is_set():
212
+ time.sleep(_config.flush_interval)
213
+ _flush()
214
+ _flush()
215
+
216
+ def _start_flush_thread():
217
+ global _flush_thread
218
+ _running.set()
219
+ _flush_thread = threading.Thread(target=_flush_loop, daemon=True, name="authbinder-flush")
220
+ _flush_thread.start()
221
+
222
+ def shutdown():
223
+ _running.clear()
224
+ if _flush_thread: _flush_thread.join(timeout=10)
225
+
226
+ def ping():
227
+ try:
228
+ r = httpx.get(f"{_config.api_url}/health", timeout=5.0)
229
+ print("Connected to AuthBinder" if r.status_code == 200 else f"AuthBinder returned {r.status_code}")
230
+ return r.status_code == 200
231
+ except Exception as e:
232
+ print(f"Could not reach AuthBinder: {e}")
233
+ return False
234
+
235
+ if os.environ.get("AUTHBINDER_API_KEY") and os.environ.get("AUTHBINDER_TENANT_ID"):
236
+ init()
@@ -0,0 +1,56 @@
1
+ Metadata-Version: 2.4
2
+ Name: authbinder
3
+ Version: 1.0.0
4
+ Summary: AI agent audit platform SDK. Captures telemetry from LangChain, CrewAI, AutoGen, LlamaIndex, and Haystack agents.
5
+ Author-email: AuthBinder <info@getauthbinder.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://authbinder.com
8
+ Keywords: ai,agents,audit,security,compliance,langchain,crewai,autogen
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Topic :: Security
14
+ Requires-Python: >=3.9
15
+ Description-Content-Type: text/markdown
16
+ Requires-Dist: httpx>=0.24.0
17
+
18
+ # AuthBinder SDK
19
+
20
+ AI agent audit platform. Automatically captures telemetry from your AI agents for risk scoring and compliance reporting.
21
+
22
+ ## Install
23
+
24
+ pip install authbinder
25
+
26
+ ## Usage
27
+
28
+ from authbinder import init, auto_instrument
29
+
30
+ init(
31
+ tenant_id="your-tenant-id",
32
+ api_key="ab_live_your-api-key",
33
+ package="baseline"
34
+ )
35
+ auto_instrument()
36
+
37
+ ## Supported frameworks
38
+
39
+ - LangChain
40
+ - CrewAI
41
+ - AutoGen
42
+ - LlamaIndex
43
+ - Haystack
44
+
45
+ ## Manual instrumentation
46
+
47
+ from authbinder import observe
48
+
49
+ @observe(destination="salesforce", action="read")
50
+ def crm_lookup(customer_id):
51
+ ...
52
+
53
+ ## Links
54
+
55
+ - Website: https://authbinder.com
56
+ - Support: info@getauthbinder.com
@@ -0,0 +1,8 @@
1
+ README.md
2
+ pyproject.toml
3
+ authbinder/__init__.py
4
+ authbinder.egg-info/PKG-INFO
5
+ authbinder.egg-info/SOURCES.txt
6
+ authbinder.egg-info/dependency_links.txt
7
+ authbinder.egg-info/requires.txt
8
+ authbinder.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ httpx>=0.24.0
@@ -0,0 +1 @@
1
+ authbinder
@@ -0,0 +1,32 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "authbinder"
7
+ version = "1.0.0"
8
+ description = "AI agent audit platform SDK. Captures telemetry from LangChain, CrewAI, AutoGen, LlamaIndex, and Haystack agents."
9
+ readme = "README.md"
10
+ license = {text = "MIT"}
11
+ requires-python = ">=3.9"
12
+ authors = [
13
+ {name = "AuthBinder", email = "info@getauthbinder.com"}
14
+ ]
15
+ keywords = ["ai", "agents", "audit", "security", "compliance", "langchain", "crewai", "autogen"]
16
+ classifiers = [
17
+ "Development Status :: 5 - Production/Stable",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3",
21
+ "Topic :: Security",
22
+ ]
23
+ dependencies = [
24
+ "httpx>=0.24.0",
25
+ ]
26
+
27
+ [project.urls]
28
+ Homepage = "https://authbinder.com"
29
+
30
+ [tool.setuptools.packages.find]
31
+ where = ["."]
32
+ include = ["authbinder*"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+