Skip to main content

Re-implementation of deepagents using Google ADK primitives

Project description

adk-deepagents

Re-implementation of deepagents using Google ADK primitives.

Build autonomous, tool-using AI agents with filesystem access, shell execution, sub-agent delegation, conversation summarization, persistent memory, and skills integration — all powered by Google's Agent Development Kit.

Features

  • Filesystem toolsls, read_file, write_file, edit_file, glob, grep backed by pluggable storage
  • Shell execution — Local subprocess or sandboxed execution via Heimdall MCP
  • Browser automation — Navigate websites, fill forms, extract data via @playwright/mcp or agent-browser CLI skill
  • Sub-agent delegation — Spawn child agents for isolated, parallelizable sub-tasks
  • Conversation summarization — Automatic context window management for long-running sessions
  • Persistent memory — Load AGENTS.md files into the system prompt across sessions
  • Todo tracking — Built-in write_todos / read_todos tools for task management
  • Human-in-the-loop — Interrupt specific tools to require human approval before execution
  • Pluggable backendsStateBackend (in-memory), FilesystemBackend (local disk), CompositeBackend (path-based routing)
  • Skills integration — Optional integration with adk-skills-agent

Installation

Requires Python 3.11+.

uv pip install adk-deepagents

Or add it to a project with uv:

uv add adk-deepagents

Optional dependencies

# For skills integration
uv pip install "adk-deepagents[skills]"

# For Heimdall MCP sandboxed execution
uv pip install google-adk
npm i -g @heimdall-ai/heimdall

# For browser automation via Playwright MCP
uv pip install adk-deepagents

# For Temporal-backed dynamic task delegation
uv pip install "adk-deepagents[temporal]"

CLI Quickstart (adk-deepagents)

The package installs an adk-deepagents CLI for interactive and non-interactive workflows.

# Interactive REPL (default mode)
adk-deepagents

# Interactive REPL with an auto-submitted first prompt
adk-deepagents -m "Summarize this repository"

# One-shot non-interactive run
adk-deepagents -n "Run tests and summarize failures"

# Piped stdin non-interactive run (automation-friendly output)
printf 'Summarize README.md\n' | adk-deepagents -q

For the full command/flag reference, see docs/cli.md.

Python Quickstart

from adk_deepagents import create_deep_agent

# Create an agent with default settings:
# - Gemini 2.5 Flash model
# - Filesystem tools (ls, read, write, edit, glob, grep)
# - Todo tools (write_todos, read_todos)
# - StateBackend (in-memory file storage)
agent = create_deep_agent(
    name="my_agent",
    instruction="You are a helpful coding assistant.",
)

Running interactively

import asyncio
from google.adk.runners import InMemoryRunner

async def main():
    runner = InMemoryRunner(agent=agent, app_name="demo")
    session = await runner.session_service.create_session(
        app_name="demo", user_id="user",
    )

    async for event in runner.run_async(
        session_id=session.id,
        user_id="user",
        new_message="List the files in /",
    ):
        if event.content and event.content.parts:
            for part in event.content.parts:
                if hasattr(part, "text") and part.text:
                    print(part.text)

asyncio.run(main())

Using with ADK CLI

Create an agent.py in a directory with a top-level root_agent:

# my_project/agent.py
from adk_deepagents import create_deep_agent

root_agent = create_deep_agent(
    name="my_agent",
    instruction="You are a helpful assistant.",
)

Then run:

uv run adk run my_project/

API Reference

create_deep_agent()

The main synchronous factory function. Returns a configured google.adk.agents.LlmAgent.

from adk_deepagents import create_deep_agent

agent = create_deep_agent(
    model="gemini-2.5-flash",       # LLM model string
    tools=None,                      # Additional tool functions
    instruction=None,                # Custom system instruction
    subagents=None,                  # Sub-agent specifications
    skills=None,                     # Skill directory paths
    skills_config=None,              # SkillsConfig for adk-skills
    memory=None,                     # AGENTS.md file paths to load
    output_schema=None,              # Pydantic BaseModel for structured output
    backend=None,                    # Backend instance or factory
    execution=None,                  # "local", "heimdall", or MCP config dict
    browser=None,                    # "playwright" or BrowserConfig
    summarization=None,              # SummarizationConfig
    delegation_mode="static",       # "static", "dynamic", or "both"
    dynamic_task_config=None,        # DynamicTaskConfig (includes optional Temporal backend)
    interrupt_on=None,               # Tool names requiring approval
    name="deep_agent",              # Agent name
)

create_deep_agent_async()

Async variant that resolves MCP tools before creating the agent. Required for execution="heimdall", dict-based MCP configs, or browser="playwright".

from adk_deepagents import create_deep_agent_async

agent, cleanup = await create_deep_agent_async(
    execution="heimdall",
    # ... same parameters as create_deep_agent()
)

# When done:
if cleanup:
    await cleanup()
# Browser automation
from adk_deepagents import BrowserConfig, create_deep_agent_async

agent, cleanup = await create_deep_agent_async(
    browser="playwright",  # or BrowserConfig(headless=False)
)

# When done:
if cleanup:
    await cleanup()

Returns (LlmAgent, cleanup_fn | None).

Configuration

Backends

Backends control how the agent reads and writes files.

StateBackend (default)

In-memory file storage backed by the ADK session state dict. Files persist for the duration of the session.

agent = create_deep_agent()  # Uses StateBackend by default

FilesystemBackend

Reads and writes to the local filesystem.

from adk_deepagents.backends.filesystem import FilesystemBackend

agent = create_deep_agent(
    backend=FilesystemBackend(root_dir="/path/to/project"),
)

CompositeBackend

Routes file operations to different backends based on path prefixes. Longer prefixes take priority.

from adk_deepagents.backends import StateBackend, CompositeBackend
from adk_deepagents.backends.filesystem import FilesystemBackend

def my_backend_factory(state):
    return CompositeBackend(
        default=StateBackend(state),
        routes={
            "/workspace": FilesystemBackend(root_dir="./workspace"),
        },
    )

agent = create_deep_agent(backend=my_backend_factory)

You can also pass a BackendFactory — a callable (state: dict) -> Backend — for deferred construction from session state.

Execution

Local (subprocess)

Runs shell commands directly on the host. Suitable for development and testing.

agent = create_deep_agent(execution="local")

Heimdall MCP (sandboxed)

Sandboxed Python (Pyodide/WASM) and Bash execution via the Heimdall MCP server.

agent, cleanup = await create_deep_agent_async(execution="heimdall")

Or with custom MCP server config:

agent, cleanup = await create_deep_agent_async(
    execution={
        "command": "npx",
        "args": ["@heimdall-ai/heimdall"],
        "env": {"HEIMDALL_WORKSPACE": "/workspace"},
    },
)

# SSE transport
agent, cleanup = await create_deep_agent_async(
    execution={"uri": "http://localhost:8080"},
)

Sub-agents

Delegate isolated sub-tasks to child agents. A general-purpose sub-agent is always included by default.

from adk_deepagents import create_deep_agent, SubAgentSpec

agent = create_deep_agent(
    subagents=[
        SubAgentSpec(
            name="researcher",
            description="Searches the codebase for relevant files and patterns.",
            system_prompt="You are a code research assistant.",
        ),
        SubAgentSpec(
            name="writer",
            description="Writes and edits code files.",
            model="gemini-2.5-pro",
        ),
    ],
)

By default (delegation_mode="static"), each sub-agent is exposed as its own tool (researcher, writer, etc.) and the parent delegates by calling those tools.

Dynamic Task Delegation

Use delegation_mode="dynamic" to expose a single task tool that routes work to sub-agents at runtime (LangChain deepagents-style). The tool supports task_id to continue the same delegated sub-session across turns.

DynamicTaskConfig also lets you enforce runtime guardrails like max_depth (recursive delegation depth) and max_parallel (simultaneous running tasks).

from adk_deepagents import DynamicTaskConfig, SubAgentSpec, create_deep_agent

agent = create_deep_agent(
    subagents=[
        SubAgentSpec(name="explore", description="Searches files and code patterns."),
        SubAgentSpec(name="coder", description="Writes and edits files."),
    ],
    delegation_mode="dynamic",
    dynamic_task_config=DynamicTaskConfig(
        timeout_seconds=90,
        allow_model_override=False,
    ),
)

Use delegation_mode="both" to keep static sub-agent tools and add the dynamic task tool side by side.

Temporal-backed dynamic tasks

To run delegated task() turns on Temporal workers instead of in-process sessions, set DynamicTaskConfig.temporal:

from adk_deepagents import create_deep_agent
from adk_deepagents.types import DynamicTaskConfig, TemporalTaskConfig

agent = create_deep_agent(
    delegation_mode="dynamic",
    dynamic_task_config=DynamicTaskConfig(
        temporal=TemporalTaskConfig(
            target_host="127.0.0.1:7233",
            namespace="default",
            task_queue="adk-deepagents-tasks",
        )
    ),
)

See docs/temporal.md for worker setup, devenv services, and integration test instructions.

When the CLI runs in an environment with ADK_DEEPAGENTS_TEMPORAL_* variables, it auto-enables Temporal-backed dynamic tasks using those settings.

Summarization

Automatic context window management. When the conversation exceeds a configurable fraction of the context window, older messages are replaced with a condensed summary.

from adk_deepagents import create_deep_agent, SummarizationConfig

agent = create_deep_agent(
    summarization=SummarizationConfig(
        model="gemini-2.5-flash",
        trigger=("fraction", 0.85),     # Trigger at 85% of context window
        keep=("messages", 6),           # Keep 6 most recent messages
        history_path_prefix="/conversation_history",
    ),
)

Offloaded conversation history is saved to the backend at the configured path prefix for later reference.

Memory

Load persistent AGENTS.md files into the agent's system prompt. Memory is loaded once on the first agent invocation and cached in session state.

agent = create_deep_agent(
    memory=["/AGENTS.md", "/docs/CONTEXT.md"],
)

Memory files should contain project context, role descriptions, coding conventions, or other persistent knowledge the agent should always have access to.

Human-in-the-loop

Require human approval before specific tools execute. When a tool is interrupted, its invocation is stored in session state under _pending_approval.

agent = create_deep_agent(
    interrupt_on={
        "write_file": True,
        "execute": True,
        "read_file": False,  # Explicitly allow (no interruption)
    },
)

Structured output

Use a Pydantic BaseModel subclass to constrain the agent's final output format.

from pydantic import BaseModel

class AnalysisResult(BaseModel):
    summary: str
    issues: list[str]
    confidence: float

agent = create_deep_agent(
    output_schema=AnalysisResult,
    instruction="Analyze the given code and return structured results.",
)

Built-in Tools

Every agent created with create_deep_agent() includes these tools:

Tool Description
ls List files and directories at a path
read_file Read file contents with optional pagination
write_file Create a new file (no overwrites)
edit_file Edit a file via string replacement
glob Find files matching a glob pattern
grep Search for text patterns within files
write_todos Create or update a todo list
read_todos Read the current todo list

With execution="local" or execution="heimdall", an execute tool is also available for shell commands.

With summarization=SummarizationConfig(...), a compact_conversation tool is added for manual context compaction on the next model turn.

With browser="playwright", browser tools (browser_navigate, browser_snapshot, browser_click, browser_type, etc.) are added for web page interaction.

With subagents=[...] and delegation_mode="static" (default), one tool is generated per sub-agent specification.

With delegation_mode="dynamic" or "both", a single task tool is added for runtime delegation.

Project Structure

adk_deepagents/
├── __init__.py          # Public API exports
├── graph.py             # create_deep_agent() and create_deep_agent_async()
├── types.py             # SubAgentSpec, SummarizationConfig, SkillsConfig, BrowserConfig
├── prompts.py           # System prompt templates
├── memory.py            # AGENTS.md loading and formatting
├── summarization.py     # Context window management
├── backends/
│   ├── protocol.py      # Backend ABC and data types
│   ├── state.py         # StateBackend (in-memory)
│   ├── filesystem.py    # FilesystemBackend (local disk)
│   ├── composite.py     # CompositeBackend (path-based routing)
│   └── utils.py         # Shared utilities
├── callbacks/
│   ├── before_agent.py  # Memory loading on first invocation
│   ├── before_model.py  # Prompt injection and summarization
│   ├── before_tool.py   # Human-in-the-loop interrupts
│   └── after_tool.py    # Post-tool processing and eviction
├── execution/
│   ├── local.py         # Local subprocess execution
│   ├── heimdall.py      # Heimdall MCP integration
│   └── bridge.py        # Skills-to-Heimdall script execution bridge
├── browser/
│   ├── __init__.py      # Browser module exports
│   ├── playwright_mcp.py # Playwright MCP integration
│   └── prompts.py       # Browser agent system prompts
├── skills/
│   └── integration.py   # adk-skills registry integration
├── temporal/
│   ├── client.py        # Temporal workflow dispatch client
│   ├── workflows.py     # Dynamic task workflow definition
│   ├── activities.py    # Dynamic task activity implementation
│   └── worker.py        # Temporal worker factory
└── tools/
    ├── compact.py       # Manual conversation compaction tool
    ├── filesystem.py    # Filesystem tool implementations
    ├── todos.py         # Todo tool implementations
    └── task.py          # Sub-agent delegation tools

Development

Setup

git clone https://github.com/anthropics/adk-deepagents.git
cd adk-deepagents
uv sync

Commands

# Run all tests
uv run pytest

# Run a specific test file
uv run pytest tests/unit_tests/test_summarization.py

# Lint
uv run ruff check .

# Format
uv run ruff format .

# Type check
uv run ty check

devenv (Temporal + OTEL collector)

The repo includes a devenv.nix that can run local support services for Temporal workflows and OTEL trace collection.

# Start services (temporal-server + temporal-worker + otel-collector)
devenv up

# Enter shell with devenv-provided environment variables
devenv shell

# Start only Temporal stack processes
devenv up temporal-server temporal-worker

# Reset local OTEL state file
otel-reset

# Reset local Temporal dev state
temporal-reset

temporal-worker runs uv run python -m adk_deepagents.temporal.dev_worker and uses ADK_DEEPAGENTS_TEMPORAL_WORKER_MODEL (or ADK_DEEPAGENTS_MODEL) for its default model. It also exposes a local liveness probe on 127.0.0.1:17451 for supervisor health checks.

temporal-server also starts Temporal Web UI on http://127.0.0.1:8233.

Temporal dynamic-task workflows may stay Running for a short period so the same task_id can resume; they auto-complete after idle timeout (ADK_DEEPAGENTS_TEMPORAL_IDLE_TIMEOUT_SECONDS, default 600).

Trace collector output is written to:

.devenv/state/otel/traces.json

The lockfile (devenv.lock) pins devenv inputs for reproducible environments. Update it with:

devenv update

Testing

Tests use pytest with pytest-asyncio (asyncio_mode = "auto"). Unit tests are in tests/unit_tests/, integration tests in tests/integration_tests/.

# Run with verbose output
uv run pytest -v

# Run only unit tests
uv run pytest tests/unit_tests/

# Run tests matching a pattern
uv run pytest -k "test_summarization"

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

adk_deepagents-0.3.0.tar.gz (714.1 kB view details)

Uploaded Source

Built Distribution

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

adk_deepagents-0.3.0-py3-none-any.whl (212.8 kB view details)

Uploaded Python 3

File details

Details for the file adk_deepagents-0.3.0.tar.gz.

File metadata

  • Download URL: adk_deepagents-0.3.0.tar.gz
  • Upload date:
  • Size: 714.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for adk_deepagents-0.3.0.tar.gz
Algorithm Hash digest
SHA256 8356aedca9c04b5cd4e9cb9d2d42b46860217720a4dc3b16c26780ce43eedcd8
MD5 a3095cf94a56c624f08ddfc540763150
BLAKE2b-256 97bc6b363449a7fe3b35dae7924c0a2b65993967bc4366c11e78d0dfb981e5a2

See more details on using hashes here.

Provenance

The following attestation bundles were made for adk_deepagents-0.3.0.tar.gz:

Publisher: publish.yml on manojlds/adk-deepagents

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file adk_deepagents-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: adk_deepagents-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 212.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for adk_deepagents-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b5e82bc15aec2163d3de988ebe279fd422d12ad62ef1be681eec94d74d680082
MD5 b30cb1c8b1e9a2a122713795cda7c9b2
BLAKE2b-256 322bada8b7d1ac3c4005bc95db499ea4b43831d5c150d54f94d3d1789cf00180

See more details on using hashes here.

Provenance

The following attestation bundles were made for adk_deepagents-0.3.0-py3-none-any.whl:

Publisher: publish.yml on manojlds/adk-deepagents

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page