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

Uploaded Python 3

File details

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

File metadata

File hashes

Hashes for sondera_harness_adk-0.1.0.dev1281.tar.gz
Algorithm Hash digest
SHA256 68f4188fac6357f79e1bec0f54cb54aab91dbc4d5ab7639f4397fa0d5da35ef5
MD5 ddbe65718fdd7069ac41e968b0d491c0
BLAKE2b-256 e9945700a8f53b301d4e7be749ca8af6feeba963ee30fc6fff01827792adeaf6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for sondera_harness_adk-0.1.0.dev1281-py3-none-any.whl
Algorithm Hash digest
SHA256 01f6546986d4d4e986da80a1a4efa52a5eaccc2015597e14132c72a1dd3f464b
MD5 5c765479b02ba584aa1666145ec611e9
BLAKE2b-256 2bcfa8311c74ac3cfc93611b12c9e966a61ad1936c06d39fb48d2c1ba742c6ec

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