viktron-sdk 0.2.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.
- viktron_sdk-0.2.0/PKG-INFO +107 -0
- viktron_sdk-0.2.0/README.md +79 -0
- viktron_sdk-0.2.0/pyproject.toml +35 -0
- viktron_sdk-0.2.0/setup.cfg +4 -0
- viktron_sdk-0.2.0/viktron_sdk/__init__.py +7 -0
- viktron_sdk-0.2.0/viktron_sdk/analytics.py +117 -0
- viktron_sdk-0.2.0/viktron_sdk/guard.py +356 -0
- viktron_sdk-0.2.0/viktron_sdk/integrations/__init__.py +0 -0
- viktron_sdk-0.2.0/viktron_sdk/integrations/autogen.py +191 -0
- viktron_sdk-0.2.0/viktron_sdk/integrations/crewai.py +125 -0
- viktron_sdk-0.2.0/viktron_sdk/integrations/langchain.py +74 -0
- viktron_sdk-0.2.0/viktron_sdk/telemetry.py +175 -0
- viktron_sdk-0.2.0/viktron_sdk.egg-info/PKG-INFO +107 -0
- viktron_sdk-0.2.0/viktron_sdk.egg-info/SOURCES.txt +15 -0
- viktron_sdk-0.2.0/viktron_sdk.egg-info/dependency_links.txt +1 -0
- viktron_sdk-0.2.0/viktron_sdk.egg-info/requires.txt +15 -0
- viktron_sdk-0.2.0/viktron_sdk.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: viktron-sdk
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Framework-agnostic governance SDK for AI agents — policy enforcement, telemetry, and observability
|
|
5
|
+
Author-email: Viktron AI <support@viktron.ai>
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://viktron.ai
|
|
8
|
+
Project-URL: Documentation, https://viktron.ai/docs
|
|
9
|
+
Project-URL: Repository, https://github.com/vikasvardhanv/viktron-agentsALR
|
|
10
|
+
Keywords: ai,agents,governance,telemetry,observability,llm
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
15
|
+
Requires-Python: >=3.9
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
Requires-Dist: httpx>=0.24.0
|
|
18
|
+
Provides-Extra: langchain
|
|
19
|
+
Requires-Dist: langchain-core>=0.1.0; extra == "langchain"
|
|
20
|
+
Provides-Extra: crewai
|
|
21
|
+
Requires-Dist: crewai>=0.1.0; extra == "crewai"
|
|
22
|
+
Provides-Extra: autogen
|
|
23
|
+
Requires-Dist: pyautogen>=0.2.0; extra == "autogen"
|
|
24
|
+
Provides-Extra: all
|
|
25
|
+
Requires-Dist: langchain-core>=0.1.0; extra == "all"
|
|
26
|
+
Requires-Dist: crewai>=0.1.0; extra == "all"
|
|
27
|
+
Requires-Dist: pyautogen>=0.2.0; extra == "all"
|
|
28
|
+
|
|
29
|
+
# Viktron SDK
|
|
30
|
+
|
|
31
|
+
Framework-agnostic governance SDK for AI agents — policy enforcement, telemetry, and real-time observability for production AI systems.
|
|
32
|
+
|
|
33
|
+
## Install
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pip install viktron-sdk
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Quick Start
|
|
40
|
+
|
|
41
|
+
### Telemetry (send agent events to your Viktron dashboard)
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from viktron_sdk import ViktronTelemetry
|
|
45
|
+
|
|
46
|
+
tel = ViktronTelemetry(api_key="vk_live_...", agent_slug="my-agent")
|
|
47
|
+
|
|
48
|
+
# Record a task
|
|
49
|
+
tel.record_task("task-123", status="completed", duration_ms=4200, cost_usd=0.003)
|
|
50
|
+
|
|
51
|
+
# Use a context-managed span
|
|
52
|
+
with tel.span("run_campaign") as span:
|
|
53
|
+
span.set_attribute("platform", "meta")
|
|
54
|
+
result = run_campaign()
|
|
55
|
+
span.set_output(result)
|
|
56
|
+
|
|
57
|
+
tel.close() # flush remaining events
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Policy Guard (intercept LLM calls with governance rules)
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
import openai
|
|
64
|
+
from viktron_sdk import ViktronGuard
|
|
65
|
+
|
|
66
|
+
client = ViktronGuard.wrap(
|
|
67
|
+
openai.OpenAI(),
|
|
68
|
+
api_key="vk_live_...",
|
|
69
|
+
agent_id="sales-agent-prod",
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
# All create() calls are now policy-checked
|
|
73
|
+
response = client.chat.completions.create(
|
|
74
|
+
model="gpt-4o",
|
|
75
|
+
messages=[{"role": "user", "content": "Hello"}],
|
|
76
|
+
)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Works with OpenAI (sync & async), Anthropic, Cohere, and any client with `.create()` / `.generate()` call patterns.
|
|
80
|
+
|
|
81
|
+
### Framework Integrations
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
# LangChain
|
|
85
|
+
from viktron_sdk.integrations.langchain import ViktronCallbackHandler
|
|
86
|
+
handler = ViktronCallbackHandler(api_key="vk_live_...", agent_id="my-chain")
|
|
87
|
+
|
|
88
|
+
# CrewAI
|
|
89
|
+
from viktron_sdk.integrations.crewai import ViktronCrewAIObserver
|
|
90
|
+
observer = ViktronCrewAIObserver(api_key="vk_live_...", agent_id="my-crew")
|
|
91
|
+
|
|
92
|
+
# AutoGen
|
|
93
|
+
from viktron_sdk.integrations.autogen import ViktronAutoGenHook
|
|
94
|
+
hook = ViktronAutoGenHook(api_key="vk_live_...", agent_id="my-autogen")
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## API Keys
|
|
98
|
+
|
|
99
|
+
Generate your API key at [app.viktron.ai](https://app.viktron.ai) → Settings → API Keys.
|
|
100
|
+
|
|
101
|
+
Keys prefixed `vk_live_` are production; `vk_test_` are for testing.
|
|
102
|
+
|
|
103
|
+
## Links
|
|
104
|
+
|
|
105
|
+
- [Dashboard](https://app.viktron.ai)
|
|
106
|
+
- [Documentation](https://viktron.ai/docs)
|
|
107
|
+
- [GitHub](https://github.com/vikasvardhanv/viktron-agentsALR)
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Viktron SDK
|
|
2
|
+
|
|
3
|
+
Framework-agnostic governance SDK for AI agents — policy enforcement, telemetry, and real-time observability for production AI systems.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install viktron-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
### Telemetry (send agent events to your Viktron dashboard)
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from viktron_sdk import ViktronTelemetry
|
|
17
|
+
|
|
18
|
+
tel = ViktronTelemetry(api_key="vk_live_...", agent_slug="my-agent")
|
|
19
|
+
|
|
20
|
+
# Record a task
|
|
21
|
+
tel.record_task("task-123", status="completed", duration_ms=4200, cost_usd=0.003)
|
|
22
|
+
|
|
23
|
+
# Use a context-managed span
|
|
24
|
+
with tel.span("run_campaign") as span:
|
|
25
|
+
span.set_attribute("platform", "meta")
|
|
26
|
+
result = run_campaign()
|
|
27
|
+
span.set_output(result)
|
|
28
|
+
|
|
29
|
+
tel.close() # flush remaining events
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Policy Guard (intercept LLM calls with governance rules)
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
import openai
|
|
36
|
+
from viktron_sdk import ViktronGuard
|
|
37
|
+
|
|
38
|
+
client = ViktronGuard.wrap(
|
|
39
|
+
openai.OpenAI(),
|
|
40
|
+
api_key="vk_live_...",
|
|
41
|
+
agent_id="sales-agent-prod",
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
# All create() calls are now policy-checked
|
|
45
|
+
response = client.chat.completions.create(
|
|
46
|
+
model="gpt-4o",
|
|
47
|
+
messages=[{"role": "user", "content": "Hello"}],
|
|
48
|
+
)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Works with OpenAI (sync & async), Anthropic, Cohere, and any client with `.create()` / `.generate()` call patterns.
|
|
52
|
+
|
|
53
|
+
### Framework Integrations
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
# LangChain
|
|
57
|
+
from viktron_sdk.integrations.langchain import ViktronCallbackHandler
|
|
58
|
+
handler = ViktronCallbackHandler(api_key="vk_live_...", agent_id="my-chain")
|
|
59
|
+
|
|
60
|
+
# CrewAI
|
|
61
|
+
from viktron_sdk.integrations.crewai import ViktronCrewAIObserver
|
|
62
|
+
observer = ViktronCrewAIObserver(api_key="vk_live_...", agent_id="my-crew")
|
|
63
|
+
|
|
64
|
+
# AutoGen
|
|
65
|
+
from viktron_sdk.integrations.autogen import ViktronAutoGenHook
|
|
66
|
+
hook = ViktronAutoGenHook(api_key="vk_live_...", agent_id="my-autogen")
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## API Keys
|
|
70
|
+
|
|
71
|
+
Generate your API key at [app.viktron.ai](https://app.viktron.ai) → Settings → API Keys.
|
|
72
|
+
|
|
73
|
+
Keys prefixed `vk_live_` are production; `vk_test_` are for testing.
|
|
74
|
+
|
|
75
|
+
## Links
|
|
76
|
+
|
|
77
|
+
- [Dashboard](https://app.viktron.ai)
|
|
78
|
+
- [Documentation](https://viktron.ai/docs)
|
|
79
|
+
- [GitHub](https://github.com/vikasvardhanv/viktron-agentsALR)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "viktron-sdk"
|
|
7
|
+
version = "0.2.0"
|
|
8
|
+
description = "Framework-agnostic governance SDK for AI agents — policy enforcement, telemetry, and observability"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "Apache-2.0"
|
|
11
|
+
authors = [{ name = "Viktron AI", email = "support@viktron.ai" }]
|
|
12
|
+
requires-python = ">=3.9"
|
|
13
|
+
dependencies = ["httpx>=0.24.0"]
|
|
14
|
+
keywords = ["ai", "agents", "governance", "telemetry", "observability", "llm"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 3 - Alpha",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
[project.optional-dependencies]
|
|
23
|
+
langchain = ["langchain-core>=0.1.0"]
|
|
24
|
+
crewai = ["crewai>=0.1.0"]
|
|
25
|
+
autogen = ["pyautogen>=0.2.0"]
|
|
26
|
+
all = ["langchain-core>=0.1.0", "crewai>=0.1.0", "pyautogen>=0.2.0"]
|
|
27
|
+
|
|
28
|
+
[project.urls]
|
|
29
|
+
Homepage = "https://viktron.ai"
|
|
30
|
+
Documentation = "https://viktron.ai/docs"
|
|
31
|
+
Repository = "https://github.com/vikasvardhanv/viktron-agentsALR"
|
|
32
|
+
|
|
33
|
+
[tool.setuptools.packages.find]
|
|
34
|
+
where = ["."]
|
|
35
|
+
include = ["viktron_sdk*"]
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"""Viktron SDK — policy enforcement and telemetry for AI agents."""
|
|
2
|
+
from .telemetry import ViktronTelemetry
|
|
3
|
+
from .analytics import ViktronAnalytics
|
|
4
|
+
from .guard import ViktronGuard, ViktronPolicyViolation
|
|
5
|
+
|
|
6
|
+
__all__ = ["ViktronTelemetry", "ViktronAnalytics", "ViktronGuard", "ViktronPolicyViolation"]
|
|
7
|
+
__version__ = "0.2.0"
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"""Direct API client for AGENT IRL analytics and AI metrics."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from datetime import datetime, timezone
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
import httpx
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ViktronAnalytics:
|
|
12
|
+
"""Thin client for /api/saas analytics endpoints."""
|
|
13
|
+
|
|
14
|
+
def __init__(self, auth_token: str, endpoint: str = "https://api.viktron.ai", timeout: float = 10.0):
|
|
15
|
+
self.auth_token = auth_token
|
|
16
|
+
self.endpoint = endpoint.rstrip("/")
|
|
17
|
+
self._client = httpx.Client(timeout=timeout)
|
|
18
|
+
|
|
19
|
+
def ingest_events(
|
|
20
|
+
self,
|
|
21
|
+
workspace_id: str,
|
|
22
|
+
events: list[dict[str, Any]],
|
|
23
|
+
batch_id: str | None = None,
|
|
24
|
+
idempotency_key: str | None = None,
|
|
25
|
+
) -> dict[str, Any]:
|
|
26
|
+
payload_events = []
|
|
27
|
+
for event in events:
|
|
28
|
+
item = dict(event)
|
|
29
|
+
item.setdefault("workspace_id", workspace_id)
|
|
30
|
+
item.setdefault("occurred_at", datetime.now(timezone.utc).isoformat())
|
|
31
|
+
payload_events.append(item)
|
|
32
|
+
|
|
33
|
+
headers = self._auth_headers()
|
|
34
|
+
if idempotency_key:
|
|
35
|
+
headers["x-idempotency-key"] = idempotency_key
|
|
36
|
+
|
|
37
|
+
response = self._client.post(
|
|
38
|
+
f"{self.endpoint}/api/saas/events/ingest",
|
|
39
|
+
json={"events": payload_events, "batch_id": batch_id},
|
|
40
|
+
headers=headers,
|
|
41
|
+
)
|
|
42
|
+
response.raise_for_status()
|
|
43
|
+
return response.json()
|
|
44
|
+
|
|
45
|
+
def record_llm_call(
|
|
46
|
+
self,
|
|
47
|
+
workspace_id: str,
|
|
48
|
+
*,
|
|
49
|
+
model: str,
|
|
50
|
+
provider: str,
|
|
51
|
+
input_tokens: int,
|
|
52
|
+
output_tokens: int,
|
|
53
|
+
latency_ms: int,
|
|
54
|
+
status: str = "ok",
|
|
55
|
+
mission_id: str | None = None,
|
|
56
|
+
session_id: str | None = None,
|
|
57
|
+
properties: dict[str, Any] | None = None,
|
|
58
|
+
) -> dict[str, Any]:
|
|
59
|
+
total_tokens = max(0, input_tokens) + max(0, output_tokens)
|
|
60
|
+
return self.ingest_events(
|
|
61
|
+
workspace_id=workspace_id,
|
|
62
|
+
events=[
|
|
63
|
+
{
|
|
64
|
+
"category": "llm",
|
|
65
|
+
"event": "llm_call",
|
|
66
|
+
"status": status,
|
|
67
|
+
"session_id": session_id,
|
|
68
|
+
"mission_id": mission_id,
|
|
69
|
+
"llm_provider": provider,
|
|
70
|
+
"llm_model": model,
|
|
71
|
+
"input_tokens": input_tokens,
|
|
72
|
+
"output_tokens": output_tokens,
|
|
73
|
+
"total_tokens": total_tokens,
|
|
74
|
+
"latency_ms": latency_ms,
|
|
75
|
+
"properties": properties or {},
|
|
76
|
+
}
|
|
77
|
+
],
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
def get_llm_analytics(self, workspace_id: str, lookback_hours: int = 168) -> dict[str, Any]:
|
|
81
|
+
response = self._client.get(
|
|
82
|
+
f"{self.endpoint}/api/saas/ai/llm-analytics",
|
|
83
|
+
params={"workspace_id": workspace_id, "lookback_hours": lookback_hours},
|
|
84
|
+
headers=self._auth_headers(),
|
|
85
|
+
)
|
|
86
|
+
response.raise_for_status()
|
|
87
|
+
return response.json()
|
|
88
|
+
|
|
89
|
+
def get_mission_analytics(self, workspace_id: str, lookback_hours: int = 168) -> dict[str, Any]:
|
|
90
|
+
response = self._client.get(
|
|
91
|
+
f"{self.endpoint}/api/saas/ai/mission-analytics",
|
|
92
|
+
params={"workspace_id": workspace_id, "lookback_hours": lookback_hours},
|
|
93
|
+
headers=self._auth_headers(),
|
|
94
|
+
)
|
|
95
|
+
response.raise_for_status()
|
|
96
|
+
return response.json()
|
|
97
|
+
|
|
98
|
+
def get_tool_failure_rates(self, workspace_id: str, lookback_days: int = 30) -> dict[str, Any]:
|
|
99
|
+
response = self._client.get(
|
|
100
|
+
f"{self.endpoint}/api/saas/events/queries/agent-failure-rate-by-tool",
|
|
101
|
+
params={"workspace_id": workspace_id, "lookback_days": lookback_days},
|
|
102
|
+
headers=self._auth_headers(),
|
|
103
|
+
)
|
|
104
|
+
response.raise_for_status()
|
|
105
|
+
return response.json()
|
|
106
|
+
|
|
107
|
+
def close(self) -> None:
|
|
108
|
+
self._client.close()
|
|
109
|
+
|
|
110
|
+
def __enter__(self) -> "ViktronAnalytics":
|
|
111
|
+
return self
|
|
112
|
+
|
|
113
|
+
def __exit__(self, *_: Any) -> None:
|
|
114
|
+
self.close()
|
|
115
|
+
|
|
116
|
+
def _auth_headers(self) -> dict[str, str]:
|
|
117
|
+
return {"Authorization": f"Bearer {self.auth_token}"}
|