sondera-harness 0.6.3__tar.gz → 0.7.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 (84) hide show
  1. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/PKG-INFO +7 -10
  2. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/README.md +6 -9
  3. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/pyproject.toml +1 -1
  4. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/adk/plugin.py +6 -5
  5. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/langgraph/middleware.py +6 -5
  6. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/strands/harness.py +5 -4
  7. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/types.py +0 -36
  8. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera_harness.egg-info/PKG-INFO +7 -10
  9. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/LICENSE +0 -0
  10. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/setup.cfg +0 -0
  11. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/__init__.py +0 -0
  12. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/__main__.py +0 -0
  13. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/adk/__init__.py +0 -0
  14. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/adk/analyze.py +0 -0
  15. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/cli.py +0 -0
  16. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/exceptions.py +0 -0
  17. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/harness/__init__.py +0 -0
  18. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/harness/abc.py +0 -0
  19. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/harness/cedar/__init__.py +0 -0
  20. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/harness/cedar/harness.py +0 -0
  21. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/harness/cedar/schema.py +0 -0
  22. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/harness/sondera/__init__.py +0 -0
  23. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/harness/sondera/_grpc.py +0 -0
  24. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/harness/sondera/harness.py +0 -0
  25. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/langgraph/__init__.py +0 -0
  26. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/langgraph/analyze.py +0 -0
  27. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/langgraph/exceptions.py +0 -0
  28. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/langgraph/graph.py +0 -0
  29. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/google/protobuf/any_pb2.py +0 -0
  30. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/google/protobuf/any_pb2.pyi +0 -0
  31. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/google/protobuf/any_pb2_grpc.py +0 -0
  32. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/google/protobuf/duration_pb2.py +0 -0
  33. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/google/protobuf/duration_pb2.pyi +0 -0
  34. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/google/protobuf/duration_pb2_grpc.py +0 -0
  35. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/google/protobuf/empty_pb2.py +0 -0
  36. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/google/protobuf/empty_pb2.pyi +0 -0
  37. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/google/protobuf/empty_pb2_grpc.py +0 -0
  38. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/google/protobuf/struct_pb2.py +0 -0
  39. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/google/protobuf/struct_pb2.pyi +0 -0
  40. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/google/protobuf/struct_pb2_grpc.py +0 -0
  41. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/google/protobuf/timestamp_pb2.py +0 -0
  42. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/google/protobuf/timestamp_pb2.pyi +0 -0
  43. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/google/protobuf/timestamp_pb2_grpc.py +0 -0
  44. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/google/protobuf/wrappers_pb2.py +0 -0
  45. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/google/protobuf/wrappers_pb2.pyi +0 -0
  46. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/google/protobuf/wrappers_pb2_grpc.py +0 -0
  47. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/sondera/__init__.py +0 -0
  48. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/sondera/core/__init__.py +0 -0
  49. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/sondera/core/v1/__init__.py +0 -0
  50. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/sondera/core/v1/primitives_pb2.py +0 -0
  51. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/sondera/core/v1/primitives_pb2.pyi +0 -0
  52. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/sondera/core/v1/primitives_pb2_grpc.py +0 -0
  53. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/sondera/harness/__init__.py +0 -0
  54. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/sondera/harness/v1/__init__.py +0 -0
  55. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/sondera/harness/v1/harness_pb2.py +0 -0
  56. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/sondera/harness/v1/harness_pb2.pyi +0 -0
  57. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/proto/sondera/harness/v1/harness_pb2_grpc.py +0 -0
  58. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/py.typed +0 -0
  59. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/settings.py +0 -0
  60. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/strands/__init__.py +0 -0
  61. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/strands/analyze.py +0 -0
  62. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/tui/__init__.py +0 -0
  63. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/tui/app.py +0 -0
  64. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/tui/app.tcss +0 -0
  65. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/tui/screens/__init__.py +0 -0
  66. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/tui/screens/adjudication.py +0 -0
  67. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/tui/screens/agent.py +0 -0
  68. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/tui/screens/trajectory.py +0 -0
  69. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/tui/widgets/__init__.py +0 -0
  70. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/tui/widgets/agent_card.py +0 -0
  71. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/tui/widgets/agent_list.py +0 -0
  72. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/tui/widgets/recent_adjudications.py +0 -0
  73. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/tui/widgets/recent_trajectories.py +0 -0
  74. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/tui/widgets/summary.py +0 -0
  75. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/tui/widgets/tool_card.py +0 -0
  76. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/tui/widgets/violation_panel.py +0 -0
  77. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/tui/widgets/violations_list.py +0 -0
  78. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera/tui/widgets/violations_summary.py +0 -0
  79. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera_harness.egg-info/SOURCES.txt +0 -0
  80. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera_harness.egg-info/dependency_links.txt +0 -0
  81. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera_harness.egg-info/entry_points.txt +0 -0
  82. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera_harness.egg-info/requires.txt +0 -0
  83. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/src/sondera_harness.egg-info/top_level.txt +0 -0
  84. {sondera_harness-0.6.3 → sondera_harness-0.7.0}/tests/test_harness.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sondera-harness
3
- Version: 0.6.3
3
+ Version: 0.7.0
4
4
  Summary: Sondera Harness SDK for Python - Agent governance and policy enforcement
5
5
  Author-email: Sondera AI <sdk@sondera.ai>
6
6
  License-Expression: MIT
@@ -47,11 +47,6 @@ Requires-Dist: strands-agents>=1.21.0; extra == "all"
47
47
  Dynamic: license-file
48
48
 
49
49
  <div align="center">
50
- <picture>
51
- <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/sondera-ai/harness-sdk-python/main/assets/sondera-logo-dark.svg">
52
- <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/sondera-ai/harness-sdk-python/main/assets/sondera-logo-light.svg">
53
- <img alt="Sondera" src="https://raw.githubusercontent.com/sondera-ai/harness-sdk-python/main/assets/sondera-logo-light.svg" height="60">
54
- </picture>
55
50
 
56
51
  <h1>Sondera Harness</h1>
57
52
 
@@ -66,7 +61,7 @@ Dynamic: license-file
66
61
  ·
67
62
  <a href="https://github.com/sondera-ai/sondera-harness-python/tree/main/examples">Examples</a>
68
63
  ·
69
- <a href="https://discord.gg/8zMbcnDnZs">Discord</a>
64
+ <a href="https://join.slack.com/t/sonderacommunity/shared_invite/zt-3onw10qhj-5UNQ7EMuAbPk0nTwh_sNcw">Slack</a>
70
65
  </p>
71
66
 
72
67
  <p>
@@ -94,12 +89,16 @@ This policy stops your agent from running `rm -rf`, every time.
94
89
 
95
90
  ## Quickstart
96
91
 
92
+ > **Try it now:** [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/sondera-ai/sondera-harness-python/blob/main/docs/src/notebooks/quickstart.ipynb) - no install required.
93
+
97
94
  ### 1. Install
98
95
 
99
96
  ```bash
100
97
  uv add "sondera-harness[langgraph]" # or: pip install "sondera-harness[langgraph]"
101
98
  ```
102
99
 
100
+ Works with [LangChain/LangGraph](https://docs.sondera.ai/integrations/langgraph/), [Google ADK](https://docs.sondera.ai/integrations/adk/), [Strands](https://docs.sondera.ai/integrations/strands/), and [custom agents](https://docs.sondera.ai/integrations/custom/).
101
+
103
102
  ### 2. Add to Your Agent (LangGraph)
104
103
 
105
104
  ```python
@@ -132,8 +131,6 @@ agent = create_agent(
132
131
  )
133
132
  ```
134
133
 
135
- Also supports [Google ADK](https://docs.sondera.ai/integrations/adk/), [Strands](https://docs.sondera.ai/integrations/strands/), and [custom integrations](https://docs.sondera.ai/integrations/custom/).
136
-
137
134
  > [!NOTE]
138
135
  > This example uses Sondera Platform ([free account](https://sondera.ai)), which also enables the TUI below. For local-only development, see [CedarPolicyHarness](https://docs.sondera.ai/integrations/custom/).
139
136
 
@@ -163,7 +160,7 @@ uv run sondera # or: sondera (if installed via pip)
163
160
 
164
161
  ## Community
165
162
 
166
- - [Discord](https://discord.gg/8zMbcnDnZs) for questions and feedback
163
+ - [Slack](https://join.slack.com/t/sonderacommunity/shared_invite/zt-3onw10qhj-5UNQ7EMuAbPk0nTwh_sNcw) for questions and feedback
167
164
  - [GitHub Issues](https://github.com/sondera-ai/sondera-harness-python/issues) for bugs
168
165
  - [Contributing](CONTRIBUTING.md) for development setup
169
166
 
@@ -1,9 +1,4 @@
1
1
  <div align="center">
2
- <picture>
3
- <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/sondera-ai/harness-sdk-python/main/assets/sondera-logo-dark.svg">
4
- <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/sondera-ai/harness-sdk-python/main/assets/sondera-logo-light.svg">
5
- <img alt="Sondera" src="https://raw.githubusercontent.com/sondera-ai/harness-sdk-python/main/assets/sondera-logo-light.svg" height="60">
6
- </picture>
7
2
 
8
3
  <h1>Sondera Harness</h1>
9
4
 
@@ -18,7 +13,7 @@
18
13
  ·
19
14
  <a href="https://github.com/sondera-ai/sondera-harness-python/tree/main/examples">Examples</a>
20
15
  ·
21
- <a href="https://discord.gg/8zMbcnDnZs">Discord</a>
16
+ <a href="https://join.slack.com/t/sonderacommunity/shared_invite/zt-3onw10qhj-5UNQ7EMuAbPk0nTwh_sNcw">Slack</a>
22
17
  </p>
23
18
 
24
19
  <p>
@@ -46,12 +41,16 @@ This policy stops your agent from running `rm -rf`, every time.
46
41
 
47
42
  ## Quickstart
48
43
 
44
+ > **Try it now:** [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/sondera-ai/sondera-harness-python/blob/main/docs/src/notebooks/quickstart.ipynb) - no install required.
45
+
49
46
  ### 1. Install
50
47
 
51
48
  ```bash
52
49
  uv add "sondera-harness[langgraph]" # or: pip install "sondera-harness[langgraph]"
53
50
  ```
54
51
 
52
+ Works with [LangChain/LangGraph](https://docs.sondera.ai/integrations/langgraph/), [Google ADK](https://docs.sondera.ai/integrations/adk/), [Strands](https://docs.sondera.ai/integrations/strands/), and [custom agents](https://docs.sondera.ai/integrations/custom/).
53
+
55
54
  ### 2. Add to Your Agent (LangGraph)
56
55
 
57
56
  ```python
@@ -84,8 +83,6 @@ agent = create_agent(
84
83
  )
85
84
  ```
86
85
 
87
- Also supports [Google ADK](https://docs.sondera.ai/integrations/adk/), [Strands](https://docs.sondera.ai/integrations/strands/), and [custom integrations](https://docs.sondera.ai/integrations/custom/).
88
-
89
86
  > [!NOTE]
90
87
  > This example uses Sondera Platform ([free account](https://sondera.ai)), which also enables the TUI below. For local-only development, see [CedarPolicyHarness](https://docs.sondera.ai/integrations/custom/).
91
88
 
@@ -115,7 +112,7 @@ uv run sondera # or: sondera (if installed via pip)
115
112
 
116
113
  ## Community
117
114
 
118
- - [Discord](https://discord.gg/8zMbcnDnZs) for questions and feedback
115
+ - [Slack](https://join.slack.com/t/sonderacommunity/shared_invite/zt-3onw10qhj-5UNQ7EMuAbPk0nTwh_sNcw) for questions and feedback
119
116
  - [GitHub Issues](https://github.com/sondera-ai/sondera-harness-python/issues) for bugs
120
117
  - [Contributing](CONTRIBUTING.md) for development setup
121
118
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "sondera-harness"
7
- version = "0.6.3"
7
+ version = "0.7.0"
8
8
  description = "Sondera Harness SDK for Python - Agent governance and policy enforcement"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12,<3.15"
@@ -23,6 +23,7 @@ from google.genai import types as genai_types
23
23
  from sondera.adk.analyze import format
24
24
  from sondera.harness import Harness
25
25
  from sondera.types import (
26
+ Decision,
26
27
  PromptContent,
27
28
  Role,
28
29
  Stage,
@@ -135,7 +136,7 @@ class SonderaHarnessPlugin(BasePlugin):
135
136
  f"[SonderaHarness] User message adjudication for trajectory {self._harness.trajectory_id}"
136
137
  )
137
138
 
138
- if adjudication.is_denied:
139
+ if adjudication.decision == Decision.DENY:
139
140
  return genai_types.Content(
140
141
  parts=[genai_types.Part(text=adjudication.reason)]
141
142
  )
@@ -212,7 +213,7 @@ class SonderaHarnessPlugin(BasePlugin):
212
213
  f"[SonderaHarness] Before model adjudication for trajectory {self._harness.trajectory_id}"
213
214
  )
214
215
 
215
- if adjudication.is_denied:
216
+ if adjudication.decision == Decision.DENY:
216
217
  return LlmResponse(
217
218
  content=genai_types.Content(
218
219
  parts=[genai_types.Part(text=adjudication.reason)]
@@ -254,7 +255,7 @@ class SonderaHarnessPlugin(BasePlugin):
254
255
  f"[SonderaHarness] After model adjudication for trajectory {self._harness.trajectory_id}"
255
256
  )
256
257
 
257
- if adjudication.is_denied:
258
+ if adjudication.decision == Decision.DENY:
258
259
  return LlmResponse(
259
260
  content=genai_types.Content(
260
261
  parts=[genai_types.Part(text=adjudication.reason)]
@@ -296,7 +297,7 @@ class SonderaHarnessPlugin(BasePlugin):
296
297
  f"[SonderaHarness] Before tool adjudication for trajectory {self._harness.trajectory_id}"
297
298
  )
298
299
 
299
- if adjudication.is_denied:
300
+ if adjudication.decision == Decision.DENY:
300
301
  return {"error": f"Tool blocked: {adjudication.reason}"}
301
302
  return None
302
303
 
@@ -332,7 +333,7 @@ class SonderaHarnessPlugin(BasePlugin):
332
333
  f"[SonderaHarness] After tool adjudication for trajectory {self._harness.trajectory_id}"
333
334
  )
334
335
 
335
- if adjudication.is_denied:
336
+ if adjudication.decision == Decision.DENY:
336
337
  return {"error": f"Tool result blocked: {adjudication.reason}"}
337
338
  return None
338
339
 
@@ -28,6 +28,7 @@ except ImportError:
28
28
 
29
29
  from sondera.harness import Harness
30
30
  from sondera.types import (
31
+ Decision,
31
32
  PromptContent,
32
33
  Role,
33
34
  Stage,
@@ -173,7 +174,7 @@ class SonderaHarnessMiddleware(AgentMiddleware[State]):
173
174
  f"[SonderaHarness] Before Agent Adjudication for trajectory {self._harness.trajectory_id}"
174
175
  )
175
176
 
176
- if adjudication.is_denied:
177
+ if adjudication.decision == Decision.DENY:
177
178
  self._log.warning(
178
179
  f"[SonderaHarness] Policy violation detected (strategy={self._strategy.value}): "
179
180
  f"{adjudication.reason}"
@@ -226,7 +227,7 @@ class SonderaHarnessMiddleware(AgentMiddleware[State]):
226
227
  PromptContent(text=_message_to_text(request.messages[-1])),
227
228
  )
228
229
 
229
- if pre_adjudication.is_denied:
230
+ if pre_adjudication.decision == Decision.DENY:
230
231
  _LOGGER.warning(
231
232
  f"[SonderaHarness] Pre-model policy violation (strategy={self._strategy.value}): "
232
233
  f"{pre_adjudication.reason}"
@@ -259,7 +260,7 @@ class SonderaHarnessMiddleware(AgentMiddleware[State]):
259
260
  self._log.info(
260
261
  f"[SonderaHarness] Post-model Adjudication for trajectory {self._harness.trajectory_id}"
261
262
  )
262
- if post_adjudication.is_denied:
263
+ if post_adjudication.decision == Decision.DENY:
263
264
  self._log.warning(
264
265
  f"[SonderaHarness] Post-model policy violation (strategy={self._strategy.value}): "
265
266
  f"{post_adjudication.reason}"
@@ -324,7 +325,7 @@ class SonderaHarnessMiddleware(AgentMiddleware[State]):
324
325
  f"[SonderaHarness] Before Tool Adjudication for trajectory {self._harness.trajectory_id}"
325
326
  )
326
327
 
327
- if pre_adjudication.is_denied:
328
+ if pre_adjudication.decision == Decision.DENY:
328
329
  self._log.warning(
329
330
  f"[SonderaHarness] Pre-tool policy violation for {tool_name} "
330
331
  f"(strategy={self._strategy.value}): {pre_adjudication.reason}"
@@ -367,7 +368,7 @@ class SonderaHarnessMiddleware(AgentMiddleware[State]):
367
368
  f"[SonderaHarness] After Tool Adjudication for trajectory {self._harness.trajectory_id}"
368
369
  )
369
370
 
370
- if post_adjudication.is_denied:
371
+ if post_adjudication.decision == Decision.DENY:
371
372
  self._log.warning(
372
373
  f"[SonderaHarness] Post-tool policy violation for {tool_name} "
373
374
  f"(strategy={self._strategy.value}): {post_adjudication.reason}"
@@ -16,6 +16,7 @@ from strands.hooks.events import (
16
16
  from sondera.harness import Harness
17
17
  from sondera.strands.analyze import format_strands_agent
18
18
  from sondera.types import (
19
+ Decision,
19
20
  PromptContent,
20
21
  Role,
21
22
  Stage,
@@ -163,7 +164,7 @@ class SonderaHarnessHook(HookProvider):
163
164
  f"[SonderaHarness] Before model adjudication for trajectory {self._harness.trajectory_id}"
164
165
  )
165
166
 
166
- if adjudication.is_denied:
167
+ if adjudication.decision == Decision.DENY:
167
168
  self._log.warning(
168
169
  f"[SonderaHarness] Model call blocked: {adjudication.reason}"
169
170
  )
@@ -192,7 +193,7 @@ class SonderaHarnessHook(HookProvider):
192
193
  f"[SonderaHarness] After model adjudication for trajectory {self._harness.trajectory_id}"
193
194
  )
194
195
 
195
- if adjudication.is_denied:
196
+ if adjudication.decision == Decision.DENY:
196
197
  self._log.warning(
197
198
  f"[SonderaHarness] Model response blocked: {adjudication.reason}"
198
199
  )
@@ -231,7 +232,7 @@ class SonderaHarnessHook(HookProvider):
231
232
  f"[SonderaHarness] Before tool adjudication for trajectory {self._harness.trajectory_id}"
232
233
  )
233
234
 
234
- if adjudication.is_denied:
235
+ if adjudication.decision == Decision.DENY:
235
236
  # Cancel the tool call using Strands' cancel_tool mechanism
236
237
  event.cancel_tool = f"Tool blocked by policy: {adjudication.reason}"
237
238
  self._log.warning(
@@ -262,7 +263,7 @@ class SonderaHarnessHook(HookProvider):
262
263
  f"[SonderaHarness] After tool adjudication for trajectory {self._harness.trajectory_id}"
263
264
  )
264
265
 
265
- if adjudication.is_denied:
266
+ if adjudication.decision == Decision.DENY:
266
267
  # Modify the result to indicate policy violation
267
268
  event.result = {
268
269
  "content": [
@@ -258,21 +258,6 @@ class Adjudication(Model):
258
258
  annotations: list[PolicyAnnotation] = Field(default_factory=list)
259
259
  """Annotations from policy evaluations."""
260
260
 
261
- @property
262
- def is_denied(self) -> bool:
263
- """Check if is denied."""
264
- return self.decision == Decision.DENY
265
-
266
- @property
267
- def is_allowed(self) -> bool:
268
- """Check if allowed."""
269
- return self.decision == Decision.ALLOW
270
-
271
- @property
272
- def is_escalated(self) -> bool:
273
- """Check if result requires escalation."""
274
- return self.decision == Decision.ESCALATE
275
-
276
261
 
277
262
  class AdjudicatedStep(Model):
278
263
  """Result of the adjudicated input."""
@@ -286,27 +271,6 @@ class AdjudicatedStep(Model):
286
271
  guardrails: GuardrailContext | None = None
287
272
  """Guardrail check results for this step."""
288
273
 
289
- @property
290
- def is_denied(self) -> bool:
291
- """Check if result is denied."""
292
- return (
293
- self.adjudication.decision == Decision.DENY
294
- and self.mode == PolicyEngineMode.GOVERN
295
- )
296
-
297
- @property
298
- def is_allowed(self) -> bool:
299
- """Check if result is allowed."""
300
- return self.adjudication.decision == Decision.ALLOW
301
-
302
- @property
303
- def is_escalated(self) -> bool:
304
- """Check if result requires escalation."""
305
- return (
306
- self.adjudication.decision == Decision.ESCALATE
307
- and self.mode == PolicyEngineMode.GOVERN
308
- )
309
-
310
274
  @property
311
275
  def message(self) -> str:
312
276
  """Get the adjudication reason in a friendly format."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sondera-harness
3
- Version: 0.6.3
3
+ Version: 0.7.0
4
4
  Summary: Sondera Harness SDK for Python - Agent governance and policy enforcement
5
5
  Author-email: Sondera AI <sdk@sondera.ai>
6
6
  License-Expression: MIT
@@ -47,11 +47,6 @@ Requires-Dist: strands-agents>=1.21.0; extra == "all"
47
47
  Dynamic: license-file
48
48
 
49
49
  <div align="center">
50
- <picture>
51
- <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/sondera-ai/harness-sdk-python/main/assets/sondera-logo-dark.svg">
52
- <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/sondera-ai/harness-sdk-python/main/assets/sondera-logo-light.svg">
53
- <img alt="Sondera" src="https://raw.githubusercontent.com/sondera-ai/harness-sdk-python/main/assets/sondera-logo-light.svg" height="60">
54
- </picture>
55
50
 
56
51
  <h1>Sondera Harness</h1>
57
52
 
@@ -66,7 +61,7 @@ Dynamic: license-file
66
61
  ·
67
62
  <a href="https://github.com/sondera-ai/sondera-harness-python/tree/main/examples">Examples</a>
68
63
  ·
69
- <a href="https://discord.gg/8zMbcnDnZs">Discord</a>
64
+ <a href="https://join.slack.com/t/sonderacommunity/shared_invite/zt-3onw10qhj-5UNQ7EMuAbPk0nTwh_sNcw">Slack</a>
70
65
  </p>
71
66
 
72
67
  <p>
@@ -94,12 +89,16 @@ This policy stops your agent from running `rm -rf`, every time.
94
89
 
95
90
  ## Quickstart
96
91
 
92
+ > **Try it now:** [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/sondera-ai/sondera-harness-python/blob/main/docs/src/notebooks/quickstart.ipynb) - no install required.
93
+
97
94
  ### 1. Install
98
95
 
99
96
  ```bash
100
97
  uv add "sondera-harness[langgraph]" # or: pip install "sondera-harness[langgraph]"
101
98
  ```
102
99
 
100
+ Works with [LangChain/LangGraph](https://docs.sondera.ai/integrations/langgraph/), [Google ADK](https://docs.sondera.ai/integrations/adk/), [Strands](https://docs.sondera.ai/integrations/strands/), and [custom agents](https://docs.sondera.ai/integrations/custom/).
101
+
103
102
  ### 2. Add to Your Agent (LangGraph)
104
103
 
105
104
  ```python
@@ -132,8 +131,6 @@ agent = create_agent(
132
131
  )
133
132
  ```
134
133
 
135
- Also supports [Google ADK](https://docs.sondera.ai/integrations/adk/), [Strands](https://docs.sondera.ai/integrations/strands/), and [custom integrations](https://docs.sondera.ai/integrations/custom/).
136
-
137
134
  > [!NOTE]
138
135
  > This example uses Sondera Platform ([free account](https://sondera.ai)), which also enables the TUI below. For local-only development, see [CedarPolicyHarness](https://docs.sondera.ai/integrations/custom/).
139
136
 
@@ -163,7 +160,7 @@ uv run sondera # or: sondera (if installed via pip)
163
160
 
164
161
  ## Community
165
162
 
166
- - [Discord](https://discord.gg/8zMbcnDnZs) for questions and feedback
163
+ - [Slack](https://join.slack.com/t/sonderacommunity/shared_invite/zt-3onw10qhj-5UNQ7EMuAbPk0nTwh_sNcw) for questions and feedback
167
164
  - [GitHub Issues](https://github.com/sondera-ai/sondera-harness-python/issues) for bugs
168
165
  - [Contributing](CONTRIBUTING.md) for development setup
169
166
 
File without changes