This release is a pre-release and may not be stable for production use.
sondera-harness-adk
Sondera Harness governance plugin for Google ADK 2.x agents. Wraps every ADK callback point (user message, model, tool, run lifecycle) with policy adjudication against the Sondera Platform.
The package's public surface is deliberately narrow: only
SonderaHarnessPlugin is exported from the top-level package.
Installation
uv add sondera-harness-adk
Quick Start
from google.adk import Agent
from google.adk.runners import Runner
from sondera_harness_adk import SonderaHarnessPlugin
from sondera_harness_adk.harness import SonderaRemoteHarness
# Endpoint/token resolve from SONDERA_HARNESS_ENDPOINT / SONDERA_API_TOKEN
# (or ~/.sondera/env) when not passed explicitly.
harness = SonderaRemoteHarness()
plugin = SonderaHarnessPlugin(harness=harness)
agent = Agent(name="my-agent", model="gemini-2.5-flash", ...)
runner = Runner(agent=agent, app_name="my-app", plugins=[plugin])
SonderaHarnessPlugin accepts any sondera_harness_adk.abc.Harness
implementation, so custom harnesses (e.g. a local policy engine) can be
substituted for SonderaRemoteHarness. A custom harness must implement
new_scope() or be supplied as harness_factory=... so concurrent web
sessions never share mutable trajectory state.
SonderaRemoteHarness.new_scope() shallow-copies the configured harness so
subclass behavior, instance configuration, and the transport client carry into
each session while the trajectory identity is reset. Subclasses that add other
mutable per-trajectory fields must override new_scope() to reset them, or use
harness_factory=... to construct fully isolated scopes.
Tool classification
A tool call is adjudicated as the narrowest action it fits. A tool whose name
and arguments identify a file operation, a shell command, or a web fetch is sent
as FileOperation / ShellCommand / WebFetch, so the policies written for
that class apply to it; its result is reported as the matching observation.
Everything else stays a generic ToolCall, which reaches Cedar only as
Sondera::Action::"PreToolUse".
Reclassification requires the identifying argument as well as the name — a path
(or a patch body), a command string, or a URL. An ADK tool is an arbitrary
Python callable, so the name sets have to include bare verbs like read and
create; without the argument requirement an issue-tracker create would have
the file-write signature policies run against its body, which on a fail-closed
gate is a spurious deny rather than a mislabelled log line. Shell names are kept
deliberately narrow (bash, shell, terminal, run_shell_command, …)
because ADK has no canonical shell tool.
See sondera_harness_adk.tool for the full name and argument sets.
ADK web and sub-agents
adk web constructs and caches the Runner, so register the plugin by exporting
an ADK App from agents/<app_name>/agent.py:
app = App(
name="support_triage",
root_agent=root_agent,
plugins=[SonderaHarnessPlugin(harness=SonderaRemoteHarness())],
)
The plugin analyzes the complete agent tree. The root card keeps the canonical
tool inventory used by policy enforcement and exposes typed flat sub-agent
descriptors. Events keep the root Agent as the policy principal and record the
currently executing agent separately as observational attribution.
One trajectory scope is retained per (app, user, session). Fully consumed
Runner, FastAPI /run, and ADK Web /run_sse requests release their invocation
lease; shutdown then finalizes every idle scope. Direct Runner streams abandoned
before ADK runs its finalizer remain active and prevent finalization. Transport
disconnect behavior belongs to ADK's stream cleanup; the plugin only releases a
lease after receiving after_run_callback, so a missing callback stays visible
as an active fail-closed residual.
If initialization or finalization fails after a trajectory may have been created or completed remotely, that session scope is quarantined. It cannot adjudicate or initialize again; eviction or shutdown must successfully clean it up before the capacity can be reused.
The remote adapter publishes a pending trajectory ID before sending Started
or Resumed. Transport errors cannot prove whether the server received the
event, so even a pre-send failure is conservatively quarantined and targeted by
the normal terminal cleanup path.
License
MIT — see LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sondera_harness_adk-0.1.0.dev1281.tar.gz.
File metadata
- Download URL: sondera_harness_adk-0.1.0.dev1281.tar.gz
- Upload date:
- Size: 50.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
68f4188fac6357f79e1bec0f54cb54aab91dbc4d5ab7639f4397fa0d5da35ef5
|
|
| MD5 |
ddbe65718fdd7069ac41e968b0d491c0
|
|
| BLAKE2b-256 |
e9945700a8f53b301d4e7be749ca8af6feeba963ee30fc6fff01827792adeaf6
|
File details
Details for the file sondera_harness_adk-0.1.0.dev1281-py3-none-any.whl.
File metadata
- Download URL: sondera_harness_adk-0.1.0.dev1281-py3-none-any.whl
- Upload date:
- Size: 29.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
01f6546986d4d4e986da80a1a4efa52a5eaccc2015597e14132c72a1dd3f464b
|
|
| MD5 |
5c765479b02ba584aa1666145ec611e9
|
|
| BLAKE2b-256 |
2bcfa8311c74ac3cfc93611b12c9e966a61ad1936c06d39fb48d2c1ba742c6ec
|