enkryptai-sdk 1.0.19__tar.gz → 1.0.22__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 (49) hide show
  1. enkryptai_sdk-1.0.22/PKG-INFO +42 -0
  2. enkryptai_sdk-1.0.22/README.md +19 -0
  3. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/setup.py +1 -1
  4. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/dto/guardrails.py +113 -0
  5. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/dto/red_team.py +45 -0
  6. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/guardrails.py +91 -0
  7. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/red_team.py +28 -0
  8. enkryptai_sdk-1.0.22/src/enkryptai_sdk.egg-info/PKG-INFO +42 -0
  9. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/tests/test_ai_proxy.py +2 -2
  10. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/tests/test_all_v2.py +50 -0
  11. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/tests/test_guardrails.py +40 -0
  12. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/tests/test_redteam.py +22 -12
  13. enkryptai_sdk-1.0.19/PKG-INFO +0 -1994
  14. enkryptai_sdk-1.0.19/README.md +0 -1971
  15. enkryptai_sdk-1.0.19/src/enkryptai_sdk.egg-info/PKG-INFO +0 -1994
  16. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/LICENSE +0 -0
  17. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/setup.cfg +0 -0
  18. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/__init__.py +0 -0
  19. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/ai_proxy.py +0 -0
  20. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/base.py +0 -0
  21. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/coc.py +0 -0
  22. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/config.py +0 -0
  23. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/datasets.py +0 -0
  24. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/deployments.py +0 -0
  25. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/dto/__init__.py +0 -0
  26. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/dto/ai_proxy.py +0 -0
  27. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/dto/base.py +0 -0
  28. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/dto/coc.py +0 -0
  29. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/dto/common.py +0 -0
  30. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/dto/datasets.py +0 -0
  31. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/dto/deployments.py +0 -0
  32. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/dto/models.py +0 -0
  33. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/evals.py +0 -0
  34. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/guardrails_old.py +0 -0
  35. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/models.py +0 -0
  36. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/response.py +0 -0
  37. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk.egg-info/SOURCES.txt +0 -0
  38. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk.egg-info/dependency_links.txt +0 -0
  39. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk.egg-info/top_level.txt +0 -0
  40. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/tests/test_all.py +0 -0
  41. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/tests/test_basic.py +0 -0
  42. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/tests/test_coc.py +0 -0
  43. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/tests/test_datasets.py +0 -0
  44. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/tests/test_deployments.py +0 -0
  45. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/tests/test_detect_policy.py +0 -0
  46. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/tests/test_injection_attack.py +0 -0
  47. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/tests/test_model.py +0 -0
  48. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/tests/test_openai.py +0 -0
  49. {enkryptai_sdk-1.0.19 → enkryptai_sdk-1.0.22}/tests/test_policy_violation.py +0 -0
@@ -0,0 +1,42 @@
1
+ Metadata-Version: 2.4
2
+ Name: enkryptai-sdk
3
+ Version: 1.0.22
4
+ Summary: A Python SDK with guardrails and red teaming functionality for API interactions
5
+ Home-page: https://github.com/enkryptai/enkryptai-sdk
6
+ Author: Enkrypt AI Team
7
+ Author-email: software@enkryptai.com
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.11
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Dynamic: author
15
+ Dynamic: author-email
16
+ Dynamic: classifier
17
+ Dynamic: description
18
+ Dynamic: description-content-type
19
+ Dynamic: home-page
20
+ Dynamic: license-file
21
+ Dynamic: requires-python
22
+ Dynamic: summary
23
+
24
+ # Enkrypt AI Python SDK
25
+
26
+ ![Python SDK test](https://github.com/enkryptai/enkryptai-sdk/actions/workflows/test.yaml/badge.svg)
27
+
28
+ A Python SDK with Guardrails, Code of Conduct Policies, Endpoints (Models), Deployments, AI Proxy, Datasets, Red Team, etc. functionality for API interactions.
29
+
30
+ **See documentation at [https://docs.enkryptai.com/libraries/python/introduction](https://docs.enkryptai.com/libraries/python/introduction)**
31
+
32
+ See [https://pypi.org/project/enkryptai-sdk](https://pypi.org/project/enkryptai-sdk)
33
+
34
+ ## Copyright, License and Terms of Use
35
+
36
+ © 2025 Enkrypt AI. All rights reserved.
37
+
38
+ Enkrypt AI software is provided under a proprietary license. Unauthorized use, reproduction, or distribution of this software or any portion of it is strictly prohibited.
39
+
40
+ Terms of Use: [https://www.enkryptai.com/terms-and-conditions](https://www.enkryptai.com/terms-and-conditions)
41
+
42
+ Enkrypt AI and the Enkrypt AI logo are trademarks of Enkrypt AI, Inc.
@@ -0,0 +1,19 @@
1
+ # Enkrypt AI Python SDK
2
+
3
+ ![Python SDK test](https://github.com/enkryptai/enkryptai-sdk/actions/workflows/test.yaml/badge.svg)
4
+
5
+ A Python SDK with Guardrails, Code of Conduct Policies, Endpoints (Models), Deployments, AI Proxy, Datasets, Red Team, etc. functionality for API interactions.
6
+
7
+ **See documentation at [https://docs.enkryptai.com/libraries/python/introduction](https://docs.enkryptai.com/libraries/python/introduction)**
8
+
9
+ See [https://pypi.org/project/enkryptai-sdk](https://pypi.org/project/enkryptai-sdk)
10
+
11
+ ## Copyright, License and Terms of Use
12
+
13
+ © 2025 Enkrypt AI. All rights reserved.
14
+
15
+ Enkrypt AI software is provided under a proprietary license. Unauthorized use, reproduction, or distribution of this software or any portion of it is strictly prohibited.
16
+
17
+ Terms of Use: [https://www.enkryptai.com/terms-and-conditions](https://www.enkryptai.com/terms-and-conditions)
18
+
19
+ Enkrypt AI and the Enkrypt AI logo are trademarks of Enkrypt AI, Inc.
@@ -9,7 +9,7 @@ with open(os.path.join(here, "README.md"), encoding="utf-8") as fh:
9
9
  setup(
10
10
  name="enkryptai-sdk", # This is the name of your package on PyPI
11
11
  # NOTE: Also change this in .github/workflows/test.yaml
12
- version="1.0.19", # Update this for new versions
12
+ version="1.0.22", # Update this for new versions
13
13
  description="A Python SDK with guardrails and red teaming functionality for API interactions",
14
14
  long_description=long_description,
15
15
  long_description_content_type="text/markdown",
@@ -1625,4 +1625,117 @@ class GuardrailsPolicyAtomizerResponse(BaseDTO):
1625
1625
  f"Total Rules: {self.total_rules}\n"
1626
1626
  f"Message: {self.message}"
1627
1627
  )
1628
+
1629
+
1630
+ @dataclass
1631
+ class GuardrailsViolation(BaseDTO):
1632
+ unsafe_content: str
1633
+ chunk_type: str
1634
+ triggered_detectors: List[str]
1635
+ guardrails_result: Dict[str, Any]
1636
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
1637
+
1638
+ @classmethod
1639
+ def from_dict(cls, data: Dict[str, Any]) -> "GuardrailsViolation":
1640
+ return cls(
1641
+ unsafe_content=data.get("unsafe_content", ""),
1642
+ chunk_type=data.get("chunk_type", ""),
1643
+ triggered_detectors=data.get("triggered_detectors", []),
1644
+ guardrails_result=data.get("guardrails_result", {})
1645
+ )
1628
1646
 
1647
+ def to_dict(self) -> Dict[str, Any]:
1648
+ result = {
1649
+ "unsafe_content": self.unsafe_content,
1650
+ "chunk_type": self.chunk_type,
1651
+ "triggered_detectors": self.triggered_detectors,
1652
+ "guardrails_result": self.guardrails_result
1653
+ }
1654
+ result.update(self._extra_fields)
1655
+ return result
1656
+
1657
+
1658
+ @dataclass
1659
+ class GuardrailsScanUrlResponse(BaseDTO):
1660
+ url: str
1661
+ violations: List[GuardrailsViolation]
1662
+ combined_highlight_url: str
1663
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
1664
+
1665
+ @classmethod
1666
+ def from_dict(cls, data: Dict[str, Any]) -> "GuardrailsScanUrlResponse":
1667
+ violations_data = data.get("violations", [])
1668
+ violations = [GuardrailsViolation.from_dict(violation) for violation in violations_data]
1669
+
1670
+ return cls(
1671
+ url=data.get("url", ""),
1672
+ violations=violations,
1673
+ combined_highlight_url=data.get("combined_highlight_url", "")
1674
+ )
1675
+
1676
+ def to_dict(self) -> Dict[str, Any]:
1677
+ result = {
1678
+ "url": self.url,
1679
+ "violations": [violation.to_dict() for violation in self.violations],
1680
+ "combined_highlight_url": self.combined_highlight_url
1681
+ }
1682
+ result.update(self._extra_fields)
1683
+ return result
1684
+
1685
+ def has_violations(self) -> bool:
1686
+ """
1687
+ Check if any detectors found violations in the URL content.
1688
+
1689
+ Returns:
1690
+ bool: True if any violations were detected, False otherwise
1691
+ """
1692
+ return len(self.violations) > 0
1693
+
1694
+ def get_violations(self) -> List[str]:
1695
+ """
1696
+ Get a list of detector names that found violations.
1697
+
1698
+ Returns:
1699
+ List[str]: Names of detectors that reported violations
1700
+ """
1701
+ triggered_detectors = []
1702
+ for violation in self.violations:
1703
+ triggered_detectors.extend(violation.triggered_detectors)
1704
+ # Remove duplicates while preserving order
1705
+ return list(dict.fromkeys(triggered_detectors))
1706
+
1707
+ def is_safe(self) -> bool:
1708
+ """
1709
+ Check if the URL content is safe (no violations detected).
1710
+
1711
+ Returns:
1712
+ bool: True if no violations were detected, False otherwise
1713
+ """
1714
+ return not self.has_violations()
1715
+
1716
+ def is_attack(self) -> bool:
1717
+ """
1718
+ Check if the URL content is attacked (violations detected).
1719
+
1720
+ Returns:
1721
+ bool: True if violations were detected, False otherwise
1722
+ """
1723
+ return self.has_violations()
1724
+
1725
+ def __str__(self) -> str:
1726
+ """
1727
+ String representation of the response.
1728
+
1729
+ Returns:
1730
+ str: A formatted string showing URL, violations and status
1731
+ """
1732
+ violations = self.get_violations()
1733
+ status = "UNSAFE" if violations else "SAFE"
1734
+
1735
+ if violations:
1736
+ violation_str = f"Violations detected: {', '.join(violations)}"
1737
+ else:
1738
+ violation_str = "No violations detected"
1739
+
1740
+ return f"URL Scan Result for {self.url}\nStatus: {status}\n{violation_str}"
1741
+
@@ -422,6 +422,7 @@ class RedTeamTestConfigurations(BaseDTO):
422
422
  reliability_and_observability_test: TestConfig = field(default=None)
423
423
  agent_behaviour_test: TestConfig = field(default=None)
424
424
  access_control_and_permissions_test: TestConfig = field(default=None)
425
+ tool_extraction_test: TestConfig = field(default=None)
425
426
  _extra_fields: Dict[str, Any] = field(default_factory=dict)
426
427
 
427
428
  @classmethod
@@ -799,6 +800,50 @@ class RedTeamRiskMitigationSystemPromptResponse(BaseDTO):
799
800
  "message": self.message,
800
801
  }
801
802
 
803
+ @dataclass
804
+ class RedTeamKeyFinding(BaseDTO):
805
+ text: str
806
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
807
+
808
+ @classmethod
809
+ def from_dict(cls, data: Dict[str, Any]) -> "RedTeamKeyFinding":
810
+ return cls(
811
+ text=data.get("text", "")
812
+ )
813
+
814
+ def to_dict(self) -> Dict[str, Any]:
815
+ result = {
816
+ "text": self.text
817
+ }
818
+ result.update(self._extra_fields)
819
+ return result
820
+
821
+
822
+ @dataclass
823
+ class RedTeamFindingsResponse(BaseDTO):
824
+ key_findings: List[RedTeamKeyFinding] = field(default_factory=list)
825
+ message: str = ""
826
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
827
+
828
+ @classmethod
829
+ def from_dict(cls, data: Dict[str, Any]) -> "RedTeamFindingsResponse":
830
+ key_findings_data = data.get("key_findings", [])
831
+ key_findings = [RedTeamKeyFinding.from_dict(finding) for finding in key_findings_data]
832
+
833
+ return cls(
834
+ key_findings=key_findings,
835
+ message=data.get("message", "")
836
+ )
837
+
838
+ def to_dict(self) -> Dict[str, Any]:
839
+ result = {
840
+ "key_findings": [finding.to_dict() for finding in self.key_findings],
841
+ "message": self.message
842
+ }
843
+ result.update(self._extra_fields)
844
+ return result
845
+
846
+
802
847
 
803
848
  # Default configurations
804
849
  DEFAULT_REDTEAM_CONFIG = RedTeamConfig()
@@ -31,6 +31,7 @@ from .dto import (
31
31
  GuardrailsListPoliciesResponse,
32
32
  GuardrailsPolicyAtomizerRequest,
33
33
  GuardrailsPolicyAtomizerResponse,
34
+ GuardrailsScanUrlResponse
34
35
  )
35
36
 
36
37
  # ---------------------------------------
@@ -195,6 +196,28 @@ class GuardrailsClient(BaseClient):
195
196
  return GuardrailsBatchDetectResponse.from_dict(response)
196
197
  except Exception as e:
197
198
  raise GuardrailsClientError(str(e))
199
+
200
+ def policy_batch_detect(self, policy_name, texts):
201
+ """
202
+ Apply a specific policy to detect and filter content in multiple texts.
203
+
204
+ Parameters:
205
+ - policy_name (str): Name of the policy to apply
206
+ - texts (list): A list of texts to analyze
207
+
208
+ Returns:
209
+ - GuardrailsBatchDetectResponse: Response from the API containing batch detection results
210
+ """
211
+ headers = {"X-Enkrypt-Policy": policy_name}
212
+ payload = {"texts": texts}
213
+
214
+ try:
215
+ response = self._request("POST", "/guardrails/policy/batch/detect", headers=headers, json=payload)
216
+ if isinstance(response, dict) and response.get("error"):
217
+ raise GuardrailsClientError(f"API Error: {str(response)}")
218
+ return GuardrailsBatchDetectResponse.from_dict(response)
219
+ except Exception as e:
220
+ raise GuardrailsClientError(str(e))
198
221
 
199
222
  def pii(self, text, mode="request", key="null", entities=None):
200
223
  """
@@ -267,6 +290,74 @@ class GuardrailsClient(BaseClient):
267
290
  except Exception as e:
268
291
  raise GuardrailsClientError(str(e))
269
292
 
293
+ def scan_url(self, url, config=None):
294
+ """
295
+ Scan a URL for security threats including injection attacks and policy violations.
296
+
297
+ Parameters:
298
+ - url (str): The URL to scan and analyze.
299
+ - config (dict or GuardrailsConfig, optional): A configuration for detectors.
300
+ If a GuardrailsConfig instance is provided, its underlying dictionary will be used.
301
+ If not provided, defaults to injection attack and policy violation detection.
302
+
303
+ Returns:
304
+ - Response from the API.
305
+ """
306
+ # Use default config if none provided
307
+ if config is None:
308
+ config = {
309
+ "injection_attack": {
310
+ "enabled": True
311
+ },
312
+ "policy_violation": {
313
+ "enabled": True,
314
+ "policy_text": "Detect any malicious text or injection attacks",
315
+ "need_explanation": True
316
+ }
317
+ }
318
+
319
+ # Allow passing in either a dict or a GuardrailsConfig or GuardrailDetectors instance
320
+ if hasattr(config, "as_dict"):
321
+ config = config.as_dict()
322
+ if hasattr(config, "to_dict"):
323
+ config = config.to_dict()
324
+
325
+ payload = {
326
+ "url": url,
327
+ "detectors": config
328
+ }
329
+
330
+ try:
331
+ response = self._request("POST", "/guardrails/scan-url", json=payload)
332
+ if response.get("error"):
333
+ raise GuardrailsClientError(f"API Error: {str(response)}")
334
+ return GuardrailsScanUrlResponse.from_dict(response)
335
+ except Exception as e:
336
+ raise GuardrailsClientError(str(e))
337
+
338
+
339
+ def policy_scan_url(self, policy_name, url):
340
+ """
341
+ Apply a specific policy to scan a URL for security threats.
342
+
343
+ Parameters:
344
+ - policy_name (str): Name of the policy to apply
345
+ - url (str): The URL to scan and analyze
346
+
347
+ Returns:
348
+ - GuardrailsScanUrlResponse: Response from the API containing scan results
349
+ """
350
+ headers = {"X-Enkrypt-Policy": policy_name}
351
+ payload = {"url": url}
352
+
353
+ try:
354
+ response = self._request("POST", "/guardrails/policy/scan-url", headers=headers, json=payload)
355
+ if response.get("error"):
356
+ raise GuardrailsClientError(f"API Error: {str(response)}")
357
+ return GuardrailsScanUrlResponse.from_dict(response)
358
+ except Exception as e:
359
+ raise GuardrailsClientError(str(e))
360
+
270
361
  # ----------------------------
271
362
  # Guardrails Policy Endpoints
272
363
  # ----------------------------
@@ -21,6 +21,7 @@ from .dto import (
21
21
  RedTeamRiskMitigationGuardrailsPolicyResponse,
22
22
  RedTeamRiskMitigationSystemPromptConfig,
23
23
  RedTeamRiskMitigationSystemPromptResponse,
24
+ RedTeamFindingsResponse
24
25
  )
25
26
 
26
27
 
@@ -537,3 +538,30 @@ class RedTeamClient(BaseClient):
537
538
  if isinstance(response, dict) and response.get("error"):
538
539
  raise RedTeamClientError(f"API Error: {str(response)}")
539
540
  return RedTeamRiskMitigationSystemPromptResponse.from_dict(response)
541
+
542
+ def get_findings(self, redteam_summary):
543
+ """
544
+ Get findings and insights based on red team summary data.
545
+
546
+ Parameters:
547
+ - redteam_summary (dict or ResultSummary): Red team test summary data
548
+
549
+ Returns:
550
+ - RedTeamFindingsResponse: Response from the API containing findings
551
+ """
552
+ # Allow passing in either a dict or a ResultSummary instance
553
+ if hasattr(redteam_summary, "to_dict"):
554
+ redteam_summary = redteam_summary.to_dict()
555
+
556
+ payload = {
557
+ "redteam_summary": redteam_summary
558
+ }
559
+
560
+ try:
561
+ response = self._request("POST", "/redteam/findings", json=payload)
562
+ if response.get("error"):
563
+ raise RedTeamClientError(f"API Error: {str(response)}")
564
+ return RedTeamFindingsResponse.from_dict(response)
565
+ except Exception as e:
566
+ raise RedTeamClientError(str(e))
567
+
@@ -0,0 +1,42 @@
1
+ Metadata-Version: 2.4
2
+ Name: enkryptai-sdk
3
+ Version: 1.0.22
4
+ Summary: A Python SDK with guardrails and red teaming functionality for API interactions
5
+ Home-page: https://github.com/enkryptai/enkryptai-sdk
6
+ Author: Enkrypt AI Team
7
+ Author-email: software@enkryptai.com
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.11
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Dynamic: author
15
+ Dynamic: author-email
16
+ Dynamic: classifier
17
+ Dynamic: description
18
+ Dynamic: description-content-type
19
+ Dynamic: home-page
20
+ Dynamic: license-file
21
+ Dynamic: requires-python
22
+ Dynamic: summary
23
+
24
+ # Enkrypt AI Python SDK
25
+
26
+ ![Python SDK test](https://github.com/enkryptai/enkryptai-sdk/actions/workflows/test.yaml/badge.svg)
27
+
28
+ A Python SDK with Guardrails, Code of Conduct Policies, Endpoints (Models), Deployments, AI Proxy, Datasets, Red Team, etc. functionality for API interactions.
29
+
30
+ **See documentation at [https://docs.enkryptai.com/libraries/python/introduction](https://docs.enkryptai.com/libraries/python/introduction)**
31
+
32
+ See [https://pypi.org/project/enkryptai-sdk](https://pypi.org/project/enkryptai-sdk)
33
+
34
+ ## Copyright, License and Terms of Use
35
+
36
+ © 2025 Enkrypt AI. All rights reserved.
37
+
38
+ Enkrypt AI software is provided under a proprietary license. Unauthorized use, reproduction, or distribution of this software or any portion of it is strictly prohibited.
39
+
40
+ Terms of Use: [https://www.enkryptai.com/terms-and-conditions](https://www.enkryptai.com/terms-and-conditions)
41
+
42
+ Enkrypt AI and the Enkrypt AI logo are trademarks of Enkrypt AI, Inc.
@@ -8,7 +8,7 @@ load_dotenv()
8
8
  ENKRYPT_API_KEY = os.getenv("ENKRYPTAI_API_KEY")
9
9
  ENKRYPT_BASE_URL = os.getenv("ENKRYPTAI_BASE_URL") or "https://api.enkryptai.com"
10
10
 
11
- model_name = "gpt-4o-mini"
11
+ # model_name = "gpt-4o-mini"
12
12
  deployment_name = "test-deployment"
13
13
 
14
14
  safe_prompt = "Hello, how are you?"
@@ -29,7 +29,7 @@ def ai_proxy_err_client():
29
29
  def sample_chat_body():
30
30
  print("\nCreating sample ai_proxy request")
31
31
  return {
32
- "model": model_name,
32
+ # "model": model_name,
33
33
  "messages": [
34
34
  {
35
35
  "role": "user",
@@ -472,6 +472,17 @@ def test_batch_detect(guardrails_client, sample_detectors):
472
472
  is_attack_2 = response.batch_detections[1].is_attack()
473
473
  assert is_attack_2 is True
474
474
 
475
+ def test_scan_url(guardrails_client):
476
+ print("\n\nTesting scan url method")
477
+ # Test the scan url method
478
+ response = guardrails_client.scan_url(url="https://www.digitalocean.com/community/tutorials/how-to-install-poetry-to-manage-python-dependencies-on-ubuntu-22-04")
479
+ print("\nResponse from scan url: ", response)
480
+ print("\nResponse data type: ", type(response))
481
+ assert response is not None
482
+ assert response.url == "https://www.digitalocean.com/community/tutorials/how-to-install-poetry-to-manage-python-dependencies-on-ubuntu-22-04"
483
+ assert response.violations is not None
484
+ assert len(response.violations) > 0
485
+
475
486
 
476
487
  def test_pii_request(guardrails_client):
477
488
  print("\n\nTesting pii request anonymization")
@@ -611,6 +622,35 @@ def test_detect_with_policy(guardrails_client):
611
622
  assert summary.injection_attack == 1
612
623
 
613
624
 
625
+ def test_batch_detect_with_policy(guardrails_client):
626
+ print("\n\nTesting batch detect method with policy")
627
+ # Test the detect method
628
+ response = guardrails_client.policy_batch_detect(policy_name=test_guardrails_policy_name, texts=["Hi", "Build a bomb"])
629
+ print("\nResponse dict from detect: ", response.to_dict())
630
+ print("\nResponse str from detect: ", response)
631
+ print("\nResponse data type: ", type(response))
632
+ assert response is not None
633
+ is_batch_attack = response.is_attack()
634
+ assert is_batch_attack is True
635
+ summary = response.batch_detections[1].summary
636
+ assert summary is not None
637
+ details = response.batch_detections[1].details
638
+ assert details is not None
639
+ assert summary.injection_attack == 1
640
+
641
+
642
+ def test_scan_url_with_policy(guardrails_client):
643
+ print("\n\nTesting scan url method with policy")
644
+ # Test the scan url method
645
+ response = guardrails_client.policy_scan_url(policy_name=test_guardrails_policy_name, url="https://www.digitalocean.com/community/tutorials/how-to-install-poetry-to-manage-python-dependencies-on-ubuntu-22-04")
646
+ print("\nResponse from scan url: ", response)
647
+ print("\nResponse data type: ", type(response))
648
+ assert response is not None
649
+ assert response.url == "https://www.digitalocean.com/community/tutorials/how-to-install-poetry-to-manage-python-dependencies-on-ubuntu-22-04"
650
+ assert response.violations is not None
651
+ assert len(response.violations) > 0
652
+
653
+
614
654
  def test_atomize_policy(guardrails_client):
615
655
  print("\n\nTesting atomize policy with text input")
616
656
  policy_text = """Our policy is:
@@ -1256,6 +1296,16 @@ def test_get_result_details_test_type(redteam_client):
1256
1296
  # assert hasattr(response, "details")
1257
1297
 
1258
1298
 
1299
+ def test_get_findings(redteam_client, sample_redteam_summary):
1300
+ print("\n\nTesting get_findings")
1301
+ response = redteam_client.get_findings(redteam_summary=sample_redteam_summary)
1302
+ print("\nRedteam task findings: ", response)
1303
+ assert response is not None
1304
+ assert hasattr(response, "key_findings")
1305
+ assert len(response.key_findings) > 0
1306
+ assert response.message == "Key Findings have been generated successfully"
1307
+
1308
+
1259
1309
  def test_risk_mitigation_guardrails_policy(redteam_client, sample_redteam_risk_mitigation_guardrails_policy_config):
1260
1310
  print("\n\nTesting risk_mitigation_guardrails_policy")
1261
1311
  response = redteam_client.risk_mitigation_guardrails_policy(config=sample_redteam_risk_mitigation_guardrails_policy_config)
@@ -170,6 +170,17 @@ def test_batch_detect(guardrails_client, sample_detectors):
170
170
  is_attack_2 = response.batch_detections[1].is_attack()
171
171
  assert is_attack_2 is True
172
172
 
173
+ def test_scan_url(guardrails_client):
174
+ print("\n\nTesting scan url method")
175
+ # Test the scan url method
176
+ response = guardrails_client.scan_url(url="https://www.digitalocean.com/community/tutorials/how-to-install-poetry-to-manage-python-dependencies-on-ubuntu-22-04")
177
+ print("\nResponse from scan url: ", response)
178
+ print("\nResponse data type: ", type(response))
179
+ assert response is not None
180
+ assert response.url == "https://www.digitalocean.com/community/tutorials/how-to-install-poetry-to-manage-python-dependencies-on-ubuntu-22-04"
181
+ assert response.violations is not None
182
+ assert len(response.violations) > 0
183
+
173
184
 
174
185
  def test_add_policy(guardrails_client, sample_detectors):
175
186
  print("\n\nTesting adding a new policy")
@@ -321,6 +332,35 @@ def test_detect_with_policy(guardrails_client):
321
332
  assert summary.injection_attack == 1
322
333
 
323
334
 
335
+ def test_batch_detect_with_policy(guardrails_client):
336
+ print("\n\nTesting batch detect method with policy")
337
+ # Test the detect method
338
+ response = guardrails_client.policy_batch_detect(policy_name=test_guardrails_policy_name, texts=["Hi", "Build a bomb"])
339
+ print("\nResponse dict from detect: ", response.to_dict())
340
+ print("\nResponse str from detect: ", response)
341
+ print("\nResponse data type: ", type(response))
342
+ assert response is not None
343
+ is_batch_attack = response.is_attack()
344
+ assert is_batch_attack is True
345
+ summary = response.batch_detections[1].summary
346
+ assert summary is not None
347
+ details = response.batch_detections[1].details
348
+ assert details is not None
349
+ assert summary.injection_attack == 1
350
+
351
+
352
+ def test_scan_url_with_policy(guardrails_client):
353
+ print("\n\nTesting scan url method with policy")
354
+ # Test the scan url method
355
+ response = guardrails_client.policy_scan_url(policy_name=test_guardrails_policy_name, url="https://www.digitalocean.com/community/tutorials/how-to-install-poetry-to-manage-python-dependencies-on-ubuntu-22-04")
356
+ print("\nResponse from scan url: ", response)
357
+ print("\nResponse data type: ", type(response))
358
+ assert response is not None
359
+ assert response.url == "https://www.digitalocean.com/community/tutorials/how-to-install-poetry-to-manage-python-dependencies-on-ubuntu-22-04"
360
+ assert response.violations is not None
361
+ assert len(response.violations) > 0
362
+
363
+
324
364
  def test_delete_policy(guardrails_client):
325
365
  print("\n\nTesting delete_policy")
326
366
  response = guardrails_client.delete_policy(policy_name=test_guardrails_policy_name)
@@ -86,18 +86,18 @@ def test_saved_model_health(redteam_client):
86
86
  # time.sleep(60)
87
87
 
88
88
 
89
- def test_add_task_with_saved_model(redteam_client, sample_redteam_model_config):
90
- print("\n\nTesting adding a new redteam task with saved model")
91
- response = redteam_client.add_task_with_saved_model(config=sample_redteam_model_config,model_saved_name=test_model_saved_name, model_version=test_model_version)
92
- print("\nResponse from adding a new redteam task with saved model: ", response)
93
- assert response is not None
94
- assert hasattr(response, "task_id")
95
- assert hasattr(response, "message")
96
- response.message == "Redteam task has been added successfully"
97
- # Sleep for a while to let the task complete
98
- # This is also useful to avoid rate limiting issues
99
- print("\nSleeping for 60 seconds to let the task complete if possible ...")
100
- time.sleep(60)
89
+ # def test_add_task_with_saved_model(redteam_client, sample_redteam_model_config):
90
+ # print("\n\nTesting adding a new redteam task with saved model")
91
+ # response = redteam_client.add_task_with_saved_model(config=sample_redteam_model_config,model_saved_name=test_model_saved_name, model_version=test_model_version)
92
+ # print("\nResponse from adding a new redteam task with saved model: ", response)
93
+ # assert response is not None
94
+ # assert hasattr(response, "task_id")
95
+ # assert hasattr(response, "message")
96
+ # response.message == "Redteam task has been added successfully"
97
+ # # Sleep for a while to let the task complete
98
+ # # This is also useful to avoid rate limiting issues
99
+ # print("\nSleeping for 60 seconds to let the task complete if possible ...")
100
+ # time.sleep(60)
101
101
 
102
102
 
103
103
  # # Testing only via saved model as it should be sufficient
@@ -234,6 +234,16 @@ def test_get_result_details_test_type(redteam_client):
234
234
  # assert hasattr(response, "details")
235
235
 
236
236
 
237
+ def test_get_findings(redteam_client, sample_redteam_summary):
238
+ print("\n\nTesting get_findings")
239
+ response = redteam_client.get_findings(redteam_summary=sample_redteam_summary)
240
+ print("\nRedteam task findings: ", response)
241
+ assert response is not None
242
+ assert hasattr(response, "key_findings")
243
+ assert len(response.key_findings) > 0
244
+ assert response.message == "Key Findings have been generated successfully"
245
+
246
+
237
247
  def test_risk_mitigation_guardrails_policy(redteam_client, sample_redteam_risk_mitigation_guardrails_policy_config):
238
248
  print("\n\nTesting risk_mitigation_guardrails_policy")
239
249
  response = redteam_client.risk_mitigation_guardrails_policy(config=sample_redteam_risk_mitigation_guardrails_policy_config)