sondera-harness 0.6.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 (83) hide show
  1. sondera_harness-0.6.0/LICENSE +21 -0
  2. sondera_harness-0.6.0/PKG-INFO +323 -0
  3. sondera_harness-0.6.0/README.md +275 -0
  4. sondera_harness-0.6.0/pyproject.toml +160 -0
  5. sondera_harness-0.6.0/setup.cfg +4 -0
  6. sondera_harness-0.6.0/src/sondera/__init__.py +111 -0
  7. sondera_harness-0.6.0/src/sondera/__main__.py +4 -0
  8. sondera_harness-0.6.0/src/sondera/adk/__init__.py +3 -0
  9. sondera_harness-0.6.0/src/sondera/adk/analyze.py +222 -0
  10. sondera_harness-0.6.0/src/sondera/adk/plugin.py +387 -0
  11. sondera_harness-0.6.0/src/sondera/cli.py +22 -0
  12. sondera_harness-0.6.0/src/sondera/exceptions.py +167 -0
  13. sondera_harness-0.6.0/src/sondera/harness/__init__.py +6 -0
  14. sondera_harness-0.6.0/src/sondera/harness/abc.py +102 -0
  15. sondera_harness-0.6.0/src/sondera/harness/cedar/__init__.py +0 -0
  16. sondera_harness-0.6.0/src/sondera/harness/cedar/harness.py +363 -0
  17. sondera_harness-0.6.0/src/sondera/harness/cedar/schema.py +225 -0
  18. sondera_harness-0.6.0/src/sondera/harness/sondera/__init__.py +0 -0
  19. sondera_harness-0.6.0/src/sondera/harness/sondera/_grpc.py +354 -0
  20. sondera_harness-0.6.0/src/sondera/harness/sondera/harness.py +890 -0
  21. sondera_harness-0.6.0/src/sondera/langgraph/__init__.py +15 -0
  22. sondera_harness-0.6.0/src/sondera/langgraph/analyze.py +543 -0
  23. sondera_harness-0.6.0/src/sondera/langgraph/exceptions.py +19 -0
  24. sondera_harness-0.6.0/src/sondera/langgraph/graph.py +210 -0
  25. sondera_harness-0.6.0/src/sondera/langgraph/middleware.py +454 -0
  26. sondera_harness-0.6.0/src/sondera/proto/google/protobuf/any_pb2.py +37 -0
  27. sondera_harness-0.6.0/src/sondera/proto/google/protobuf/any_pb2.pyi +14 -0
  28. sondera_harness-0.6.0/src/sondera/proto/google/protobuf/any_pb2_grpc.py +24 -0
  29. sondera_harness-0.6.0/src/sondera/proto/google/protobuf/duration_pb2.py +37 -0
  30. sondera_harness-0.6.0/src/sondera/proto/google/protobuf/duration_pb2.pyi +14 -0
  31. sondera_harness-0.6.0/src/sondera/proto/google/protobuf/duration_pb2_grpc.py +24 -0
  32. sondera_harness-0.6.0/src/sondera/proto/google/protobuf/empty_pb2.py +37 -0
  33. sondera_harness-0.6.0/src/sondera/proto/google/protobuf/empty_pb2.pyi +9 -0
  34. sondera_harness-0.6.0/src/sondera/proto/google/protobuf/empty_pb2_grpc.py +24 -0
  35. sondera_harness-0.6.0/src/sondera/proto/google/protobuf/struct_pb2.py +47 -0
  36. sondera_harness-0.6.0/src/sondera/proto/google/protobuf/struct_pb2.pyi +49 -0
  37. sondera_harness-0.6.0/src/sondera/proto/google/protobuf/struct_pb2_grpc.py +24 -0
  38. sondera_harness-0.6.0/src/sondera/proto/google/protobuf/timestamp_pb2.py +37 -0
  39. sondera_harness-0.6.0/src/sondera/proto/google/protobuf/timestamp_pb2.pyi +14 -0
  40. sondera_harness-0.6.0/src/sondera/proto/google/protobuf/timestamp_pb2_grpc.py +24 -0
  41. sondera_harness-0.6.0/src/sondera/proto/google/protobuf/wrappers_pb2.py +53 -0
  42. sondera_harness-0.6.0/src/sondera/proto/google/protobuf/wrappers_pb2.pyi +59 -0
  43. sondera_harness-0.6.0/src/sondera/proto/google/protobuf/wrappers_pb2_grpc.py +24 -0
  44. sondera_harness-0.6.0/src/sondera/proto/sondera/__init__.py +0 -0
  45. sondera_harness-0.6.0/src/sondera/proto/sondera/core/__init__.py +0 -0
  46. sondera_harness-0.6.0/src/sondera/proto/sondera/core/v1/__init__.py +0 -0
  47. sondera_harness-0.6.0/src/sondera/proto/sondera/core/v1/primitives_pb2.py +88 -0
  48. sondera_harness-0.6.0/src/sondera/proto/sondera/core/v1/primitives_pb2.pyi +259 -0
  49. sondera_harness-0.6.0/src/sondera/proto/sondera/core/v1/primitives_pb2_grpc.py +24 -0
  50. sondera_harness-0.6.0/src/sondera/proto/sondera/harness/__init__.py +0 -0
  51. sondera_harness-0.6.0/src/sondera/proto/sondera/harness/v1/__init__.py +0 -0
  52. sondera_harness-0.6.0/src/sondera/proto/sondera/harness/v1/harness_pb2.py +81 -0
  53. sondera_harness-0.6.0/src/sondera/proto/sondera/harness/v1/harness_pb2.pyi +192 -0
  54. sondera_harness-0.6.0/src/sondera/proto/sondera/harness/v1/harness_pb2_grpc.py +498 -0
  55. sondera_harness-0.6.0/src/sondera/py.typed +0 -0
  56. sondera_harness-0.6.0/src/sondera/settings.py +20 -0
  57. sondera_harness-0.6.0/src/sondera/strands/__init__.py +5 -0
  58. sondera_harness-0.6.0/src/sondera/strands/analyze.py +244 -0
  59. sondera_harness-0.6.0/src/sondera/strands/harness.py +333 -0
  60. sondera_harness-0.6.0/src/sondera/tui/__init__.py +0 -0
  61. sondera_harness-0.6.0/src/sondera/tui/app.py +309 -0
  62. sondera_harness-0.6.0/src/sondera/tui/screens/__init__.py +5 -0
  63. sondera_harness-0.6.0/src/sondera/tui/screens/adjudication.py +184 -0
  64. sondera_harness-0.6.0/src/sondera/tui/screens/agent.py +158 -0
  65. sondera_harness-0.6.0/src/sondera/tui/screens/trajectory.py +158 -0
  66. sondera_harness-0.6.0/src/sondera/tui/widgets/__init__.py +23 -0
  67. sondera_harness-0.6.0/src/sondera/tui/widgets/agent_card.py +94 -0
  68. sondera_harness-0.6.0/src/sondera/tui/widgets/agent_list.py +73 -0
  69. sondera_harness-0.6.0/src/sondera/tui/widgets/recent_adjudications.py +52 -0
  70. sondera_harness-0.6.0/src/sondera/tui/widgets/recent_trajectories.py +54 -0
  71. sondera_harness-0.6.0/src/sondera/tui/widgets/summary.py +57 -0
  72. sondera_harness-0.6.0/src/sondera/tui/widgets/tool_card.py +33 -0
  73. sondera_harness-0.6.0/src/sondera/tui/widgets/violation_panel.py +72 -0
  74. sondera_harness-0.6.0/src/sondera/tui/widgets/violations_list.py +78 -0
  75. sondera_harness-0.6.0/src/sondera/tui/widgets/violations_summary.py +104 -0
  76. sondera_harness-0.6.0/src/sondera/types.py +346 -0
  77. sondera_harness-0.6.0/src/sondera_harness.egg-info/PKG-INFO +323 -0
  78. sondera_harness-0.6.0/src/sondera_harness.egg-info/SOURCES.txt +81 -0
  79. sondera_harness-0.6.0/src/sondera_harness.egg-info/dependency_links.txt +1 -0
  80. sondera_harness-0.6.0/src/sondera_harness.egg-info/entry_points.txt +2 -0
  81. sondera_harness-0.6.0/src/sondera_harness.egg-info/requires.txt +25 -0
  82. sondera_harness-0.6.0/src/sondera_harness.egg-info/top_level.txt +1 -0
  83. sondera_harness-0.6.0/tests/test_harness.py +254 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sondera, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,323 @@
1
+ Metadata-Version: 2.4
2
+ Name: sondera-harness
3
+ Version: 0.6.0
4
+ Summary: Sondera Harness SDK for Python - Agent governance and policy enforcement
5
+ Author-email: Sondera AI <sdk@sondera.ai>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/sondera-ai/harness-sdk-python
8
+ Project-URL: Documentation, https://docs.sondera.ai
9
+ Project-URL: Repository, https://github.com/sondera-ai/harness-sdk-python
10
+ Project-URL: Issues, https://github.com/sondera-ai/harness-sdk-python/issues
11
+ Project-URL: Changelog, https://github.com/sondera-ai/harness-sdk-python/blob/main/CHANGELOG.md
12
+ Keywords: ai,agents,governance,policy,guardrails,llm,langchain,langgraph
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
21
+ Classifier: Topic :: Security
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: <3.15,>=3.12
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: cedar-python>=0.1.1
27
+ Requires-Dist: click>=8.0.0
28
+ Requires-Dist: click-default-group>=1.2.4
29
+ Requires-Dist: grpcio>=1.76.0
30
+ Requires-Dist: grpcio-tools>=1.76.0
31
+ Requires-Dist: httpx>=0.27.0
32
+ Requires-Dist: pydantic>=2.12.0
33
+ Requires-Dist: pydantic-settings>=2.12.0
34
+ Requires-Dist: textual>=6.11.0
35
+ Provides-Extra: adk
36
+ Requires-Dist: google-adk>=1.22.0; extra == "adk"
37
+ Provides-Extra: langgraph
38
+ Requires-Dist: langchain>=1.2.0; extra == "langgraph"
39
+ Requires-Dist: langgraph>=1.0.5; extra == "langgraph"
40
+ Provides-Extra: strands
41
+ Requires-Dist: strands-agents>=1.21.0; extra == "strands"
42
+ Provides-Extra: all
43
+ Requires-Dist: google-adk>=1.22.0; extra == "all"
44
+ Requires-Dist: langchain>=1.2.0; extra == "all"
45
+ Requires-Dist: langgraph>=1.0.5; extra == "all"
46
+ Requires-Dist: strands-agents>=1.21.0; extra == "all"
47
+ Dynamic: license-file
48
+
49
+ # Sondera Harness SDK for Python
50
+
51
+ [![Python 3.12+](https://img.shields.io/badge/python-3.12+-blue.svg)](https://www.python.org/downloads/)
52
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
53
+
54
+ >
55
+ > One step at a time. One action at a time. One trajectory at a time.
56
+ >
57
+
58
+ AI agents systems operate beyond traditional security boundaries, making autonomous decisions, calling tools, and accessing resources based on context that changes with every execution. Sondera SDK provides runtime governance for these agentic systems, answering not just "can this agent do X?" but "should it do X here, now, with this data?" Built for developers deploying agents through LangGraph, Google ADK, and Strands, Sondera enables real-time trajectory tracking, policy-as-code enforcement via Cedar, and behavioral adjudication so you can ship agents with confidence.
59
+
60
+ ## Features
61
+
62
+ - **Managed harness-as-a-service** with the Sondera Harness for enterprise policy governance and guardrails
63
+ - **Local policy-as-code** using Cedar policy language in the Cedar Policy Harness
64
+ - **Real-time trajectory** observability, adjudication, and steering
65
+ - **Scaffold integrations** for LangGraph, Google ADK, and Strands
66
+ - **CLI and TUI** for monitoring agent behavior
67
+
68
+ ## Installation
69
+
70
+ ```bash
71
+ uv add sondera-harness
72
+ ```
73
+
74
+ ### Optional Dependencies
75
+
76
+ Install extras for specific framework integrations:
77
+
78
+ ```bash
79
+ # Google ADK support
80
+ uv add sondera-harness --extra adk
81
+
82
+ # LangGraph support
83
+ uv add sondera-harness --extra langgraph
84
+
85
+ # Strands support
86
+ uv add sondera-harness --extra strands
87
+
88
+ # All integrations
89
+ uv add sondera-harness --all-extras
90
+ ```
91
+
92
+ ## Quick Start
93
+
94
+ ### Configuration
95
+
96
+ Set your API credentials via environment variables:
97
+
98
+ ```bash
99
+ export SONDERA_HARNESS_ENDPOINT="your-harness.sondera.ai:443"
100
+ export SONDERA_API_TOKEN="<YOUR_SONDERA_API_KEY>"
101
+ ```
102
+
103
+ Or create a `.env` file or `~/.sondera/env`:
104
+
105
+ ```env
106
+ SONDERA_HARNESS_ENDPOINT=your-harness.sondera.ai:443
107
+ SONDERA_API_TOKEN=<YOUR_SONDERA_API_KEY>
108
+ ```
109
+
110
+ ## Scaffold Integrations
111
+
112
+ ### LangGraph / LangChain
113
+
114
+ ```python
115
+ from langchain.agents import create_agent
116
+ from sondera.harness import SonderaRemoteHarness
117
+ from sondera.langgraph import SonderaHarnessMiddleware, Strategy, create_agent_from_langchain_tools
118
+
119
+ # Analyze your tools and create agent metadata
120
+ sondera_agent = create_agent_from_langchain_tools(
121
+ tools=my_tools,
122
+ agent_id="langchain-agent",
123
+ agent_name="My LangChain Agent",
124
+ agent_description="An agent that helps with tasks",
125
+ )
126
+
127
+ # Create harness with agent
128
+ harness = SonderaRemoteHarness(agent=sondera_agent)
129
+
130
+ # Create middleware
131
+ middleware = SonderaHarnessMiddleware(
132
+ harness=harness,
133
+ strategy=Strategy.BLOCK, # or Strategy.STEER
134
+ )
135
+
136
+ # Create agent with middleware
137
+ agent = create_agent(
138
+ model=my_model,
139
+ tools=my_tools,
140
+ middleware=[middleware],
141
+ )
142
+ ```
143
+
144
+ ### Google ADK
145
+
146
+ ```python
147
+ from google.adk.agents import Agent
148
+ from google.adk.runners import Runner
149
+ from sondera.harness import SonderaRemoteHarness
150
+ from sondera.adk import SonderaHarnessPlugin
151
+
152
+ # Create harness
153
+ harness = SonderaRemoteHarness(
154
+ sondera_api_key="<YOUR_SONDERA_API_KEY>",
155
+ )
156
+
157
+ # Create plugin
158
+ plugin = SonderaHarnessPlugin(harness=harness)
159
+
160
+ # Create agent
161
+ agent = Agent(
162
+ name="my-adk-agent",
163
+ model="gemini-2.0-flash",
164
+ instruction="Be helpful and safe",
165
+ tools=[...],
166
+ )
167
+
168
+ # Create runner with plugin
169
+ runner = Runner(
170
+ agent=agent,
171
+ app_name="my-app",
172
+ plugins=[plugin],
173
+ )
174
+ ```
175
+
176
+ ### Strands Agents
177
+
178
+ ```python
179
+ from strands import Agent
180
+ from sondera.harness import SonderaRemoteHarness
181
+ from sondera.strands import SonderaHarnessHook
182
+
183
+ # Create harness
184
+ harness = SonderaRemoteHarness(
185
+ sondera_api_key="<YOUR_SONDERA_API_KEY>",
186
+ )
187
+
188
+ # Create hook
189
+ hook = SonderaHarnessHook(harness=harness)
190
+
191
+ # Create agent with hook
192
+ agent = Agent(
193
+ system_prompt="You are a helpful assistant",
194
+ model="anthropic.claude-3-5-sonnet-20241022-v2:0",
195
+ hooks=[hook],
196
+ )
197
+
198
+ # Run agent (hooks fire automatically)
199
+ response = agent("What is 5 + 3?")
200
+ ```
201
+
202
+ ### Custom Scaffold
203
+
204
+ ```python
205
+ from sondera import SonderaRemoteHarness, Agent, PromptContent, Role, Stage
206
+
207
+ # Create a harness instance
208
+ harness = SonderaRemoteHarness(
209
+ sondera_harness_endpoint="localhost:50051",
210
+ sondera_api_key="<YOUR_SONDERA_API_KEY>",
211
+ sondera_harness_client_secure=True, # Enable TLS for production
212
+ )
213
+
214
+ # Define your agent
215
+ agent = Agent(
216
+ id="my-agent",
217
+ provider_id="custom",
218
+ name="My Assistant",
219
+ description="A helpful AI assistant",
220
+ instruction="Be helpful, accurate, and safe",
221
+ tools=[],
222
+ )
223
+
224
+ # Initialize a trajectory
225
+ await harness.initialize(agent=agent)
226
+
227
+ # Adjudicate user input
228
+ adjudication = await harness.adjudicate(
229
+ Stage.PRE_MODEL,
230
+ Role.USER,
231
+ PromptContent(text="Hello, can you help me?"),
232
+ )
233
+
234
+ if adjudication.is_allowed:
235
+ # Proceed with agent logic
236
+ pass
237
+ elif adjudication.is_denied:
238
+ print(f"Request blocked: {adjudication.reason}")
239
+
240
+ # Finalize the trajectory
241
+ await harness.finalize()
242
+ ```
243
+
244
+ ## Remote and Local Harnesses
245
+
246
+ ### Cedar Policy Harness (Local Only)
247
+
248
+ For a local harness deployment, you can use the `CedarPolicyHarness` to evaluate Cedar policies:
249
+
250
+ ```python
251
+ from sondera.harness import CedarPolicyHarness
252
+ from sondera import Agent
253
+
254
+ # Define Cedar policies
255
+ policies = '''
256
+ @id("forbid-dangerous-bash")
257
+ forbid(
258
+ principal,
259
+ action == Coding_Agent::Action::"Bash",
260
+ resource
261
+ )
262
+ when {
263
+ context has parameters &&
264
+ (context.parameters.command like "*rm -rf /*" ||
265
+ context.parameters.command like "*mkfs*" ||
266
+ context.parameters.command like "*dd if=/dev/zero*" ||
267
+ context.parameters.command like "*> /dev/sda*")
268
+ };
269
+ '''
270
+
271
+ # Create local policy engine
272
+ harness = CedarPolicyHarness(
273
+ policy_set=policies,
274
+ agent=my_agent,
275
+ )
276
+
277
+ await harness.initialize()
278
+ # Use same adjudication API as RemoteHarness
279
+ ```
280
+
281
+ ## CLI & TUI
282
+
283
+ Launch the Sondera TUI for monitoring (note, requires a Sondera account and API key):
284
+
285
+ ```bash
286
+ sondera
287
+ ```
288
+
289
+ The TUI provides:
290
+ - Real-time agent and trajectory overview
291
+ - Adjudication history and policy violations
292
+ - Agent details and tool inspection
293
+
294
+ ## Examples
295
+
296
+ See the [examples/](examples/) directory for complete demos:
297
+
298
+ - **LangGraph**: Investment chatbot with policy enforcement
299
+ - **ADK**: Payment and healthcare agents
300
+ - **Strands**: Various agent implementations
301
+
302
+ ## Environment Variables
303
+
304
+ | Variable | Description | Default |
305
+ |----------|-------------|---------|
306
+ | `SONDERA_HARNESS_ENDPOINT` | Harness service endpoint | `localhost:50051` |
307
+ | `SONDERA_API_TOKEN` | JWT authentication token | Required for remote |
308
+
309
+ ## Requirements
310
+
311
+ - Python 3.12 or higher (up to 3.14)
312
+
313
+ ## Security
314
+
315
+ See [SECURITY.md](SECURITY.md) for security best practices and vulnerability reporting.
316
+
317
+ ## Contributing
318
+
319
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for contribution guidelines.
320
+
321
+ ## License
322
+
323
+ MIT - see [LICENSE](LICENSE) for details.
@@ -0,0 +1,275 @@
1
+ # Sondera Harness SDK for Python
2
+
3
+ [![Python 3.12+](https://img.shields.io/badge/python-3.12+-blue.svg)](https://www.python.org/downloads/)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
5
+
6
+ >
7
+ > One step at a time. One action at a time. One trajectory at a time.
8
+ >
9
+
10
+ AI agents systems operate beyond traditional security boundaries, making autonomous decisions, calling tools, and accessing resources based on context that changes with every execution. Sondera SDK provides runtime governance for these agentic systems, answering not just "can this agent do X?" but "should it do X here, now, with this data?" Built for developers deploying agents through LangGraph, Google ADK, and Strands, Sondera enables real-time trajectory tracking, policy-as-code enforcement via Cedar, and behavioral adjudication so you can ship agents with confidence.
11
+
12
+ ## Features
13
+
14
+ - **Managed harness-as-a-service** with the Sondera Harness for enterprise policy governance and guardrails
15
+ - **Local policy-as-code** using Cedar policy language in the Cedar Policy Harness
16
+ - **Real-time trajectory** observability, adjudication, and steering
17
+ - **Scaffold integrations** for LangGraph, Google ADK, and Strands
18
+ - **CLI and TUI** for monitoring agent behavior
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ uv add sondera-harness
24
+ ```
25
+
26
+ ### Optional Dependencies
27
+
28
+ Install extras for specific framework integrations:
29
+
30
+ ```bash
31
+ # Google ADK support
32
+ uv add sondera-harness --extra adk
33
+
34
+ # LangGraph support
35
+ uv add sondera-harness --extra langgraph
36
+
37
+ # Strands support
38
+ uv add sondera-harness --extra strands
39
+
40
+ # All integrations
41
+ uv add sondera-harness --all-extras
42
+ ```
43
+
44
+ ## Quick Start
45
+
46
+ ### Configuration
47
+
48
+ Set your API credentials via environment variables:
49
+
50
+ ```bash
51
+ export SONDERA_HARNESS_ENDPOINT="your-harness.sondera.ai:443"
52
+ export SONDERA_API_TOKEN="<YOUR_SONDERA_API_KEY>"
53
+ ```
54
+
55
+ Or create a `.env` file or `~/.sondera/env`:
56
+
57
+ ```env
58
+ SONDERA_HARNESS_ENDPOINT=your-harness.sondera.ai:443
59
+ SONDERA_API_TOKEN=<YOUR_SONDERA_API_KEY>
60
+ ```
61
+
62
+ ## Scaffold Integrations
63
+
64
+ ### LangGraph / LangChain
65
+
66
+ ```python
67
+ from langchain.agents import create_agent
68
+ from sondera.harness import SonderaRemoteHarness
69
+ from sondera.langgraph import SonderaHarnessMiddleware, Strategy, create_agent_from_langchain_tools
70
+
71
+ # Analyze your tools and create agent metadata
72
+ sondera_agent = create_agent_from_langchain_tools(
73
+ tools=my_tools,
74
+ agent_id="langchain-agent",
75
+ agent_name="My LangChain Agent",
76
+ agent_description="An agent that helps with tasks",
77
+ )
78
+
79
+ # Create harness with agent
80
+ harness = SonderaRemoteHarness(agent=sondera_agent)
81
+
82
+ # Create middleware
83
+ middleware = SonderaHarnessMiddleware(
84
+ harness=harness,
85
+ strategy=Strategy.BLOCK, # or Strategy.STEER
86
+ )
87
+
88
+ # Create agent with middleware
89
+ agent = create_agent(
90
+ model=my_model,
91
+ tools=my_tools,
92
+ middleware=[middleware],
93
+ )
94
+ ```
95
+
96
+ ### Google ADK
97
+
98
+ ```python
99
+ from google.adk.agents import Agent
100
+ from google.adk.runners import Runner
101
+ from sondera.harness import SonderaRemoteHarness
102
+ from sondera.adk import SonderaHarnessPlugin
103
+
104
+ # Create harness
105
+ harness = SonderaRemoteHarness(
106
+ sondera_api_key="<YOUR_SONDERA_API_KEY>",
107
+ )
108
+
109
+ # Create plugin
110
+ plugin = SonderaHarnessPlugin(harness=harness)
111
+
112
+ # Create agent
113
+ agent = Agent(
114
+ name="my-adk-agent",
115
+ model="gemini-2.0-flash",
116
+ instruction="Be helpful and safe",
117
+ tools=[...],
118
+ )
119
+
120
+ # Create runner with plugin
121
+ runner = Runner(
122
+ agent=agent,
123
+ app_name="my-app",
124
+ plugins=[plugin],
125
+ )
126
+ ```
127
+
128
+ ### Strands Agents
129
+
130
+ ```python
131
+ from strands import Agent
132
+ from sondera.harness import SonderaRemoteHarness
133
+ from sondera.strands import SonderaHarnessHook
134
+
135
+ # Create harness
136
+ harness = SonderaRemoteHarness(
137
+ sondera_api_key="<YOUR_SONDERA_API_KEY>",
138
+ )
139
+
140
+ # Create hook
141
+ hook = SonderaHarnessHook(harness=harness)
142
+
143
+ # Create agent with hook
144
+ agent = Agent(
145
+ system_prompt="You are a helpful assistant",
146
+ model="anthropic.claude-3-5-sonnet-20241022-v2:0",
147
+ hooks=[hook],
148
+ )
149
+
150
+ # Run agent (hooks fire automatically)
151
+ response = agent("What is 5 + 3?")
152
+ ```
153
+
154
+ ### Custom Scaffold
155
+
156
+ ```python
157
+ from sondera import SonderaRemoteHarness, Agent, PromptContent, Role, Stage
158
+
159
+ # Create a harness instance
160
+ harness = SonderaRemoteHarness(
161
+ sondera_harness_endpoint="localhost:50051",
162
+ sondera_api_key="<YOUR_SONDERA_API_KEY>",
163
+ sondera_harness_client_secure=True, # Enable TLS for production
164
+ )
165
+
166
+ # Define your agent
167
+ agent = Agent(
168
+ id="my-agent",
169
+ provider_id="custom",
170
+ name="My Assistant",
171
+ description="A helpful AI assistant",
172
+ instruction="Be helpful, accurate, and safe",
173
+ tools=[],
174
+ )
175
+
176
+ # Initialize a trajectory
177
+ await harness.initialize(agent=agent)
178
+
179
+ # Adjudicate user input
180
+ adjudication = await harness.adjudicate(
181
+ Stage.PRE_MODEL,
182
+ Role.USER,
183
+ PromptContent(text="Hello, can you help me?"),
184
+ )
185
+
186
+ if adjudication.is_allowed:
187
+ # Proceed with agent logic
188
+ pass
189
+ elif adjudication.is_denied:
190
+ print(f"Request blocked: {adjudication.reason}")
191
+
192
+ # Finalize the trajectory
193
+ await harness.finalize()
194
+ ```
195
+
196
+ ## Remote and Local Harnesses
197
+
198
+ ### Cedar Policy Harness (Local Only)
199
+
200
+ For a local harness deployment, you can use the `CedarPolicyHarness` to evaluate Cedar policies:
201
+
202
+ ```python
203
+ from sondera.harness import CedarPolicyHarness
204
+ from sondera import Agent
205
+
206
+ # Define Cedar policies
207
+ policies = '''
208
+ @id("forbid-dangerous-bash")
209
+ forbid(
210
+ principal,
211
+ action == Coding_Agent::Action::"Bash",
212
+ resource
213
+ )
214
+ when {
215
+ context has parameters &&
216
+ (context.parameters.command like "*rm -rf /*" ||
217
+ context.parameters.command like "*mkfs*" ||
218
+ context.parameters.command like "*dd if=/dev/zero*" ||
219
+ context.parameters.command like "*> /dev/sda*")
220
+ };
221
+ '''
222
+
223
+ # Create local policy engine
224
+ harness = CedarPolicyHarness(
225
+ policy_set=policies,
226
+ agent=my_agent,
227
+ )
228
+
229
+ await harness.initialize()
230
+ # Use same adjudication API as RemoteHarness
231
+ ```
232
+
233
+ ## CLI & TUI
234
+
235
+ Launch the Sondera TUI for monitoring (note, requires a Sondera account and API key):
236
+
237
+ ```bash
238
+ sondera
239
+ ```
240
+
241
+ The TUI provides:
242
+ - Real-time agent and trajectory overview
243
+ - Adjudication history and policy violations
244
+ - Agent details and tool inspection
245
+
246
+ ## Examples
247
+
248
+ See the [examples/](examples/) directory for complete demos:
249
+
250
+ - **LangGraph**: Investment chatbot with policy enforcement
251
+ - **ADK**: Payment and healthcare agents
252
+ - **Strands**: Various agent implementations
253
+
254
+ ## Environment Variables
255
+
256
+ | Variable | Description | Default |
257
+ |----------|-------------|---------|
258
+ | `SONDERA_HARNESS_ENDPOINT` | Harness service endpoint | `localhost:50051` |
259
+ | `SONDERA_API_TOKEN` | JWT authentication token | Required for remote |
260
+
261
+ ## Requirements
262
+
263
+ - Python 3.12 or higher (up to 3.14)
264
+
265
+ ## Security
266
+
267
+ See [SECURITY.md](SECURITY.md) for security best practices and vulnerability reporting.
268
+
269
+ ## Contributing
270
+
271
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for contribution guidelines.
272
+
273
+ ## License
274
+
275
+ MIT - see [LICENSE](LICENSE) for details.