Skip to main content
Pre-release

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

sondera_harness_adk-0.1.0.dev1337.tar.gz (50.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sondera_harness_adk-0.1.0.dev1337-py3-none-any.whl (29.5 kB view details)

Uploaded Python 3

File details

Details for the file sondera_harness_adk-0.1.0.dev1337.tar.gz.

File metadata

File hashes

Hashes for sondera_harness_adk-0.1.0.dev1337.tar.gz
Algorithm Hash digest
SHA256 51a3d277f58ca0854099e87b798b5fc52a0c76a97de6f0713cce090b23d39443
MD5 0ece4bb09381bbc0be74c0a9fc22dc91
BLAKE2b-256 62c7c11d79a8ef2633e4576c0590c0a99b73c879a44bca8efba5f9d0adb9d647

See more details on using hashes here.

File details

Details for the file sondera_harness_adk-0.1.0.dev1337-py3-none-any.whl.

File metadata

File hashes

Hashes for sondera_harness_adk-0.1.0.dev1337-py3-none-any.whl
Algorithm Hash digest
SHA256 59e6e5ee332e9b09c3305ffa883cdb89f7d36d831abcd8ae9170e309494f6733
MD5 a79550625c530fb82bb72d256286fec2
BLAKE2b-256 c7f75cc6d12eb627ce4ead52b06960d88dd75d36eb948aaa288cdfc0b2d69085

See more details on using hashes here.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page