Observed since 20 Oct, 19:36 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Re-implementation of deepagents using Google ADK primitives
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.
ls, read_file, write_file, edit_file, glob, grep backed by pluggable storageAGENTS.md files into the system prompt across sessionswrite_todos / read_todos tools for task managementStateBackend (in-memory), FilesystemBackend (local disk), CompositeBackend (path-based routing)Requires Python 3.11+.
uv pip install adk-deepagents
Or add it to a project with uv:
uv add adk-deepagents
# 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]"
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.
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.",
)
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())
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/
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).
Backends control how the agent reads and writes files.
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
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"),
)
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.
Runs shell commands directly on the host. Suitable for development and testing.
agent = create_deep_agent(execution="local")
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"},
)
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.
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.
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.
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.
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.
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)
},
)
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.",
)
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.
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
git clone https://github.com/anthropics/adk-deepagents.git
cd adk-deepagents
uv sync
# 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
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
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"
MIT
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 0.3.0 | 5 Apr 2026 | 8 |
This describes our collected data; it is not a security assessment.
Observed since 20 Oct, 19:36 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:b3b2a1e2c25c5eaa52fac510baf696a988a911eb0aa6211ca355b1bb5f95ed3f