adk-agent-harness
A deep-agent harness for Google ADK: planning, subagents, background work,
structured user input, and sandboxes, built on native ADK primitives.
Documentation · Getting started · API reference · Changelog
adk-agent-harness turns a Google ADK agent into a deep agent: one that
plans, delegates to subagents, works in the background, asks the user for
structured input, and keeps long sessions on track.
It doesn't replace ADK. One factory, create_deep_agent(...), returns a
standard google.adk.apps.App. You run it with an ordinary ADK Runner, your
own model client, and your own session service, and your UI receives ordinary
ADK events.
What it adds to ADK
| Feature | What you get |
|---|---|
| Task ledger | A todo tool for plans and progress, stored in session state and shown to the model before every call |
| Prebuilt subagents | SubAgentSpec: children with their own model, tools, skills, thinking, and sandbox access |
| Spawned subagents | A spawn_subagent tool: the agent creates focused children at runtime from tools, skills, and models you allow |
| Background subagents | background=true: the child runs in isolation while the root agent continues, and its result is reported back automatically |
| Model selection | A validated catalog of models the agent can choose from for children |
| Asking the user | Structured questions with a JSON schema, pause and resume, and UI helpers |
| Sandbox workspaces | local, Daytona, E2B, or Cloud Run, with build-time credential checks and a workspace shared with subagents |
| Interrupted tool calls | Calls left without a result (cancel, crash, ignored form) are answered before the next model call, so providers don't reject the session |
| Thinking, compaction, caching | One-line settings, plus a compaction prompt written for long-running work |
Install
pip install adk-agent-harness
Python 3.10+ and google-adk>=2.7.1,<3. Optional extras install ADK's remote
sandbox backends: [daytona], [e2b], or [sandbox] for both.
Model clients and session services are yours to choose: pass any ADK BaseLlm
as model_client (for example LiteLlm for OpenAI, Anthropic, or open-source
models), and give the Runner any ADK session service, such as
DatabaseSessionService for Postgres.
Quick start
import asyncio
from google.adk.runners import InMemoryRunner
from google.genai import types
from adk_agent_harness import SpawnConfig, create_deep_agent
def search_notes(query: str) -> str:
"""Search the team's notes."""
return f"No notes found for: {query}"
app = create_deep_agent(
name="research_assistant",
model_client="gemini-3-flash-preview",
instruction="Research thoroughly and keep your plan current.",
tools=[search_notes],
spawn=SpawnConfig(enabled=True), # let the agent delegate to subagents
elicitation=True, # let the agent ask structured questions
)
async def main() -> None:
runner = InMemoryRunner(app=app)
session = await runner.session_service.create_session(app_name=app.name, user_id="u1")
message = types.Content(role="user", parts=[types.Part.from_text(text="Assess our Q3 launch risks.")])
async for event in runner.run_async(user_id="u1", session_id=session.id, new_message=message):
for part in event.content.parts if event.content else []:
if part.text and not part.thought:
print(f"[{event.author}] {part.text}")
asyncio.run(main())
Features at a glance
Subagents
from adk_agent_harness import ModelSpec, SpawnConfig, SubAgentSpec
app = create_deep_agent(
name="editor",
model_client="gemini-3-flash-preview",
instruction="Write the report and have it reviewed.",
subagents=[SubAgentSpec(name="reviewer", goal="Review drafts for factual errors.")],
available_models=[ModelSpec(id="strong", model_client="gemini-3-pro-preview",
description="Hard reasoning and review.")],
spawn=SpawnConfig(enabled=True, tools={"fetch_url": fetch_url}),
)
Prebuilt subagents become tools named after them. spawn_subagent lets the
agent create a child on the fly. Both run like ADK's own single-turn subagents
and stream their events in the root run_async() stream.
Subagents guide →
Background subagents
The agent calls spawn_subagent(..., background=true), gets a task ID
immediately, and keeps working. The result is added to its next model call.
Your app can stream the child's events separately:
from adk_agent_harness import stream_background_task_events
async for event in stream_background_task_events(task_id):
... # raw ADK events from the child
Asking the user
from adk_agent_harness import create_elicitation_response, project_elicitation_event
request = project_elicitation_event(event) # the agent paused with a question
if request:
reply = create_elicitation_response(request, {"environment": "staging"})
async for event in runner.run_async(user_id=uid, session_id=sid,
invocation_id=request.invocation_id, new_message=reply):
...
Sandbox workspaces
app = create_deep_agent(..., sandbox="e2b") # or "local", "daytona", "cloud_run"
The agent gets ADK's Execute, ReadFile, WriteFile, and EditFile tools.
Missing credentials fail when the agent is built, not on first use.
Sandbox guide →
Long-running sessions
from adk_agent_harness import CompactionConfig, ThinkingConfig
app = create_deep_agent(
...,
thinking=ThinkingConfig(include_thoughts=True),
compaction=CompactionConfig(token_threshold=100_000),
context_cache=True,
)
Thinking, compaction, caching guide →
Examples
Runnable examples live in
examples/sdk:
the task ledger, skills and toolsets, thinking and compaction, subagents,
elicitation and model selection, and sandboxes.
Development
uv sync # dev tools included
uv run python -m pytest tests/unit
uv sync --group docs && uv run zensical serve # docs at http://localhost:8000
Releases: see
docs/PUBLISHING.md.
License
MIT
Metadata
Release files for adk-agent-harness 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| adk_agent_harness-0.2.0.tar.gz | 84.9 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| adk_agent_harness-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 115.9 kB
Release files / adk_agent_harness-0.2.0.tar.gz
| Download URL | adk_agent_harness-0.2.0.tar.gz |
|---|---|
| Size | 84.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ab9c3a8a5fbdcea5b29ad9354ac44518101f37e7bf5f3e20df876f55cccafc33
|
|
BLAKE2b-256 checksum How to use checksums |
49fce45edbe3678f6a42ee94deec19f0a59bff28b6ec00450fbd47820ad3adbd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.
Transparency logRelease files / adk_agent_harness-0.2.0-py3-none-any.whl
| Download URL | adk_agent_harness-0.2.0-py3-none-any.whl |
|---|---|
| Size | 31.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e4ab182373000b67145b6e5654568f06f9af8ffd62f4d20fdbeb8df65460d830
|
|
BLAKE2b-256 checksum How to use checksums |
f34e85ab479f0cf9ee4d43d72e5df1c0282b70ef2ea0e54cd60f366cbf164d86
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.
Transparency logSecurity for adk-agent-harness 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for adk_agent_harness-0.2.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.