hiddenlayer-sdk 3.7.0__tar.gz → 3.8.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.
Files changed (173) hide show
  1. hiddenlayer_sdk-3.8.0/.release-please-manifest.json +3 -0
  2. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/CHANGELOG.md +38 -0
  3. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/PKG-INFO +1 -1
  4. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/api.md +7 -2
  5. hiddenlayer_sdk-3.8.0/examples/red_team/README.md +68 -0
  6. hiddenlayer_sdk-3.8.0/examples/red_team/red_team_http_api.ipynb +245 -0
  7. hiddenlayer_sdk-3.8.0/examples/red_team/red_team_openai.ipynb +241 -0
  8. hiddenlayer_sdk-3.8.0/examples/red_team/red_team_playwright.ipynb +270 -0
  9. hiddenlayer_sdk-3.8.0/examples/red_team/red_team_static_prompts.ipynb +249 -0
  10. hiddenlayer_sdk-3.8.0/examples/red_team/red_team_template.ipynb +215 -0
  11. hiddenlayer_sdk-3.8.0/examples/red_team/red_team_webhook.ipynb +331 -0
  12. hiddenlayer_sdk-3.8.0/examples/red_team/red_team_websocket.ipynb +323 -0
  13. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/pyproject.toml +2 -1
  14. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_files.py +1 -1
  15. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_models.py +80 -0
  16. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_version.py +1 -1
  17. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/lib/_beta_endpoints.py +1 -1
  18. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/lib/red_team_session.py +63 -121
  19. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/evaluations/red_team.py +87 -22
  20. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/runtime.py +174 -1
  21. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/__init__.py +4 -0
  22. hiddenlayer_sdk-3.8.0/src/hiddenlayer/types/evaluations/red_team_create_params.py +99 -0
  23. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/prompt_analyzer_create_response.py +7 -4
  24. hiddenlayer_sdk-3.8.0/src/hiddenlayer/types/runtime_evaluate_interaction_params.py +195 -0
  25. hiddenlayer_sdk-3.8.0/src/hiddenlayer/types/runtime_evaluate_interaction_response.py +481 -0
  26. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/job_list_response.py +9 -0
  27. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/job_request_params.py +3 -0
  28. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/scan_job.py +3 -0
  29. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/scan_report.py +34 -0
  30. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/evaluations/test_red_team.py +16 -16
  31. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/scans/test_jobs.py +2 -0
  32. hiddenlayer_sdk-3.8.0/tests/api_resources/test_runtime.py +615 -0
  33. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_models.py +57 -3
  34. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_red_team_session.py +143 -28
  35. hiddenlayer_sdk-3.8.0/uv.lock +1603 -0
  36. hiddenlayer_sdk-3.7.0/.release-please-manifest.json +0 -3
  37. hiddenlayer_sdk-3.7.0/src/hiddenlayer/types/evaluations/red_team_create_params.py +0 -59
  38. hiddenlayer_sdk-3.7.0/tests/api_resources/test_runtime.py +0 -299
  39. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/.gitignore +0 -0
  40. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/CODE_OF_CONDUCT.md +0 -0
  41. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/CONTRIBUTING.md +0 -0
  42. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/LICENSE +0 -0
  43. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/README.md +0 -0
  44. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/SECURITY.md +0 -0
  45. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/bin/check-release-environment +0 -0
  46. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/bin/publish-jfrog +0 -0
  47. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/bin/publish-pypi +0 -0
  48. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/examples/.keep +0 -0
  49. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/examples/demo.py +0 -0
  50. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/noxfile.py +0 -0
  51. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/release-please-config.json +0 -0
  52. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/requirements-dev.lock +0 -0
  53. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/requirements.lock +0 -0
  54. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/__init__.py +0 -0
  55. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_base_client.py +0 -0
  56. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_client.py +0 -0
  57. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_compat.py +0 -0
  58. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_constants.py +0 -0
  59. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_exceptions.py +0 -0
  60. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_oauth2.py +0 -0
  61. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_qs.py +0 -0
  62. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_resource.py +0 -0
  63. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_response.py +0 -0
  64. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_streaming.py +0 -0
  65. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_types.py +0 -0
  66. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/__init__.py +0 -0
  67. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/_compat.py +0 -0
  68. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/_datetime_parse.py +0 -0
  69. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/_json.py +0 -0
  70. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/_logs.py +0 -0
  71. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/_path.py +0 -0
  72. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/_proxy.py +0 -0
  73. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/_reflection.py +0 -0
  74. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/_resources_proxy.py +0 -0
  75. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/_streams.py +0 -0
  76. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/_sync.py +0 -0
  77. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/_transform.py +0 -0
  78. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/_typing.py +0 -0
  79. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/_utils.py +0 -0
  80. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/lib/.keep +0 -0
  81. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/lib/__init__.py +0 -0
  82. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/lib/_beta.py +0 -0
  83. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/lib/community_scan.py +0 -0
  84. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/lib/evaluation_sessions.py +0 -0
  85. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/lib/model_scan.py +0 -0
  86. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/lib/red_team_exceptions.py +0 -0
  87. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/lib/scan_utils.py +0 -0
  88. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/pagination.py +0 -0
  89. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/py.typed +0 -0
  90. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/__init__.py +0 -0
  91. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/evaluations/__init__.py +0 -0
  92. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/evaluations/evaluations.py +0 -0
  93. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/interactions.py +0 -0
  94. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/models/__init__.py +0 -0
  95. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/models/cards.py +0 -0
  96. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/models/models.py +0 -0
  97. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/prompt_analyzer.py +0 -0
  98. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/scans/__init__.py +0 -0
  99. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/scans/jobs.py +0 -0
  100. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/scans/results.py +0 -0
  101. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/scans/scans.py +0 -0
  102. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/scans/upload/__init__.py +0 -0
  103. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/scans/upload/file.py +0 -0
  104. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/scans/upload/upload.py +0 -0
  105. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/sensors.py +0 -0
  106. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/evaluations/__init__.py +0 -0
  107. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/evaluations/red_team_create_response.py +0 -0
  108. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/evaluations/red_team_retrieve_evaluation_results_response.py +0 -0
  109. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/evaluations/red_team_retrieve_next_action_response.py +0 -0
  110. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/evaluations/red_team_retrieve_status_response.py +0 -0
  111. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/evaluations/red_team_submit_target_response_params.py +0 -0
  112. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/evaluations/red_team_submit_target_response_response.py +0 -0
  113. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/interaction_analyze_params.py +0 -0
  114. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/interaction_analyze_response.py +0 -0
  115. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/model_retrieve_response.py +0 -0
  116. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/models/__init__.py +0 -0
  117. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/models/card_list_params.py +0 -0
  118. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/models/card_list_response.py +0 -0
  119. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/prompt_analyzer_create_params.py +0 -0
  120. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/runtime_evaluate_request_params.py +0 -0
  121. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/runtime_evaluate_request_response.py +0 -0
  122. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/runtime_evaluate_response_params.py +0 -0
  123. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/runtime_evaluate_response_response.py +0 -0
  124. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/__init__.py +0 -0
  125. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/job_list_params.py +0 -0
  126. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/job_retrieve_params.py +0 -0
  127. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/result_sarif_response.py +0 -0
  128. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/upload/__init__.py +0 -0
  129. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/upload/file_add_response.py +0 -0
  130. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/upload/file_complete_response.py +0 -0
  131. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/upload_complete_all_response.py +0 -0
  132. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/upload_start_params.py +0 -0
  133. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/upload_start_response.py +0 -0
  134. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/sensor_create_params.py +0 -0
  135. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/sensor_create_response.py +0 -0
  136. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/sensor_query_params.py +0 -0
  137. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/sensor_query_response.py +0 -0
  138. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/sensor_retrieve_response.py +0 -0
  139. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/sensor_update_params.py +0 -0
  140. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/sensor_update_response.py +0 -0
  141. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/__init__.py +0 -0
  142. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/__init__.py +0 -0
  143. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/evaluations/__init__.py +0 -0
  144. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/models/__init__.py +0 -0
  145. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/models/test_cards.py +0 -0
  146. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/scans/__init__.py +0 -0
  147. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/scans/test_results.py +0 -0
  148. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/scans/test_upload.py +0 -0
  149. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/scans/upload/__init__.py +0 -0
  150. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/scans/upload/test_file.py +0 -0
  151. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/test_interactions.py +0 -0
  152. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/test_models.py +0 -0
  153. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/test_prompt_analyzer.py +0 -0
  154. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/test_sensors.py +0 -0
  155. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/conftest.py +0 -0
  156. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/sample_file.txt +0 -0
  157. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_beta.py +0 -0
  158. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_client.py +0 -0
  159. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_community_scan.py +0 -0
  160. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_extract_files.py +0 -0
  161. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_files.py +0 -0
  162. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_model_scan.py +0 -0
  163. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_qs.py +0 -0
  164. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_required_args.py +0 -0
  165. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_response.py +0 -0
  166. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_streaming.py +0 -0
  167. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_transform.py +0 -0
  168. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_utils/test_datetime_parse.py +0 -0
  169. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_utils/test_json.py +0 -0
  170. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_utils/test_path.py +0 -0
  171. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_utils/test_proxy.py +0 -0
  172. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_utils/test_typing.py +0 -0
  173. {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/utils.py +0 -0
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "3.8.0"
3
+ }
@@ -1,5 +1,43 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.8.0 (2026-06-24)
4
+
5
+ Full Changelog: [v3.7.1...v3.8.0](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/compare/v3.7.1...v3.8.0)
6
+
7
+ ### Features
8
+
9
+ * **api:** api update ([4fd0d62](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/4fd0d62737e1273a0558bf66017fa054e39d1f87))
10
+ * **api:** api update ([c53a283](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/c53a2836f987b7dac46aa1c5677a945f45d21c2a))
11
+ * **api:** api update ([67dccee](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/67dcceea5e111f16a30688efb33bc0e0f06ca12c))
12
+ * **api:** api update ([8f00ab1](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/8f00ab1201dcda0488ca47abcf4cd4a2d4718da7))
13
+ * **api:** api update ([e612915](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/e6129151ba357559bb291bfe0dc6a3d3e81f3dff))
14
+ * **red-team:** forward all start_session params and drop hardcoded defaults ([#206](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/issues/206)) ([45ee409](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/45ee40985d82db175e48140c2a82b9713ea8a83c))
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * **client:** add missing f-string prefix in file type error message ([3405322](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/3405322c1f1b379b50d464842607bdfa8c3c080f))
20
+
21
+
22
+ ### Chores
23
+
24
+ * **internal:** codegen related update ([bb8153f](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/bb8153fc39bdb5dfc962908caad4e3eaeb9fd249))
25
+ * regenerate beta endpoint registry [skip ci] ([89009da](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/89009dab82686744fb693a7e47de13c01ac9909e))
26
+ * regenerate beta endpoint registry [skip ci] ([c08dc03](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/c08dc0341664260b09dc40e021e5c4fba0a00cf7))
27
+
28
+
29
+ ### Documentation
30
+
31
+ * **examples:** add red team evaluation notebooks ([#205](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/issues/205)) ([5a1229b](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/5a1229b5cf3930e3a0b1665d97fdb4ea134b83da))
32
+
33
+ ## 3.7.1 (2026-05-14)
34
+
35
+ Full Changelog: [v3.7.0...v3.7.1](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/compare/v3.7.0...v3.7.1)
36
+
37
+ ### Bug Fixes
38
+
39
+ * **red_team_session:** fix red team sessions failing with "invalid UUID length: 0" when prompt_set_id is not provided ([#198](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/issues/198)) ([5e3c85e](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/5e3c85e57482ffeda2011b8f7c65a67efe0a084d))
40
+
3
41
  ## 3.7.0 (2026-05-07)
4
42
 
5
43
  Full Changelog: [v3.6.0...v3.7.0](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/compare/v3.6.0...v3.7.0)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: hiddenlayer-sdk
3
- Version: 3.7.0
3
+ Version: 3.8.0
4
4
  Summary: The official Python library for the hiddenlayer API
5
5
  Project-URL: Homepage, https://github.com/hiddenlayerai/hiddenlayer-sdk-python
6
6
  Project-URL: Repository, https://github.com/hiddenlayerai/hiddenlayer-sdk-python
@@ -79,11 +79,16 @@ Methods:
79
79
  Types:
80
80
 
81
81
  ```python
82
- from hiddenlayer.types import RuntimeEvaluateRequestResponse, RuntimeEvaluateResponseResponse
82
+ from hiddenlayer.types import (
83
+ RuntimeEvaluateInteractionResponse,
84
+ RuntimeEvaluateRequestResponse,
85
+ RuntimeEvaluateResponseResponse,
86
+ )
83
87
  ```
84
88
 
85
89
  Methods:
86
90
 
91
+ - <code title="post /detection/v2/interaction-evaluations">client.runtime.<a href="./src/hiddenlayer/resources/runtime.py">evaluate_interaction</a>(\*\*<a href="src/hiddenlayer/types/runtime_evaluate_interaction_params.py">params</a>) -> <a href="./src/hiddenlayer/types/runtime_evaluate_interaction_response.py">RuntimeEvaluateInteractionResponse</a></code>
87
92
  - <code title="post /detection/v2/request-evaluations">client.runtime.<a href="./src/hiddenlayer/resources/runtime.py">evaluate_request</a>(\*\*<a href="src/hiddenlayer/types/runtime_evaluate_request_params.py">params</a>) -> <a href="./src/hiddenlayer/types/runtime_evaluate_request_response.py">RuntimeEvaluateRequestResponse</a></code>
88
93
  - <code title="post /detection/v2/response-evaluations">client.runtime.<a href="./src/hiddenlayer/resources/runtime.py">evaluate_response</a>(\*\*<a href="src/hiddenlayer/types/runtime_evaluate_response_params.py">params</a>) -> <a href="./src/hiddenlayer/types/runtime_evaluate_response_response.py">RuntimeEvaluateResponseResponse</a></code>
89
94
 
@@ -236,7 +241,7 @@ Accessed via `client.evaluation_sessions.red_team`.
236
241
 
237
242
  Methods:
238
243
 
239
- - **start_session(name, target_model, target_system_prompt="", max_turns=3, execution_strategy_type="random", attacker_max_generation_attempts=2, n_random_techniques=1, max_parallel_techniques=1, prompt_set_id="", hiddenlayer_project_id=None, poll_interval=2.0, poll_max_wait=None, sessions_per_technique=1) -> RedTeamSession**
244
+ - **start_session(name, target_model, target_system_prompt="", objective_ids=omit, refusal_judge_model=omit, objective_judge_model=omit, attacker_model=omit, evaluation_report_model=omit, attacker_guidance=omit, severity_mapping=omit, config_id=omit, max_turns=3, execution_strategy_type="random", attacker_max_generation_attempts=2, n_random_techniques=1, max_parallel_techniques=1, prompt_set_id=omit, hiddenlayer_project_id=None, poll_interval=2.0, poll_max_wait=None, sessions_per_technique=1) -> RedTeamSession**
240
245
  Start a new red team session. Returns a `RedTeamSession` (sync) or `AsyncRedTeamSession` (async).
241
246
  Uses adaptive multi-objective evaluation: each session runs to `max_turns` (no short-circuit),
242
247
  tests all objectives, and maintains cross-session state for adaptive attacks.
@@ -0,0 +1,68 @@
1
+ # Red Team Integrations
2
+
3
+ Example notebooks for driving HiddenLayer red team evaluations against different
4
+ kinds of targets using the [HiddenLayer Python SDK](https://github.com/hiddenlayerai/hiddenlayer-sdk-python).
5
+
6
+ Every notebook follows the same pattern:
7
+
8
+ 1. Configure the target and the evaluation parameters.
9
+ 2. Implement an async `handler(prompt, history, session_id, target_system_prompt)`
10
+ that calls your target and returns its reply as a string.
11
+ 3. Start a session with `client.evaluation_sessions.red_team.start_session(...)`
12
+ and drive it with `session.run_with_callback_parallel(handler=handler)`.
13
+ 4. Retrieve the report with `client.evaluations.red_team.retrieve_evaluation_results(...)`.
14
+
15
+ The `handler` is the only integration point — swap it to point at any target.
16
+
17
+ `red_team_openai.ipynb` additionally shows how to **resume** an existing
18
+ workflow (`resume_session` + `retrieve_status`), and `red_team_http_api.ipynb`
19
+ shows scoping a run to a project via `hiddenlayer_project_id`.
20
+
21
+ ## Notebooks
22
+
23
+ | Notebook | Target |
24
+ |----------|--------|
25
+ | [`red_team_openai.ipynb`](./red_team_openai.ipynb) | An OpenAI Chat Completions model |
26
+ | [`red_team_http_api.ipynb`](./red_team_http_api.ipynb) | A custom LLM app/agent behind an HTTP/REST endpoint |
27
+ | [`red_team_playwright.ipynb`](./red_team_playwright.ipynb) | A web chat UI driven via Playwright browser automation |
28
+ | [`red_team_static_prompts.ipynb`](./red_team_static_prompts.ipynb) | A target tested with a pre-written static prompt set |
29
+ | [`red_team_webhook.ipynb`](./red_team_webhook.ipynb) | A target that replies asynchronously via webhook callback (includes a self-contained mock target) |
30
+ | [`red_team_websocket.ipynb`](./red_team_websocket.ipynb) | A target reached over a persistent WebSocket connection (includes a self-contained mock target) |
31
+ | [`red_team_template.ipynb`](./red_team_template.ipynb) | Generic skeleton — drop in any target |
32
+
33
+ ## Setup
34
+
35
+ ```bash
36
+ pip install hiddenlayer-sdk jupyter
37
+
38
+ # Per-notebook extras:
39
+ pip install openai # red_team_openai.ipynb
40
+ pip install aiohttp # red_team_webhook.ipynb, red_team_websocket.ipynb
41
+ pip install playwright # red_team_playwright.ipynb
42
+ playwright install chromium
43
+ ```
44
+
45
+ `red_team_webhook.ipynb` targets a service that replies **asynchronously** via a
46
+ webhook callback. It runs a small in-notebook receiver and ships with a
47
+ self-contained mock target so it works out of the box; for a real external
48
+ target, expose the receiver with a tunnel (e.g. ngrok / cloudflared) and set
49
+ `PUBLIC_CALLBACK_URL` accordingly.
50
+
51
+ Provide credentials via environment variables (read automatically by the SDK):
52
+
53
+ - `HIDDENLAYER_CLIENT_ID` and `HIDDENLAYER_CLIENT_SECRET` (OAuth2), **or**
54
+ - `HIDDENLAYER_TOKEN` (Bearer token)
55
+ - `OPENAI_API_KEY` for `red_team_openai.ipynb`
56
+
57
+ By default the client targets US production (`prod-us`). For EU production pass
58
+ `environment="prod-eu"`, and for a self-hosted deployment pass
59
+ `base_url="http://your-host:port"` to `AsyncHiddenLayer()`.
60
+
61
+ ## Run
62
+
63
+ ```bash
64
+ jupyter lab examples/red_team/red_team_openai.ipynb
65
+ ```
66
+
67
+ Run the cells top to bottom. Results are viewable in the
68
+ [HiddenLayer Console](https://console.hiddenlayer.ai/).
@@ -0,0 +1,245 @@
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {},
6
+ "source": [
7
+ "# HiddenLayer Red Team Evaluation - HTTP/REST API Target\n",
8
+ "\n",
9
+ "Evaluate a custom target (LLM app or agent) that is exposed behind an HTTP endpoint. Adapt `to_target_request` / `from_target_response` to match your target's request and response schema.\n",
10
+ "\n",
11
+ "**Prerequisites:**\n",
12
+ "- `pip install hiddenlayer-sdk`\n",
13
+ "- Credentials read from the environment:\n",
14
+ " - `HIDDENLAYER_CLIENT_ID` and `HIDDENLAYER_CLIENT_SECRET` (OAuth2), or `HIDDENLAYER_TOKEN` (Bearer token)\n",
15
+ "\n",
16
+ "**SDK Reference:** [hiddenlayer-sdk-python](https://github.com/hiddenlayerai/hiddenlayer-sdk-python)"
17
+ ]
18
+ },
19
+ {
20
+ "cell_type": "markdown",
21
+ "metadata": {},
22
+ "source": [
23
+ "## Setup"
24
+ ]
25
+ },
26
+ {
27
+ "cell_type": "code",
28
+ "metadata": {},
29
+ "source": [
30
+ "import httpx\n",
31
+ "\n",
32
+ "from hiddenlayer import AsyncHiddenLayer\n",
33
+ "\n",
34
+ "# AsyncHiddenLayer() reads credentials from the environment.\n",
35
+ "# For EU prod pass environment=\"prod-eu\"; for self-hosted pass base_url=\"http://your-host:port\".\n",
36
+ "client = AsyncHiddenLayer()"
37
+ ],
38
+ "execution_count": null,
39
+ "outputs": []
40
+ },
41
+ {
42
+ "cell_type": "markdown",
43
+ "metadata": {},
44
+ "source": [
45
+ "## Configurables\n",
46
+ "\n",
47
+ "1. Configure target\n",
48
+ "2. Configure evaluation"
49
+ ]
50
+ },
51
+ {
52
+ "cell_type": "code",
53
+ "metadata": {},
54
+ "source": [
55
+ "# Target configuration\n",
56
+ "TARGET_URL = \"https://api.example.com/v1/chat\"\n",
57
+ "TARGET_MODEL_NAME = \"gpt-4o-mini\"\n",
58
+ "TARGET_SYSTEM_PROMPT = \"You are a helpful AI assistant.\"\n",
59
+ "CUSTOM_HEADERS = {\n",
60
+ " # \"Authorization\": \"Bearer your-api-key\",\n",
61
+ "}\n",
62
+ "\n",
63
+ "# Evaluation configuration\n",
64
+ "EVAL_NAME = \"API Red Team Eval\" # Name of the evaluation\n",
65
+ "EXECUTION_STRATEGY = \"single\" # Options: \"single\", \"random\", \"static_prompt_set\"\n",
66
+ "MAX_TURNS = 5 # Options: 1-5\n",
67
+ "SESSIONS_PER_TECHNIQUE = 2 # Options: 1-5\n",
68
+ "PARALLEL_TECHNIQUES = 10 # Options: 1-10\n",
69
+ "HIDDENLAYER_PROJECT_ID = None # Options: None, \"<project_id_or_alias>\""
70
+ ],
71
+ "execution_count": null,
72
+ "outputs": []
73
+ },
74
+ {
75
+ "cell_type": "markdown",
76
+ "metadata": {},
77
+ "source": [
78
+ "## Verify payload adapters\n",
79
+ "\n",
80
+ "- `to_target_request` needs to align with the target's request payload schema\n",
81
+ "- `from_target_response` needs to extract the reply text from the target's response payload schema"
82
+ ]
83
+ },
84
+ {
85
+ "cell_type": "code",
86
+ "metadata": {},
87
+ "source": [
88
+ "def to_target_request(prompt, history, session_id):\n",
89
+ " \"\"\"Format the attack payload to match the target's request schema.\"\"\"\n",
90
+ " messages = [{\"role\": msg[\"role\"], \"content\": msg[\"content\"]} for msg in history]\n",
91
+ " messages.append({\"role\": \"user\", \"content\": prompt})\n",
92
+ " return {\"model\": TARGET_MODEL_NAME, \"messages\": messages}\n",
93
+ "\n",
94
+ "\n",
95
+ "def from_target_response(api_response):\n",
96
+ " \"\"\"Extract the response text from the target's response schema.\"\"\"\n",
97
+ " if \"choices\" in api_response:\n",
98
+ " return api_response[\"choices\"][0][\"message\"][\"content\"]\n",
99
+ " return api_response.get(\"response\", str(api_response))"
100
+ ],
101
+ "execution_count": null,
102
+ "outputs": []
103
+ },
104
+ {
105
+ "cell_type": "markdown",
106
+ "metadata": {},
107
+ "source": [
108
+ "## Create Handler\n",
109
+ "\n",
110
+ "The handler acts as a proxy between the attacker and the target: it receives an attack prompt from HiddenLayer, calls the target, and returns the target's reply."
111
+ ]
112
+ },
113
+ {
114
+ "cell_type": "code",
115
+ "metadata": {},
116
+ "source": [
117
+ "async def handler(prompt, history, session_id, target_system_prompt):\n",
118
+ " \"\"\"Handler acts as proxy between attacker and target.\"\"\"\n",
119
+ " payload = to_target_request(prompt, history, session_id)\n",
120
+ " headers = {\"Content-Type\": \"application/json\", **CUSTOM_HEADERS}\n",
121
+ "\n",
122
+ " async with httpx.AsyncClient(timeout=None) as http_client:\n",
123
+ " response = await http_client.post(TARGET_URL, json=payload, headers=headers)\n",
124
+ " response.raise_for_status()\n",
125
+ " return from_target_response(response.json())"
126
+ ],
127
+ "execution_count": null,
128
+ "outputs": []
129
+ },
130
+ {
131
+ "cell_type": "markdown",
132
+ "metadata": {},
133
+ "source": [
134
+ "## Run the Evaluation\n",
135
+ "\n",
136
+ "Open a red team session and run attack techniques in parallel against the target."
137
+ ]
138
+ },
139
+ {
140
+ "cell_type": "code",
141
+ "metadata": {},
142
+ "source": [
143
+ "session = await client.evaluation_sessions.red_team.start_session(\n",
144
+ " name=EVAL_NAME,\n",
145
+ " target_model=TARGET_MODEL_NAME,\n",
146
+ " target_system_prompt=TARGET_SYSTEM_PROMPT,\n",
147
+ " execution_strategy_type=EXECUTION_STRATEGY,\n",
148
+ " max_turns=MAX_TURNS,\n",
149
+ " sessions_per_technique=SESSIONS_PER_TECHNIQUE,\n",
150
+ " max_parallel_techniques=PARALLEL_TECHNIQUES,\n",
151
+ " hiddenlayer_project_id=HIDDENLAYER_PROJECT_ID,\n",
152
+ ")\n",
153
+ "\n",
154
+ "print(f\"Session started: {session.workflow_id}\")\n",
155
+ "\n",
156
+ "await session.run_with_callback_parallel(handler=handler)\n",
157
+ "\n",
158
+ "print(\"Evaluation complete. View results: https://console.hiddenlayer.ai/\")"
159
+ ],
160
+ "execution_count": null,
161
+ "outputs": []
162
+ },
163
+ {
164
+ "cell_type": "markdown",
165
+ "metadata": {},
166
+ "source": [
167
+ "## Resume a Session\n",
168
+ "\n",
169
+ "Reconnect to a previously started workflow by its `workflow_id` — useful after an interruption or to monitor a long-running evaluation from another process. `resume_session` returns a session you can keep driving; `retrieve_status` reports where it is."
170
+ ]
171
+ },
172
+ {
173
+ "cell_type": "code",
174
+ "metadata": {},
175
+ "source": [
176
+ "async def resume(workflow_id):\n",
177
+ " \"\"\"Reconnect to an existing workflow, finish it if still running, and return results.\"\"\"\n",
178
+ " session = await client.evaluation_sessions.red_team.resume_session(workflow_id=workflow_id)\n",
179
+ " status = await client.evaluations.red_team.retrieve_status(workflow_id)\n",
180
+ " print(f\"Resumed {session.workflow_id} - status: {status.status}\")\n",
181
+ "\n",
182
+ " if status.status == \"RUNNING\":\n",
183
+ " await session.run_with_callback_parallel(handler=handler)\n",
184
+ "\n",
185
+ " return await client.evaluations.red_team.retrieve_evaluation_results(workflow_id)\n",
186
+ "\n",
187
+ "\n",
188
+ "# results = await resume(\"<workflow_id>\")"
189
+ ],
190
+ "execution_count": null,
191
+ "outputs": []
192
+ },
193
+ {
194
+ "cell_type": "markdown",
195
+ "metadata": {},
196
+ "source": [
197
+ "## Retrieve Results\n",
198
+ "\n",
199
+ "Fetch and summarize the evaluation report for the completed session."
200
+ ]
201
+ },
202
+ {
203
+ "cell_type": "code",
204
+ "metadata": {},
205
+ "source": [
206
+ "results = await client.evaluations.red_team.retrieve_evaluation_results(\n",
207
+ " session.workflow_id\n",
208
+ ")\n",
209
+ "\n",
210
+ "report = results.result.report\n",
211
+ "summary = report[\"summary\"]\n",
212
+ "\n",
213
+ "print(\"=\" * 60)\n",
214
+ "print(\"RED TEAM EVALUATION SUMMARY\")\n",
215
+ "print(\"=\" * 60)\n",
216
+ "print(f\"Total Sessions: {summary['total_sessions']}\")\n",
217
+ "print(f\"Success Rate: {summary['success_rate_pct']:.1f}%\")\n",
218
+ "print(f\"Successful: {summary['success_total']} / {summary['attempts_total']}\")\n",
219
+ "print(f\"Errors: {summary['error_total']}\")\n",
220
+ "print()\n",
221
+ "\n",
222
+ "print(\"BY OBJECTIVE\")\n",
223
+ "print(\"-\" * 60)\n",
224
+ "for obj_id, obj in report[\"by_objective\"].items():\n",
225
+ " status = \"PASS\" if obj[\"success\"] == 0 else \"FAIL\"\n",
226
+ " pct = obj[\"success\"] / obj[\"attempts\"] * 100 if obj[\"attempts\"] else 0\n",
227
+ " print(f\" {obj_id}: {obj['success']}/{obj['attempts']} succeeded ({pct:.0f}%) [{status}]\")"
228
+ ],
229
+ "execution_count": null,
230
+ "outputs": []
231
+ }
232
+ ],
233
+ "metadata": {
234
+ "kernelspec": {
235
+ "display_name": "Python 3",
236
+ "language": "python",
237
+ "name": "python3"
238
+ },
239
+ "language_info": {
240
+ "name": "python"
241
+ }
242
+ },
243
+ "nbformat": 4,
244
+ "nbformat_minor": 4
245
+ }
@@ -0,0 +1,241 @@
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {},
6
+ "source": [
7
+ "# HiddenLayer Red Team Evaluation - OpenAI Target\n",
8
+ "\n",
9
+ "Run adversarial red team attack techniques against an OpenAI chat model.\n",
10
+ "\n",
11
+ "The handler is the integration point: HiddenLayer generates attack prompts, your handler forwards each prompt to the target and returns the target's reply.\n",
12
+ "\n",
13
+ "**Prerequisites:**\n",
14
+ "- `pip install hiddenlayer-sdk openai`\n",
15
+ "- Credentials read from the environment:\n",
16
+ " - `HIDDENLAYER_CLIENT_ID` and `HIDDENLAYER_CLIENT_SECRET` (OAuth2), or `HIDDENLAYER_TOKEN` (Bearer token)\n",
17
+ " - `OPENAI_API_KEY` (used to call the target model)\n",
18
+ "\n",
19
+ "**SDK Reference:** [hiddenlayer-sdk-python](https://github.com/hiddenlayerai/hiddenlayer-sdk-python)"
20
+ ]
21
+ },
22
+ {
23
+ "cell_type": "markdown",
24
+ "metadata": {},
25
+ "source": [
26
+ "## Setup"
27
+ ]
28
+ },
29
+ {
30
+ "cell_type": "code",
31
+ "metadata": {},
32
+ "source": [
33
+ "import os\n",
34
+ "\n",
35
+ "from openai import AsyncOpenAI\n",
36
+ "\n",
37
+ "from hiddenlayer import AsyncHiddenLayer\n",
38
+ "\n",
39
+ "# AsyncHiddenLayer() reads credentials from the environment.\n",
40
+ "# For EU prod pass environment=\"prod-eu\"; for self-hosted pass base_url=\"http://your-host:port\".\n",
41
+ "client = AsyncHiddenLayer()\n",
42
+ "\n",
43
+ "openai_client = AsyncOpenAI(api_key=os.getenv(\"OPENAI_API_KEY\"))"
44
+ ],
45
+ "execution_count": null,
46
+ "outputs": []
47
+ },
48
+ {
49
+ "cell_type": "markdown",
50
+ "metadata": {},
51
+ "source": [
52
+ "## Configurables\n",
53
+ "\n",
54
+ "1. Configure target\n",
55
+ "2. Configure evaluation"
56
+ ]
57
+ },
58
+ {
59
+ "cell_type": "code",
60
+ "metadata": {},
61
+ "source": [
62
+ "# Target configuration\n",
63
+ "TARGET_MODEL = \"gpt-4o-mini\"\n",
64
+ "TARGET_SYSTEM_PROMPT = \"You are a helpful AI assistant.\"\n",
65
+ "\n",
66
+ "# Evaluation configuration\n",
67
+ "EVAL_NAME = \"OpenAI Red Team Eval\" # Name of the evaluation\n",
68
+ "EXECUTION_STRATEGY = \"single\" # Options: \"single\", \"random\", \"static_prompt_set\"\n",
69
+ "MAX_TURNS = 5 # Options: 1-5\n",
70
+ "SESSIONS_PER_TECHNIQUE = 1 # Options: 1-5\n",
71
+ "PARALLEL_TECHNIQUES = 5 # Options: 1-10"
72
+ ],
73
+ "execution_count": null,
74
+ "outputs": []
75
+ },
76
+ {
77
+ "cell_type": "markdown",
78
+ "metadata": {},
79
+ "source": [
80
+ "## Verify payload adapters\n",
81
+ "\n",
82
+ "- `to_target_request` builds the OpenAI Chat Completions payload from the attack prompt and history\n",
83
+ "- `from_target_response` extracts the assistant's reply text from the target response"
84
+ ]
85
+ },
86
+ {
87
+ "cell_type": "code",
88
+ "metadata": {},
89
+ "source": [
90
+ "def to_target_request(prompt, history, session_id):\n",
91
+ " \"\"\"Build the target request payload from the attack prompt and history.\"\"\"\n",
92
+ " messages = [{\"role\": \"system\", \"content\": TARGET_SYSTEM_PROMPT}]\n",
93
+ " messages.extend(history)\n",
94
+ " messages.append({\"role\": \"user\", \"content\": prompt})\n",
95
+ " return {\"model\": TARGET_MODEL, \"messages\": messages}\n",
96
+ "\n",
97
+ "\n",
98
+ "def from_target_response(response):\n",
99
+ " \"\"\"Extract the assistant reply text from the target response.\"\"\"\n",
100
+ " return response.choices[0].message.content or \" \""
101
+ ],
102
+ "execution_count": null,
103
+ "outputs": []
104
+ },
105
+ {
106
+ "cell_type": "markdown",
107
+ "metadata": {},
108
+ "source": [
109
+ "## Create Handler\n",
110
+ "\n",
111
+ "The handler acts as a proxy between the attacker and the target: it receives an attack prompt from HiddenLayer, calls the target, and returns the target's reply."
112
+ ]
113
+ },
114
+ {
115
+ "cell_type": "code",
116
+ "metadata": {},
117
+ "source": [
118
+ "async def handler(prompt, history, session_id, target_system_prompt):\n",
119
+ " \"\"\"Handler acts as proxy between attacker and target.\"\"\"\n",
120
+ " payload = to_target_request(prompt, history, session_id)\n",
121
+ " response = await openai_client.chat.completions.create(**payload)\n",
122
+ " return from_target_response(response)"
123
+ ],
124
+ "execution_count": null,
125
+ "outputs": []
126
+ },
127
+ {
128
+ "cell_type": "markdown",
129
+ "metadata": {},
130
+ "source": [
131
+ "## Run the Evaluation\n",
132
+ "\n",
133
+ "Open a red team session and run attack techniques in parallel against the target."
134
+ ]
135
+ },
136
+ {
137
+ "cell_type": "code",
138
+ "metadata": {},
139
+ "source": [
140
+ "session = await client.evaluation_sessions.red_team.start_session(\n",
141
+ " name=EVAL_NAME,\n",
142
+ " target_model=TARGET_MODEL,\n",
143
+ " target_system_prompt=TARGET_SYSTEM_PROMPT,\n",
144
+ " execution_strategy_type=EXECUTION_STRATEGY,\n",
145
+ " max_turns=MAX_TURNS,\n",
146
+ " sessions_per_technique=SESSIONS_PER_TECHNIQUE,\n",
147
+ " max_parallel_techniques=PARALLEL_TECHNIQUES,\n",
148
+ ")\n",
149
+ "\n",
150
+ "print(f\"Session started: {session.workflow_id}\")\n",
151
+ "\n",
152
+ "await session.run_with_callback_parallel(handler=handler)\n",
153
+ "\n",
154
+ "print(\"Evaluation complete. View results: https://console.hiddenlayer.ai/\")"
155
+ ],
156
+ "execution_count": null,
157
+ "outputs": []
158
+ },
159
+ {
160
+ "cell_type": "markdown",
161
+ "metadata": {},
162
+ "source": [
163
+ "## Resume a Session\n",
164
+ "\n",
165
+ "Reconnect to a previously started workflow by its `workflow_id` — useful after an interruption or to monitor a long-running evaluation from another process. `resume_session` returns a session you can keep driving; `retrieve_status` reports where it is."
166
+ ]
167
+ },
168
+ {
169
+ "cell_type": "code",
170
+ "metadata": {},
171
+ "source": [
172
+ "async def resume(workflow_id):\n",
173
+ " \"\"\"Reconnect to an existing workflow, finish it if still running, and return results.\"\"\"\n",
174
+ " session = await client.evaluation_sessions.red_team.resume_session(workflow_id=workflow_id)\n",
175
+ " status = await client.evaluations.red_team.retrieve_status(workflow_id)\n",
176
+ " print(f\"Resumed {session.workflow_id} - status: {status.status}\")\n",
177
+ "\n",
178
+ " if status.status == \"RUNNING\":\n",
179
+ " await session.run_with_callback_parallel(handler=handler)\n",
180
+ "\n",
181
+ " return await client.evaluations.red_team.retrieve_evaluation_results(workflow_id)\n",
182
+ "\n",
183
+ "\n",
184
+ "# results = await resume(\"<workflow_id>\")"
185
+ ],
186
+ "execution_count": null,
187
+ "outputs": []
188
+ },
189
+ {
190
+ "cell_type": "markdown",
191
+ "metadata": {},
192
+ "source": [
193
+ "## Retrieve Results\n",
194
+ "\n",
195
+ "Fetch and summarize the evaluation report for the completed session."
196
+ ]
197
+ },
198
+ {
199
+ "cell_type": "code",
200
+ "metadata": {},
201
+ "source": [
202
+ "results = await client.evaluations.red_team.retrieve_evaluation_results(\n",
203
+ " session.workflow_id\n",
204
+ ")\n",
205
+ "\n",
206
+ "report = results.result.report\n",
207
+ "summary = report[\"summary\"]\n",
208
+ "\n",
209
+ "print(\"=\" * 60)\n",
210
+ "print(\"RED TEAM EVALUATION SUMMARY\")\n",
211
+ "print(\"=\" * 60)\n",
212
+ "print(f\"Total Sessions: {summary['total_sessions']}\")\n",
213
+ "print(f\"Success Rate: {summary['success_rate_pct']:.1f}%\")\n",
214
+ "print(f\"Successful: {summary['success_total']} / {summary['attempts_total']}\")\n",
215
+ "print(f\"Errors: {summary['error_total']}\")\n",
216
+ "print()\n",
217
+ "\n",
218
+ "print(\"BY OBJECTIVE\")\n",
219
+ "print(\"-\" * 60)\n",
220
+ "for obj_id, obj in report[\"by_objective\"].items():\n",
221
+ " status = \"PASS\" if obj[\"success\"] == 0 else \"FAIL\"\n",
222
+ " pct = obj[\"success\"] / obj[\"attempts\"] * 100 if obj[\"attempts\"] else 0\n",
223
+ " print(f\" {obj_id}: {obj['success']}/{obj['attempts']} succeeded ({pct:.0f}%) [{status}]\")"
224
+ ],
225
+ "execution_count": null,
226
+ "outputs": []
227
+ }
228
+ ],
229
+ "metadata": {
230
+ "kernelspec": {
231
+ "display_name": "Python 3",
232
+ "language": "python",
233
+ "name": "python3"
234
+ },
235
+ "language_info": {
236
+ "name": "python"
237
+ }
238
+ },
239
+ "nbformat": 4,
240
+ "nbformat_minor": 4
241
+ }