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.dev1284.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.dev1284-py3-none-any.whl (29.5 kB view details)

Uploaded Python 3

File details

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

File metadata

File hashes

Hashes for sondera_harness_adk-0.1.0.dev1284.tar.gz
Algorithm Hash digest
SHA256 1db506dd603a4ced6368c1fc06eff240bd434d8b5dc5a56a63c2a0fc8e4a8a29
MD5 1339b53531bb2b7e748bc8c0769729ca
BLAKE2b-256 cf116cf88a6b86be54e2b1afcddccffe8e0daafe63ab181d47083bac29d0b706

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for sondera_harness_adk-0.1.0.dev1284-py3-none-any.whl
Algorithm Hash digest
SHA256 83400620e355e4e14044f6209fbda5c395665c2ff075cf58eb9c176712550289
MD5 7da825d475e926538574010229ffea42
BLAKE2b-256 46d795d5381bab5ed2e9f044646a383a81ac6c6587f8466989e5badb3b6f0e0f

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