google-adk-extras 0.1.1__tar.gz → 0.2.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {google_adk_extras-0.1.1 → google_adk_extras-0.2.5}/MANIFEST.in +3 -1
- google_adk_extras-0.2.5/PKG-INFO +302 -0
- google_adk_extras-0.2.5/README.md +259 -0
- google_adk_extras-0.2.5/docs/agent-loading.md +28 -0
- google_adk_extras-0.2.5/docs/credentials.md +31 -0
- google_adk_extras-0.2.5/docs/examples.md +11 -0
- google_adk_extras-0.2.5/docs/fastapi.md +24 -0
- google_adk_extras-0.2.5/docs/getting-started.md +49 -0
- google_adk_extras-0.2.5/docs/index.md +19 -0
- google_adk_extras-0.2.5/docs/quickstarts.md +61 -0
- google_adk_extras-0.2.5/docs/services.md +37 -0
- google_adk_extras-0.2.5/docs/troubleshooting.md +29 -0
- google_adk_extras-0.2.5/docs/uris.md +31 -0
- google_adk_extras-0.2.5/examples/README.md +15 -0
- google_adk_extras-0.2.5/examples/consume_remote_a2a.py +40 -0
- google_adk_extras-0.2.5/examples/credentials/google_oauth2.py +27 -0
- google_adk_extras-0.2.5/examples/custom_loader.py +29 -0
- google_adk_extras-0.2.5/examples/fastapi_app.py +28 -0
- google_adk_extras-0.2.5/examples/programmatic_a2a_expose.py +37 -0
- google_adk_extras-0.2.5/examples/runner_basic.py +27 -0
- google_adk_extras-0.2.5/examples/services/artifacts_local.py +15 -0
- google_adk_extras-0.2.5/examples/services/memory_yaml.py +14 -0
- google_adk_extras-0.2.5/examples/services/sessions_sql.py +15 -0
- google_adk_extras-0.2.5/mkdocs.yml +61 -0
- google_adk_extras-0.2.5/pyproject.toml +43 -0
- {google_adk_extras-0.1.1 → google_adk_extras-0.2.5}/setup.py +40 -30
- google_adk_extras-0.2.5/src/google_adk_extras/__init__.py +31 -0
- google_adk_extras-0.2.5/src/google_adk_extras/adk_builder.py +1030 -0
- google_adk_extras-0.2.5/src/google_adk_extras/artifacts/__init__.py +28 -0
- {google_adk_extras-0.1.1 → google_adk_extras-0.2.5}/src/google_adk_extras/artifacts/base_custom_artifact_service.py +148 -11
- {google_adk_extras-0.1.1 → google_adk_extras-0.2.5}/src/google_adk_extras/artifacts/local_folder_artifact_service.py +133 -13
- {google_adk_extras-0.1.1 → google_adk_extras-0.2.5}/src/google_adk_extras/artifacts/s3_artifact_service.py +135 -19
- {google_adk_extras-0.1.1 → google_adk_extras-0.2.5}/src/google_adk_extras/artifacts/sql_artifact_service.py +109 -10
- google_adk_extras-0.2.5/src/google_adk_extras/credentials/__init__.py +34 -0
- google_adk_extras-0.2.5/src/google_adk_extras/credentials/base_custom_credential_service.py +113 -0
- google_adk_extras-0.2.5/src/google_adk_extras/credentials/github_oauth2_credential_service.py +213 -0
- google_adk_extras-0.2.5/src/google_adk_extras/credentials/google_oauth2_credential_service.py +216 -0
- google_adk_extras-0.2.5/src/google_adk_extras/credentials/http_basic_auth_credential_service.py +388 -0
- google_adk_extras-0.2.5/src/google_adk_extras/credentials/jwt_credential_service.py +345 -0
- google_adk_extras-0.2.5/src/google_adk_extras/credentials/microsoft_oauth2_credential_service.py +250 -0
- google_adk_extras-0.2.5/src/google_adk_extras/credentials/x_oauth2_credential_service.py +240 -0
- google_adk_extras-0.2.5/src/google_adk_extras/custom_agent_loader.py +170 -0
- google_adk_extras-0.2.5/src/google_adk_extras/enhanced_adk_web_server.py +137 -0
- google_adk_extras-0.2.5/src/google_adk_extras/enhanced_fastapi.py +507 -0
- google_adk_extras-0.2.5/src/google_adk_extras/enhanced_runner.py +38 -0
- google_adk_extras-0.2.5/src/google_adk_extras/memory/__init__.py +32 -0
- {google_adk_extras-0.1.1 → google_adk_extras-0.2.5}/src/google_adk_extras/memory/base_custom_memory_service.py +37 -5
- {google_adk_extras-0.1.1 → google_adk_extras-0.2.5}/src/google_adk_extras/memory/sql_memory_service.py +105 -19
- {google_adk_extras-0.1.1 → google_adk_extras-0.2.5}/src/google_adk_extras/memory/yaml_file_memory_service.py +115 -22
- google_adk_extras-0.2.5/src/google_adk_extras/sessions/__init__.py +29 -0
- {google_adk_extras-0.1.1 → google_adk_extras-0.2.5}/src/google_adk_extras/sessions/base_custom_session_service.py +133 -11
- {google_adk_extras-0.1.1 → google_adk_extras-0.2.5}/src/google_adk_extras/sessions/sql_session_service.py +127 -16
- {google_adk_extras-0.1.1 → google_adk_extras-0.2.5}/src/google_adk_extras/sessions/yaml_file_session_service.py +122 -14
- google_adk_extras-0.2.5/src/google_adk_extras.egg-info/PKG-INFO +302 -0
- {google_adk_extras-0.1.1 → google_adk_extras-0.2.5}/src/google_adk_extras.egg-info/SOURCES.txt +34 -26
- google_adk_extras-0.2.5/src/google_adk_extras.egg-info/requires.txt +38 -0
- google_adk_extras-0.2.5/tests/test_a2a_helpers.py +199 -0
- google_adk_extras-0.1.1/PKG-INFO +0 -175
- google_adk_extras-0.1.1/README.md +0 -145
- google_adk_extras-0.1.1/examples/README.md +0 -69
- google_adk_extras-0.1.1/examples/artifact/README.md +0 -41
- google_adk_extras-0.1.1/examples/artifact/example.py +0 -198
- google_adk_extras-0.1.1/examples/artifact/local_folder_artifact_example.py +0 -97
- google_adk_extras-0.1.1/examples/artifact/mongodb_artifact_example.py +0 -80
- google_adk_extras-0.1.1/examples/artifact/s3_artifact_example.py +0 -46
- google_adk_extras-0.1.1/examples/artifact/sql_artifact_example.py +0 -112
- google_adk_extras-0.1.1/examples/artifact_service_example.py +0 -196
- google_adk_extras-0.1.1/examples/google_adk_integration.py +0 -91
- google_adk_extras-0.1.1/examples/memory/README.md +0 -41
- google_adk_extras-0.1.1/examples/memory/example.py +0 -243
- google_adk_extras-0.1.1/examples/memory/mongodb_memory_example.py +0 -96
- google_adk_extras-0.1.1/examples/memory/redis_memory_example.py +0 -96
- google_adk_extras-0.1.1/examples/memory/sql_memory_example.py +0 -105
- google_adk_extras-0.1.1/examples/memory/yaml_memory_example.py +0 -93
- google_adk_extras-0.1.1/examples/session/README.md +0 -40
- google_adk_extras-0.1.1/examples/session/example.py +0 -229
- google_adk_extras-0.1.1/examples/session/mongodb_session_example.py +0 -77
- google_adk_extras-0.1.1/examples/session/redis_session_example.py +0 -70
- google_adk_extras-0.1.1/examples/session/sql_session_example.py +0 -87
- google_adk_extras-0.1.1/examples/session/yaml_session_example.py +0 -76
- google_adk_extras-0.1.1/examples/session_service_example.py +0 -118
- google_adk_extras-0.1.1/examples/test_session_service.py +0 -75
- google_adk_extras-0.1.1/pyproject.toml +0 -29
- google_adk_extras-0.1.1/src/__init__.py +0 -0
- google_adk_extras-0.1.1/src/google_adk_extras/__init__.py +0 -1
- google_adk_extras-0.1.1/src/google_adk_extras/artifacts/__init__.py +0 -15
- google_adk_extras-0.1.1/src/google_adk_extras/memory/__init__.py +0 -15
- google_adk_extras-0.1.1/src/google_adk_extras/py.typed +0 -0
- google_adk_extras-0.1.1/src/google_adk_extras/sessions/__init__.py +0 -13
- google_adk_extras-0.1.1/src/google_adk_extras.egg-info/PKG-INFO +0 -175
- google_adk_extras-0.1.1/src/google_adk_extras.egg-info/requires.txt +0 -15
- google_adk_extras-0.1.1/src/main.py +0 -0
- google_adk_extras-0.1.1/tests/test_basic.py +0 -7
- {google_adk_extras-0.1.1 → google_adk_extras-0.2.5}/LICENSE +0 -0
- {google_adk_extras-0.1.1 → google_adk_extras-0.2.5}/setup.cfg +0 -0
- {google_adk_extras-0.1.1 → google_adk_extras-0.2.5}/src/google_adk_extras/artifacts/mongo_artifact_service.py +0 -0
- {google_adk_extras-0.1.1 → google_adk_extras-0.2.5}/src/google_adk_extras/memory/mongo_memory_service.py +0 -0
- {google_adk_extras-0.1.1 → google_adk_extras-0.2.5}/src/google_adk_extras/memory/redis_memory_service.py +0 -0
- {google_adk_extras-0.1.1 → google_adk_extras-0.2.5}/src/google_adk_extras/sessions/mongo_session_service.py +0 -0
- {google_adk_extras-0.1.1 → google_adk_extras-0.2.5}/src/google_adk_extras/sessions/redis_session_service.py +0 -0
- {google_adk_extras-0.1.1 → google_adk_extras-0.2.5}/src/google_adk_extras.egg-info/dependency_links.txt +0 -0
- {google_adk_extras-0.1.1 → google_adk_extras-0.2.5}/src/google_adk_extras.egg-info/top_level.txt +0 -0
@@ -4,7 +4,9 @@ include pyproject.toml
|
|
4
4
|
include setup.py
|
5
5
|
recursive-include src *.py
|
6
6
|
recursive-include examples *.py *.md
|
7
|
+
recursive-include docs *.md
|
8
|
+
include mkdocs.yml
|
7
9
|
global-exclude __pycache__
|
8
10
|
global-exclude *.pyc
|
9
11
|
global-exclude *.pyo
|
10
|
-
global-exclude *~
|
12
|
+
global-exclude *~
|
@@ -0,0 +1,302 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: google-adk-extras
|
3
|
+
Version: 0.2.5
|
4
|
+
Summary: Production-ready services, credentials, and FastAPI wiring for Google ADK
|
5
|
+
Home-page: https://github.com/DeadMeme5441/google-adk-extras
|
6
|
+
Author: DeadMeme5441
|
7
|
+
Author-email: DeadMeme5441 <deadunderscorememe@gmail.com>
|
8
|
+
Requires-Python: >=3.10,<3.13
|
9
|
+
Description-Content-Type: text/markdown
|
10
|
+
License-File: LICENSE
|
11
|
+
Requires-Dist: google-adk
|
12
|
+
Requires-Dist: google-genai
|
13
|
+
Provides-Extra: sql
|
14
|
+
Requires-Dist: sqlalchemy; extra == "sql"
|
15
|
+
Provides-Extra: mongodb
|
16
|
+
Requires-Dist: pymongo; extra == "mongodb"
|
17
|
+
Provides-Extra: redis
|
18
|
+
Requires-Dist: redis; extra == "redis"
|
19
|
+
Provides-Extra: yaml
|
20
|
+
Requires-Dist: pyyaml; extra == "yaml"
|
21
|
+
Provides-Extra: s3
|
22
|
+
Requires-Dist: boto3; extra == "s3"
|
23
|
+
Provides-Extra: jwt
|
24
|
+
Requires-Dist: PyJWT; extra == "jwt"
|
25
|
+
Provides-Extra: web
|
26
|
+
Requires-Dist: fastapi; extra == "web"
|
27
|
+
Requires-Dist: watchdog; extra == "web"
|
28
|
+
Provides-Extra: dev
|
29
|
+
Requires-Dist: pytest; extra == "dev"
|
30
|
+
Requires-Dist: pytest-asyncio; extra == "dev"
|
31
|
+
Requires-Dist: build; extra == "dev"
|
32
|
+
Requires-Dist: twine; extra == "dev"
|
33
|
+
Provides-Extra: docs
|
34
|
+
Requires-Dist: mkdocs; extra == "docs"
|
35
|
+
Requires-Dist: mkdocs-material; extra == "docs"
|
36
|
+
Requires-Dist: mkdocs-llmstxt; extra == "docs"
|
37
|
+
Provides-Extra: all
|
38
|
+
Requires-Dist: google-adk-extras[docs,jwt,mongodb,redis,s3,sql,web,yaml]; extra == "all"
|
39
|
+
Dynamic: author
|
40
|
+
Dynamic: home-page
|
41
|
+
Dynamic: license-file
|
42
|
+
Dynamic: requires-python
|
43
|
+
|
44
|
+
# google-adk-extras
|
45
|
+
|
46
|
+
[](https://pypi.org/project/google-adk-extras/)
|
47
|
+

|
48
|
+

|
49
|
+
[](https://deadmeme5441.github.io/google-adk-extras/)
|
50
|
+
[](https://github.com/DeadMeme5441/google-adk-extras/actions/workflows/docs.yml)
|
51
|
+
|
52
|
+
Production-ready extensions for Google ADK (Agent Development Kit). This library adds durable service backends (sessions, artifacts, memory), practical credential services (OAuth2/JWT/Basic), and clean FastAPI wiring so you can run ADK agents with real storage and auth.
|
53
|
+
|
54
|
+
What this is not: a fork of ADK. It builds on ADK’s core runtime, agents, tools and callbacks, and drops in where ADK expects services and a web server.
|
55
|
+
|
56
|
+
|
57
|
+
## Why it exists
|
58
|
+
|
59
|
+
ADK provides the core primitives (Runner, Session/State, MemoryService, ArtifactService, CredentialService, Agents/Tools, callbacks, Dev UI, and deployment paths). See the official ADK docs for concepts and APIs.
|
60
|
+
|
61
|
+
This package focuses on three gaps common in real apps:
|
62
|
+
- Durable storage backends beyond in‑memory defaults
|
63
|
+
- Usable credential flows (Google/GitHub/Microsoft/X OAuth2, JWT, Basic)
|
64
|
+
- FastAPI integration that accepts your credential service without hacks
|
65
|
+
|
66
|
+
|
67
|
+
## Features
|
68
|
+
|
69
|
+
- Session services: SQL (SQLite/Postgres/MySQL), MongoDB, Redis, YAML files
|
70
|
+
- Artifact services: Local folder (versioned), S3‑compatible, SQL, MongoDB
|
71
|
+
- Memory services: SQL, MongoDB, Redis, YAML files (term search over text parts)
|
72
|
+
- Credential services: Google/GitHub/Microsoft/X (OAuth2), JWT, HTTP Basic
|
73
|
+
- Enhanced FastAPI wiring that respects a provided credential service
|
74
|
+
- Fluent builder (`AdkBuilder`) to assemble a FastAPI app or a Runner
|
75
|
+
- A2A helpers for exposing/consuming agents (see below)
|
76
|
+
|
77
|
+
Note on Runner: `EnhancedRunner` is a thin subclass of ADK’s `Runner` for compatibility with the enhanced web server; it does not change behavior.
|
78
|
+
|
79
|
+
|
80
|
+
## Install
|
81
|
+
|
82
|
+
Requirements: Python 3.12+, google-adk.
|
83
|
+
|
84
|
+
Using uv:
|
85
|
+
|
86
|
+
```bash
|
87
|
+
# create a venv (optional)
|
88
|
+
uv venv && source .venv/bin/activate
|
89
|
+
# install the package
|
90
|
+
uv pip install google-adk-extras
|
91
|
+
```
|
92
|
+
|
93
|
+
If you plan to use specific backends, also install their clients (examples):
|
94
|
+
- SQL: `uv pip install sqlalchemy`
|
95
|
+
- MongoDB: `uv pip install pymongo`
|
96
|
+
- Redis: `uv pip install redis`
|
97
|
+
- S3: `uv pip install boto3`
|
98
|
+
- JWT: `uv pip install PyJWT`
|
99
|
+
|
100
|
+
|
101
|
+
## Quickstart (FastAPI)
|
102
|
+
|
103
|
+
Use the fluent builder to wire services and credentials. Then run with uvicorn.
|
104
|
+
|
105
|
+
```python
|
106
|
+
# app.py
|
107
|
+
from google_adk_extras import AdkBuilder
|
108
|
+
from google_adk_extras.credentials import GoogleOAuth2CredentialService
|
109
|
+
|
110
|
+
app = (
|
111
|
+
AdkBuilder()
|
112
|
+
.with_agents_dir("./agents") # ADK agents on disk
|
113
|
+
.with_session_service("sqlite:///./sessions.db") # or: mongodb://, redis://, yaml://
|
114
|
+
.with_artifact_service("local://./artifacts") # or: s3://bucket, mongodb://, sql://
|
115
|
+
.with_memory_service("yaml://./memory") # or: redis://, mongodb://, sql://
|
116
|
+
.with_credential_service(GoogleOAuth2CredentialService(
|
117
|
+
client_id="…apps.googleusercontent.com",
|
118
|
+
client_secret="…",
|
119
|
+
scopes=["openid", "email", "profile"],
|
120
|
+
))
|
121
|
+
.with_web_ui(True) # serve ADK’s dev UI if assets available
|
122
|
+
.with_agent_reload(True)
|
123
|
+
.build_fastapi_app()
|
124
|
+
)
|
125
|
+
```
|
126
|
+
|
127
|
+
Run:
|
128
|
+
|
129
|
+
```bash
|
130
|
+
uvicorn app:app --reload
|
131
|
+
```
|
132
|
+
|
133
|
+
If you don’t keep agents on disk, register them programmatically and use a custom loader (see below).
|
134
|
+
|
135
|
+
|
136
|
+
## Quickstart (Runner)
|
137
|
+
|
138
|
+
Create a Runner wired with your chosen backends. Use agent name (filesystem loader) or pass an agent instance.
|
139
|
+
|
140
|
+
```python
|
141
|
+
from google_adk_extras import AdkBuilder
|
142
|
+
|
143
|
+
runner = (
|
144
|
+
AdkBuilder()
|
145
|
+
.with_agents_dir("./agents")
|
146
|
+
.with_session_service("sqlite:///./sessions.db")
|
147
|
+
.with_memory_service("redis://localhost:6379")
|
148
|
+
.with_artifact_service("local://./artifacts")
|
149
|
+
.build_runner("my_agent")
|
150
|
+
)
|
151
|
+
|
152
|
+
result = await runner.run("Hello there!")
|
153
|
+
```
|
154
|
+
|
155
|
+
|
156
|
+
## How this extends ADK (in practice)
|
157
|
+
|
158
|
+
ADK defines abstract service interfaces and a runner/web stack. This package provides drop‑in implementations and a small web‑server shim:
|
159
|
+
|
160
|
+
- Sessions
|
161
|
+
- `SQLSessionService` — SQLAlchemy; JSON‑serialized state/events
|
162
|
+
- `MongoSessionService` — PyMongo; per‑session doc, indexed by app/user/id
|
163
|
+
- `RedisSessionService` — hashes per session + user set; JSON state/events
|
164
|
+
- `YamlFileSessionService` — `base/app/user/{session_id}.yaml`
|
165
|
+
|
166
|
+
### A2A helpers (new)
|
167
|
+
|
168
|
+
Two light-weight helpers wrap ADK’s A2A capabilities:
|
169
|
+
|
170
|
+
- `AdkBuilder.enable_a2a_for_registered_agents(enabled=True, mount_base="/a2a", card_factory=None)`
|
171
|
+
- Expose programmatically registered agents (added via `with_agent_instance()` / `with_agents()`) over A2A without an `agents_dir`.
|
172
|
+
- Optionally supply `card_factory(name, agent) -> dict` to build an Agent Card; otherwise a minimal card is used.
|
173
|
+
|
174
|
+
- `AdkBuilder.with_remote_a2a_agent(name, agent_card_url, description=None)`
|
175
|
+
- Register a `RemoteA2aAgent` by agent card URL so your root agent can delegate to a remote agent.
|
176
|
+
- Requires `google-adk[a2a]` installed.
|
177
|
+
|
178
|
+
Expose a programmatic agent via A2A:
|
179
|
+
|
180
|
+
```python
|
181
|
+
from google_adk_extras import AdkBuilder
|
182
|
+
from google.adk.agents import Agent
|
183
|
+
|
184
|
+
hello = Agent(model="gemini-2.0-flash", name="hello", instruction="You are helpful.")
|
185
|
+
|
186
|
+
app = (
|
187
|
+
AdkBuilder()
|
188
|
+
.with_agent_instance("hello", hello)
|
189
|
+
.with_a2a_protocol(True)
|
190
|
+
.enable_a2a_for_registered_agents() # becomes available at /a2a/hello
|
191
|
+
.build_fastapi_app()
|
192
|
+
)
|
193
|
+
```
|
194
|
+
|
195
|
+
Consume a remote A2A agent:
|
196
|
+
|
197
|
+
```python
|
198
|
+
from a2a.utils.constants import AGENT_CARD_WELL_KNOWN_PATH
|
199
|
+
from google_adk_extras import AdkBuilder
|
200
|
+
|
201
|
+
card_url = f"http://remote-host:8001/a2a/prime{AGENT_CARD_WELL_KNOWN_PATH}"
|
202
|
+
|
203
|
+
app = (
|
204
|
+
AdkBuilder()
|
205
|
+
.with_remote_a2a_agent("prime_agent", card_url, description="Prime checker")
|
206
|
+
# add your root agent via with_agent_instance(...)
|
207
|
+
.build_fastapi_app()
|
208
|
+
)
|
209
|
+
```
|
210
|
+
|
211
|
+
- Artifacts
|
212
|
+
- `LocalFolderArtifactService` — per‑artifact metadata JSON + versioned data files
|
213
|
+
- `S3ArtifactService` — metadata JSON + versioned data objects in S3‑compatible storage
|
214
|
+
- `SQLArtifactService` — blobs per version in SQL
|
215
|
+
- `MongoArtifactService` — blobs per version in MongoDB
|
216
|
+
|
217
|
+
- Memory
|
218
|
+
- `SQLMemoryService`, `MongoMemoryService`, `RedisMemoryService`, `YamlFileMemoryService`
|
219
|
+
- Extracts text from `google.genai.types.Content`, tokenizes simple terms, and searches terms
|
220
|
+
|
221
|
+
- Credentials
|
222
|
+
- OAuth2: Google, GitHub, Microsoft, X (Twitter)
|
223
|
+
- Tokens: JWT (generate/verify/refresh‑aware), HTTP Basic (+ multi‑user variant)
|
224
|
+
- Persist via ADK’s session/in‑memory credential stores
|
225
|
+
|
226
|
+
- FastAPI integration
|
227
|
+
- `get_enhanced_fast_api_app(...)` accepts a provided credential service
|
228
|
+
- `EnhancedAdkWebServer` returns `EnhancedRunner` and keeps ADK’s caching/cleanup
|
229
|
+
- Prefer the fluent `AdkBuilder()` path for multi‑backend wiring in one place
|
230
|
+
|
231
|
+
|
232
|
+
## Agent loading options
|
233
|
+
|
234
|
+
- Directory loading (ADK default): `with_agents_dir("./agents")` and create `./agents/<app_name>/agent.json` (or your ADK agent files) per app.
|
235
|
+
- Programmatic agents: register instances and avoid a folder layout.
|
236
|
+
|
237
|
+
```python
|
238
|
+
from google_adk_extras import AdkBuilder
|
239
|
+
from google_adk_extras.custom_agent_loader import CustomAgentLoader
|
240
|
+
from google.adk.agents.base_agent import BaseAgent
|
241
|
+
|
242
|
+
loader = CustomAgentLoader()
|
243
|
+
loader.register_agent("my_app", BaseAgent(name="my_app")) # replace with a real agent
|
244
|
+
|
245
|
+
app = (
|
246
|
+
AdkBuilder()
|
247
|
+
.with_agent_loader(loader)
|
248
|
+
.with_session_service("sqlite:///./sessions.db")
|
249
|
+
.build_fastapi_app()
|
250
|
+
)
|
251
|
+
```
|
252
|
+
|
253
|
+
|
254
|
+
## Credential URI cheatsheet (optional)
|
255
|
+
|
256
|
+
If you prefer URIs instead of constructing services:
|
257
|
+
|
258
|
+
- Google OAuth2: `oauth2-google://client_id:secret@scopes=openid,email,profile`
|
259
|
+
- GitHub OAuth2: `oauth2-github://client_id:secret@scopes=user,repo`
|
260
|
+
- Microsoft OAuth2: `oauth2-microsoft://<tenant>/<client_id>:<secret>@scopes=User.Read`
|
261
|
+
- X OAuth2: `oauth2-x://client_id:secret@scopes=tweet.read,users.read`
|
262
|
+
- JWT: `jwt://<secret>@algorithm=HS256&issuer=my-app&audience=api.example.com&expiration_minutes=60`
|
263
|
+
- Basic: `basic-auth://username:password@realm=My%20API`
|
264
|
+
|
265
|
+
```python
|
266
|
+
cred = (
|
267
|
+
AdkBuilder()
|
268
|
+
.with_credential_service_uri("jwt://secret@issuer=my-app")
|
269
|
+
._create_credential_service()
|
270
|
+
)
|
271
|
+
```
|
272
|
+
|
273
|
+
|
274
|
+
## Notes & limitations
|
275
|
+
|
276
|
+
- The runner in this package is intentionally thin. All agent logic, tools, callbacks, and evaluation remain ADK responsibilities.
|
277
|
+
- The repository currently ships only the pieces listed above; referenced registries or configuration subsystems are intentionally out of scope.
|
278
|
+
- Some direct FastAPI parameters (e.g., ADK’s special memory URIs) pass through for parity, but the fluent builder is the recommended path for the extended backends offered here.
|
279
|
+
|
280
|
+
|
281
|
+
## Docs
|
282
|
+
|
283
|
+
This repo ships a full MkDocs site in `docs/`.
|
284
|
+
|
285
|
+
Build locally with uv:
|
286
|
+
|
287
|
+
```bash
|
288
|
+
uv pip install .[docs]
|
289
|
+
uv run mkdocs serve
|
290
|
+
```
|
291
|
+
|
292
|
+
## Development
|
293
|
+
|
294
|
+
```bash
|
295
|
+
uv sync # or: pip install -e .
|
296
|
+
pytest -q # run tests
|
297
|
+
```
|
298
|
+
|
299
|
+
|
300
|
+
## License
|
301
|
+
|
302
|
+
Apache 2.0 — see LICENSE.
|
@@ -0,0 +1,259 @@
|
|
1
|
+
# google-adk-extras
|
2
|
+
|
3
|
+
[](https://pypi.org/project/google-adk-extras/)
|
4
|
+

|
5
|
+

|
6
|
+
[](https://deadmeme5441.github.io/google-adk-extras/)
|
7
|
+
[](https://github.com/DeadMeme5441/google-adk-extras/actions/workflows/docs.yml)
|
8
|
+
|
9
|
+
Production-ready extensions for Google ADK (Agent Development Kit). This library adds durable service backends (sessions, artifacts, memory), practical credential services (OAuth2/JWT/Basic), and clean FastAPI wiring so you can run ADK agents with real storage and auth.
|
10
|
+
|
11
|
+
What this is not: a fork of ADK. It builds on ADK’s core runtime, agents, tools and callbacks, and drops in where ADK expects services and a web server.
|
12
|
+
|
13
|
+
|
14
|
+
## Why it exists
|
15
|
+
|
16
|
+
ADK provides the core primitives (Runner, Session/State, MemoryService, ArtifactService, CredentialService, Agents/Tools, callbacks, Dev UI, and deployment paths). See the official ADK docs for concepts and APIs.
|
17
|
+
|
18
|
+
This package focuses on three gaps common in real apps:
|
19
|
+
- Durable storage backends beyond in‑memory defaults
|
20
|
+
- Usable credential flows (Google/GitHub/Microsoft/X OAuth2, JWT, Basic)
|
21
|
+
- FastAPI integration that accepts your credential service without hacks
|
22
|
+
|
23
|
+
|
24
|
+
## Features
|
25
|
+
|
26
|
+
- Session services: SQL (SQLite/Postgres/MySQL), MongoDB, Redis, YAML files
|
27
|
+
- Artifact services: Local folder (versioned), S3‑compatible, SQL, MongoDB
|
28
|
+
- Memory services: SQL, MongoDB, Redis, YAML files (term search over text parts)
|
29
|
+
- Credential services: Google/GitHub/Microsoft/X (OAuth2), JWT, HTTP Basic
|
30
|
+
- Enhanced FastAPI wiring that respects a provided credential service
|
31
|
+
- Fluent builder (`AdkBuilder`) to assemble a FastAPI app or a Runner
|
32
|
+
- A2A helpers for exposing/consuming agents (see below)
|
33
|
+
|
34
|
+
Note on Runner: `EnhancedRunner` is a thin subclass of ADK’s `Runner` for compatibility with the enhanced web server; it does not change behavior.
|
35
|
+
|
36
|
+
|
37
|
+
## Install
|
38
|
+
|
39
|
+
Requirements: Python 3.12+, google-adk.
|
40
|
+
|
41
|
+
Using uv:
|
42
|
+
|
43
|
+
```bash
|
44
|
+
# create a venv (optional)
|
45
|
+
uv venv && source .venv/bin/activate
|
46
|
+
# install the package
|
47
|
+
uv pip install google-adk-extras
|
48
|
+
```
|
49
|
+
|
50
|
+
If you plan to use specific backends, also install their clients (examples):
|
51
|
+
- SQL: `uv pip install sqlalchemy`
|
52
|
+
- MongoDB: `uv pip install pymongo`
|
53
|
+
- Redis: `uv pip install redis`
|
54
|
+
- S3: `uv pip install boto3`
|
55
|
+
- JWT: `uv pip install PyJWT`
|
56
|
+
|
57
|
+
|
58
|
+
## Quickstart (FastAPI)
|
59
|
+
|
60
|
+
Use the fluent builder to wire services and credentials. Then run with uvicorn.
|
61
|
+
|
62
|
+
```python
|
63
|
+
# app.py
|
64
|
+
from google_adk_extras import AdkBuilder
|
65
|
+
from google_adk_extras.credentials import GoogleOAuth2CredentialService
|
66
|
+
|
67
|
+
app = (
|
68
|
+
AdkBuilder()
|
69
|
+
.with_agents_dir("./agents") # ADK agents on disk
|
70
|
+
.with_session_service("sqlite:///./sessions.db") # or: mongodb://, redis://, yaml://
|
71
|
+
.with_artifact_service("local://./artifacts") # or: s3://bucket, mongodb://, sql://
|
72
|
+
.with_memory_service("yaml://./memory") # or: redis://, mongodb://, sql://
|
73
|
+
.with_credential_service(GoogleOAuth2CredentialService(
|
74
|
+
client_id="…apps.googleusercontent.com",
|
75
|
+
client_secret="…",
|
76
|
+
scopes=["openid", "email", "profile"],
|
77
|
+
))
|
78
|
+
.with_web_ui(True) # serve ADK’s dev UI if assets available
|
79
|
+
.with_agent_reload(True)
|
80
|
+
.build_fastapi_app()
|
81
|
+
)
|
82
|
+
```
|
83
|
+
|
84
|
+
Run:
|
85
|
+
|
86
|
+
```bash
|
87
|
+
uvicorn app:app --reload
|
88
|
+
```
|
89
|
+
|
90
|
+
If you don’t keep agents on disk, register them programmatically and use a custom loader (see below).
|
91
|
+
|
92
|
+
|
93
|
+
## Quickstart (Runner)
|
94
|
+
|
95
|
+
Create a Runner wired with your chosen backends. Use agent name (filesystem loader) or pass an agent instance.
|
96
|
+
|
97
|
+
```python
|
98
|
+
from google_adk_extras import AdkBuilder
|
99
|
+
|
100
|
+
runner = (
|
101
|
+
AdkBuilder()
|
102
|
+
.with_agents_dir("./agents")
|
103
|
+
.with_session_service("sqlite:///./sessions.db")
|
104
|
+
.with_memory_service("redis://localhost:6379")
|
105
|
+
.with_artifact_service("local://./artifacts")
|
106
|
+
.build_runner("my_agent")
|
107
|
+
)
|
108
|
+
|
109
|
+
result = await runner.run("Hello there!")
|
110
|
+
```
|
111
|
+
|
112
|
+
|
113
|
+
## How this extends ADK (in practice)
|
114
|
+
|
115
|
+
ADK defines abstract service interfaces and a runner/web stack. This package provides drop‑in implementations and a small web‑server shim:
|
116
|
+
|
117
|
+
- Sessions
|
118
|
+
- `SQLSessionService` — SQLAlchemy; JSON‑serialized state/events
|
119
|
+
- `MongoSessionService` — PyMongo; per‑session doc, indexed by app/user/id
|
120
|
+
- `RedisSessionService` — hashes per session + user set; JSON state/events
|
121
|
+
- `YamlFileSessionService` — `base/app/user/{session_id}.yaml`
|
122
|
+
|
123
|
+
### A2A helpers (new)
|
124
|
+
|
125
|
+
Two light-weight helpers wrap ADK’s A2A capabilities:
|
126
|
+
|
127
|
+
- `AdkBuilder.enable_a2a_for_registered_agents(enabled=True, mount_base="/a2a", card_factory=None)`
|
128
|
+
- Expose programmatically registered agents (added via `with_agent_instance()` / `with_agents()`) over A2A without an `agents_dir`.
|
129
|
+
- Optionally supply `card_factory(name, agent) -> dict` to build an Agent Card; otherwise a minimal card is used.
|
130
|
+
|
131
|
+
- `AdkBuilder.with_remote_a2a_agent(name, agent_card_url, description=None)`
|
132
|
+
- Register a `RemoteA2aAgent` by agent card URL so your root agent can delegate to a remote agent.
|
133
|
+
- Requires `google-adk[a2a]` installed.
|
134
|
+
|
135
|
+
Expose a programmatic agent via A2A:
|
136
|
+
|
137
|
+
```python
|
138
|
+
from google_adk_extras import AdkBuilder
|
139
|
+
from google.adk.agents import Agent
|
140
|
+
|
141
|
+
hello = Agent(model="gemini-2.0-flash", name="hello", instruction="You are helpful.")
|
142
|
+
|
143
|
+
app = (
|
144
|
+
AdkBuilder()
|
145
|
+
.with_agent_instance("hello", hello)
|
146
|
+
.with_a2a_protocol(True)
|
147
|
+
.enable_a2a_for_registered_agents() # becomes available at /a2a/hello
|
148
|
+
.build_fastapi_app()
|
149
|
+
)
|
150
|
+
```
|
151
|
+
|
152
|
+
Consume a remote A2A agent:
|
153
|
+
|
154
|
+
```python
|
155
|
+
from a2a.utils.constants import AGENT_CARD_WELL_KNOWN_PATH
|
156
|
+
from google_adk_extras import AdkBuilder
|
157
|
+
|
158
|
+
card_url = f"http://remote-host:8001/a2a/prime{AGENT_CARD_WELL_KNOWN_PATH}"
|
159
|
+
|
160
|
+
app = (
|
161
|
+
AdkBuilder()
|
162
|
+
.with_remote_a2a_agent("prime_agent", card_url, description="Prime checker")
|
163
|
+
# add your root agent via with_agent_instance(...)
|
164
|
+
.build_fastapi_app()
|
165
|
+
)
|
166
|
+
```
|
167
|
+
|
168
|
+
- Artifacts
|
169
|
+
- `LocalFolderArtifactService` — per‑artifact metadata JSON + versioned data files
|
170
|
+
- `S3ArtifactService` — metadata JSON + versioned data objects in S3‑compatible storage
|
171
|
+
- `SQLArtifactService` — blobs per version in SQL
|
172
|
+
- `MongoArtifactService` — blobs per version in MongoDB
|
173
|
+
|
174
|
+
- Memory
|
175
|
+
- `SQLMemoryService`, `MongoMemoryService`, `RedisMemoryService`, `YamlFileMemoryService`
|
176
|
+
- Extracts text from `google.genai.types.Content`, tokenizes simple terms, and searches terms
|
177
|
+
|
178
|
+
- Credentials
|
179
|
+
- OAuth2: Google, GitHub, Microsoft, X (Twitter)
|
180
|
+
- Tokens: JWT (generate/verify/refresh‑aware), HTTP Basic (+ multi‑user variant)
|
181
|
+
- Persist via ADK’s session/in‑memory credential stores
|
182
|
+
|
183
|
+
- FastAPI integration
|
184
|
+
- `get_enhanced_fast_api_app(...)` accepts a provided credential service
|
185
|
+
- `EnhancedAdkWebServer` returns `EnhancedRunner` and keeps ADK’s caching/cleanup
|
186
|
+
- Prefer the fluent `AdkBuilder()` path for multi‑backend wiring in one place
|
187
|
+
|
188
|
+
|
189
|
+
## Agent loading options
|
190
|
+
|
191
|
+
- Directory loading (ADK default): `with_agents_dir("./agents")` and create `./agents/<app_name>/agent.json` (or your ADK agent files) per app.
|
192
|
+
- Programmatic agents: register instances and avoid a folder layout.
|
193
|
+
|
194
|
+
```python
|
195
|
+
from google_adk_extras import AdkBuilder
|
196
|
+
from google_adk_extras.custom_agent_loader import CustomAgentLoader
|
197
|
+
from google.adk.agents.base_agent import BaseAgent
|
198
|
+
|
199
|
+
loader = CustomAgentLoader()
|
200
|
+
loader.register_agent("my_app", BaseAgent(name="my_app")) # replace with a real agent
|
201
|
+
|
202
|
+
app = (
|
203
|
+
AdkBuilder()
|
204
|
+
.with_agent_loader(loader)
|
205
|
+
.with_session_service("sqlite:///./sessions.db")
|
206
|
+
.build_fastapi_app()
|
207
|
+
)
|
208
|
+
```
|
209
|
+
|
210
|
+
|
211
|
+
## Credential URI cheatsheet (optional)
|
212
|
+
|
213
|
+
If you prefer URIs instead of constructing services:
|
214
|
+
|
215
|
+
- Google OAuth2: `oauth2-google://client_id:secret@scopes=openid,email,profile`
|
216
|
+
- GitHub OAuth2: `oauth2-github://client_id:secret@scopes=user,repo`
|
217
|
+
- Microsoft OAuth2: `oauth2-microsoft://<tenant>/<client_id>:<secret>@scopes=User.Read`
|
218
|
+
- X OAuth2: `oauth2-x://client_id:secret@scopes=tweet.read,users.read`
|
219
|
+
- JWT: `jwt://<secret>@algorithm=HS256&issuer=my-app&audience=api.example.com&expiration_minutes=60`
|
220
|
+
- Basic: `basic-auth://username:password@realm=My%20API`
|
221
|
+
|
222
|
+
```python
|
223
|
+
cred = (
|
224
|
+
AdkBuilder()
|
225
|
+
.with_credential_service_uri("jwt://secret@issuer=my-app")
|
226
|
+
._create_credential_service()
|
227
|
+
)
|
228
|
+
```
|
229
|
+
|
230
|
+
|
231
|
+
## Notes & limitations
|
232
|
+
|
233
|
+
- The runner in this package is intentionally thin. All agent logic, tools, callbacks, and evaluation remain ADK responsibilities.
|
234
|
+
- The repository currently ships only the pieces listed above; referenced registries or configuration subsystems are intentionally out of scope.
|
235
|
+
- Some direct FastAPI parameters (e.g., ADK’s special memory URIs) pass through for parity, but the fluent builder is the recommended path for the extended backends offered here.
|
236
|
+
|
237
|
+
|
238
|
+
## Docs
|
239
|
+
|
240
|
+
This repo ships a full MkDocs site in `docs/`.
|
241
|
+
|
242
|
+
Build locally with uv:
|
243
|
+
|
244
|
+
```bash
|
245
|
+
uv pip install .[docs]
|
246
|
+
uv run mkdocs serve
|
247
|
+
```
|
248
|
+
|
249
|
+
## Development
|
250
|
+
|
251
|
+
```bash
|
252
|
+
uv sync # or: pip install -e .
|
253
|
+
pytest -q # run tests
|
254
|
+
```
|
255
|
+
|
256
|
+
|
257
|
+
## License
|
258
|
+
|
259
|
+
Apache 2.0 — see LICENSE.
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# Programmatic Agents
|
2
|
+
|
3
|
+
You don’t need on‑disk agent folders. Register agent instances directly.
|
4
|
+
|
5
|
+
```python
|
6
|
+
from google_adk_extras import AdkBuilder, CustomAgentLoader
|
7
|
+
from google.adk.agents.base_agent import BaseAgent
|
8
|
+
|
9
|
+
class EchoAgent(BaseAgent):
|
10
|
+
name = "echo"
|
11
|
+
async def _run_async_impl(self, ctx):
|
12
|
+
text = ctx.user_content.text if ctx.user_content else ""
|
13
|
+
yield self.create_text_response(f"Echo: {text}")
|
14
|
+
|
15
|
+
loader = CustomAgentLoader()
|
16
|
+
loader.register_agent("echo_app", EchoAgent())
|
17
|
+
|
18
|
+
app = (
|
19
|
+
AdkBuilder()
|
20
|
+
.with_agent_loader(loader)
|
21
|
+
.with_session_service("sqlite:///./sessions.db")
|
22
|
+
.build_fastapi_app()
|
23
|
+
)
|
24
|
+
```
|
25
|
+
|
26
|
+
Guidance
|
27
|
+
- Use programmatic loading for testing or dynamic agent assembly.
|
28
|
+
- Do not mix `with_agents_dir()` and registered instances in one builder.
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# Credentials
|
2
|
+
|
3
|
+
Provide auth to tools and agents using credential services.
|
4
|
+
|
5
|
+
## OAuth2
|
6
|
+
- `GoogleOAuth2CredentialService`
|
7
|
+
- `GitHubOAuth2CredentialService`
|
8
|
+
- `MicrosoftOAuth2CredentialService`
|
9
|
+
- `XOAuth2CredentialService`
|
10
|
+
|
11
|
+
```python
|
12
|
+
from google_adk_extras.credentials import GoogleOAuth2CredentialService
|
13
|
+
|
14
|
+
cred = GoogleOAuth2CredentialService(
|
15
|
+
client_id="...",
|
16
|
+
client_secret="...",
|
17
|
+
scopes=["openid", "email", "profile"],
|
18
|
+
)
|
19
|
+
|
20
|
+
app = AdkBuilder().with_credential_service(cred).build_fastapi_app()
|
21
|
+
```
|
22
|
+
|
23
|
+
## JWT
|
24
|
+
- `JWTCredentialService` (requires `PyJWT` via extra `[jwt]`).
|
25
|
+
|
26
|
+
## HTTP Basic
|
27
|
+
- `HTTPBasicAuthCredentialService` and multi‑user variant.
|
28
|
+
|
29
|
+
Notes
|
30
|
+
- You can also configure via URIs (see URIs page).
|
31
|
+
- Credential storage defaults to ADK’s session/in‑memory stores.
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# Examples
|
2
|
+
|
3
|
+
These examples are kept small and runnable; see the `examples/` folder.
|
4
|
+
|
5
|
+
- `examples/fastapi_app.py` — full app with durable backends.
|
6
|
+
- `examples/runner_basic.py` — runner without FastAPI.
|
7
|
+
- `examples/custom_loader.py` — programmatic agents.
|
8
|
+
- `examples/services/` — focused snippets per backend.
|
9
|
+
- `examples/credentials/` — focused credential usage.
|
10
|
+
|
11
|
+
Install extras to match what you run, e.g. `uv pip install google-adk-extras[sql,yaml,web]`.
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# FastAPI Integration
|
2
|
+
|
3
|
+
Use `get_enhanced_fast_api_app` indirectly via `AdkBuilder.build_fastapi_app()`.
|
4
|
+
|
5
|
+
Key points
|
6
|
+
- Accepts your provided `credential_service` (no forced in‑memory default).
|
7
|
+
- Honors ADK’s Dev UI when assets are present.
|
8
|
+
- Preserves ADK’s runner caching/cleanup semantics via `EnhancedAdkWebServer`.
|
9
|
+
|
10
|
+
Example
|
11
|
+
```python
|
12
|
+
app = (
|
13
|
+
AdkBuilder()
|
14
|
+
.with_agents_dir("./agents")
|
15
|
+
.with_session_service("sqlite:///./sessions.db")
|
16
|
+
.with_artifact_service("local://./artifacts")
|
17
|
+
.with_memory_service("yaml://./memory")
|
18
|
+
.build_fastapi_app()
|
19
|
+
)
|
20
|
+
```
|
21
|
+
|
22
|
+
Dev UI
|
23
|
+
- Set `with_web_ui(True)`; if ADK’s web assets are available, the UI is served.
|
24
|
+
- Use `with_agent_reload(True)` for filesystem agent hot‑reload.
|