hindsight-google-adk 0.1.0__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.
- hindsight_google_adk-0.1.0/.gitignore +62 -0
- hindsight_google_adk-0.1.0/LICENSE +21 -0
- hindsight_google_adk-0.1.0/PKG-INFO +166 -0
- hindsight_google_adk-0.1.0/README.md +142 -0
- hindsight_google_adk-0.1.0/hindsight_google_adk/__init__.py +39 -0
- hindsight_google_adk-0.1.0/hindsight_google_adk/_client.py +46 -0
- hindsight_google_adk-0.1.0/hindsight_google_adk/config.py +109 -0
- hindsight_google_adk-0.1.0/hindsight_google_adk/errors.py +7 -0
- hindsight_google_adk-0.1.0/hindsight_google_adk/memory.py +284 -0
- hindsight_google_adk-0.1.0/hindsight_google_adk/py.typed +0 -0
- hindsight_google_adk-0.1.0/hindsight_google_adk/tools.py +195 -0
- hindsight_google_adk-0.1.0/pyproject.toml +56 -0
- hindsight_google_adk-0.1.0/scripts/smoke_runner.py +212 -0
- hindsight_google_adk-0.1.0/tests/__init__.py +0 -0
- hindsight_google_adk-0.1.0/tests/test_config.py +70 -0
- hindsight_google_adk-0.1.0/tests/test_memory.py +299 -0
- hindsight_google_adk-0.1.0/tests/test_tools.py +155 -0
- hindsight_google_adk-0.1.0/uv.lock +2244 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Python-generated files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[oc]
|
|
4
|
+
build/
|
|
5
|
+
dist/
|
|
6
|
+
wheels/
|
|
7
|
+
*.egg-info
|
|
8
|
+
.mcp.json
|
|
9
|
+
.osgrep
|
|
10
|
+
# Virtual environments
|
|
11
|
+
.venv
|
|
12
|
+
|
|
13
|
+
# Node
|
|
14
|
+
node_modules/
|
|
15
|
+
|
|
16
|
+
# Environment variables and local config
|
|
17
|
+
.env
|
|
18
|
+
docker-compose.yml
|
|
19
|
+
docker-compose.override.yml
|
|
20
|
+
|
|
21
|
+
# IDE
|
|
22
|
+
.idea/
|
|
23
|
+
.vscode/
|
|
24
|
+
*.swp
|
|
25
|
+
*.swo
|
|
26
|
+
|
|
27
|
+
# NLTK data (will be downloaded automatically)
|
|
28
|
+
nltk_data/
|
|
29
|
+
|
|
30
|
+
# Monitoring stack (Prometheus/Grafana binaries and data)
|
|
31
|
+
.monitoring/
|
|
32
|
+
.pgbouncer/
|
|
33
|
+
|
|
34
|
+
# Large benchmark datasets (will be downloaded automatically)
|
|
35
|
+
**/longmemeval_s_cleaned.json
|
|
36
|
+
|
|
37
|
+
# Debug logs
|
|
38
|
+
logs/
|
|
39
|
+
|
|
40
|
+
.DS_Store
|
|
41
|
+
|
|
42
|
+
# Generated docs files
|
|
43
|
+
hindsight-docs/static/llms-full.txt
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
hindsight-dev/benchmarks/locomo/results/
|
|
47
|
+
hindsight-dev/benchmarks/longmemeval/results/
|
|
48
|
+
hindsight-dev/benchmarks/consolidation/results/
|
|
49
|
+
hindsight-dev/benchmarks/perf/results/
|
|
50
|
+
benchmarks/results/
|
|
51
|
+
hindsight-cli/target
|
|
52
|
+
hindsight-clients/rust/target
|
|
53
|
+
.claude/*
|
|
54
|
+
!.claude/skills/
|
|
55
|
+
whats-next.md
|
|
56
|
+
TASK.md
|
|
57
|
+
# Parked / draft integrations that aren't ready to ship
|
|
58
|
+
hindsight-integrations/_drafts/
|
|
59
|
+
# Changelog is now tracked in hindsight-docs/src/pages/changelog.md
|
|
60
|
+
# CHANGELOG.md
|
|
61
|
+
|
|
62
|
+
blog-post*
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vectorize
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hindsight-google-adk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Google ADK integration for Hindsight - persistent long-term memory for ADK agents
|
|
5
|
+
Project-URL: Homepage, https://github.com/vectorize-io/hindsight
|
|
6
|
+
Project-URL: Documentation, https://github.com/vectorize-io/hindsight/tree/main/hindsight-integrations/google-adk
|
|
7
|
+
Project-URL: Repository, https://github.com/vectorize-io/hindsight
|
|
8
|
+
Author-email: Vectorize <support@vectorize.io>
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: adk,agents,ai,google-adk,hindsight,memory
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Requires-Dist: google-adk>=2.0
|
|
22
|
+
Requires-Dist: hindsight-client>=0.4.0
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# hindsight-google-adk
|
|
26
|
+
|
|
27
|
+
Persistent long-term memory for [Google ADK](https://adk.dev/) agents via [Hindsight](https://vectorize.io/hindsight).
|
|
28
|
+
|
|
29
|
+
The package gives you two complementary patterns:
|
|
30
|
+
|
|
31
|
+
- **`HindsightMemoryService`** — Implements ADK's `BaseMemoryService`. Pass it to `Runner(memory_service=...)` and sessions are automatically retained on completion; agents calling `search_memory` get results back from Hindsight.
|
|
32
|
+
- **`create_hindsight_tools(...)`** — Returns a list of ADK `FunctionTool` instances (`hindsight_retain`, `hindsight_recall`, `hindsight_reflect`) the model can call inside a turn.
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install hindsight-google-adk
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Quick Start: Automatic Memory
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
import asyncio
|
|
44
|
+
from google.adk.agents import LlmAgent
|
|
45
|
+
from google.adk.runners import Runner
|
|
46
|
+
from google.adk.sessions import InMemorySessionService
|
|
47
|
+
|
|
48
|
+
from hindsight_google_adk import HindsightMemoryService
|
|
49
|
+
|
|
50
|
+
memory = HindsightMemoryService.from_url(
|
|
51
|
+
hindsight_api_url="https://api.hindsight.vectorize.io",
|
|
52
|
+
api_key="hsk_...",
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
agent = LlmAgent(name="assistant", model="gemini-2.0-flash")
|
|
56
|
+
|
|
57
|
+
runner = Runner(
|
|
58
|
+
app_name="my-app",
|
|
59
|
+
agent=agent,
|
|
60
|
+
session_service=InMemorySessionService(),
|
|
61
|
+
memory_service=memory,
|
|
62
|
+
)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
When a session ends, `Runner` calls `add_session_to_memory`, which retains the session's events to a Hindsight bank keyed by `(app_name, user_id)`. When the agent (or another call) invokes `search_memory(app_name, user_id, query)`, the integration runs a Hindsight recall and returns the results as ADK `MemoryEntry` objects.
|
|
66
|
+
|
|
67
|
+
## Quick Start: Explicit Tools
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
from google.adk.agents import LlmAgent
|
|
71
|
+
from hindsight_google_adk import create_hindsight_tools
|
|
72
|
+
|
|
73
|
+
tools = create_hindsight_tools(
|
|
74
|
+
bank_id="user-123",
|
|
75
|
+
hindsight_api_url="https://api.hindsight.vectorize.io",
|
|
76
|
+
api_key="hsk_...",
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
agent = LlmAgent(name="assistant", model="gemini-2.0-flash", tools=tools)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The agent now has three tools (toggle with `include_retain` / `include_recall` / `include_reflect`):
|
|
83
|
+
|
|
84
|
+
- `hindsight_retain(content)` — store information to long-term memory
|
|
85
|
+
- `hindsight_recall(query)` — search memory and return matches
|
|
86
|
+
- `hindsight_reflect(query)` — synthesize a coherent answer from memory
|
|
87
|
+
|
|
88
|
+
## Global Configuration
|
|
89
|
+
|
|
90
|
+
For shared defaults, call `configure(...)` once at startup:
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
from hindsight_google_adk import configure
|
|
94
|
+
|
|
95
|
+
configure(
|
|
96
|
+
hindsight_api_url="https://api.hindsight.vectorize.io",
|
|
97
|
+
api_key=None, # falls back to HINDSIGHT_API_KEY env var
|
|
98
|
+
bank_id_template="{app_name}::{user_id}",
|
|
99
|
+
budget="mid",
|
|
100
|
+
max_tokens=4096,
|
|
101
|
+
)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Subsequent `HindsightMemoryService.from_url()` and `create_hindsight_tools()` calls use the global config as a fallback.
|
|
105
|
+
|
|
106
|
+
## Bank ID Derivation
|
|
107
|
+
|
|
108
|
+
By default, each `(app_name, user_id)` pair gets its own bank: `"{app_name}::{user_id}"`. Override with `bank_id_template`:
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
# Per-user bank shared across apps
|
|
112
|
+
HindsightMemoryService.from_url(..., bank_id_template="user::{user_id}")
|
|
113
|
+
|
|
114
|
+
# Static bank shared across all users
|
|
115
|
+
HindsightMemoryService.from_url(..., bank_id_template="my-shared-bank")
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Configuration Reference
|
|
119
|
+
|
|
120
|
+
| Argument | Default | Description |
|
|
121
|
+
|---|---|---|
|
|
122
|
+
| `hindsight_api_url` | `https://api.hindsight.vectorize.io` | Hindsight API URL (Cloud by default). |
|
|
123
|
+
| `api_key` | `HINDSIGHT_API_KEY` env | Bearer token for Hindsight Cloud. |
|
|
124
|
+
| `bank_id_template` | `"{app_name}::{user_id}"` | Format string for deriving the bank id. |
|
|
125
|
+
| `budget` | `"mid"` | Recall budget: `low`/`mid`/`high`. |
|
|
126
|
+
| `max_tokens` | `4096` | Max tokens for recall results. |
|
|
127
|
+
| `tags` | `None` | Extra tags added to retains. `app:` and `user:` are always added. |
|
|
128
|
+
| `recall_tags` | `None` | Extra tags appended to recall queries. `user:` is always added. |
|
|
129
|
+
| `recall_tags_match` | `"any"` | Tag match mode: `any` / `all` / `any_strict` / `all_strict`. |
|
|
130
|
+
| `mission` | `None` | If set, the bank is created (idempotent) on first use with this fact-extraction mission. |
|
|
131
|
+
| `context` | `"google-adk"` | Provenance label attached to retained content. |
|
|
132
|
+
|
|
133
|
+
## Memory Scoping with Tags
|
|
134
|
+
|
|
135
|
+
Each retained session/event carries `app:<app_name>` and `user:<user_id>` tags. Recall queries automatically include `user:<user_id>` so users never see each other's memories. Pass `tags=[...]` to extend the retain set or `recall_tags=[...]` to filter recall further.
|
|
136
|
+
|
|
137
|
+
## Connection Modes
|
|
138
|
+
|
|
139
|
+
### Hindsight Cloud (recommended)
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
HindsightMemoryService.from_url(
|
|
143
|
+
hindsight_api_url="https://api.hindsight.vectorize.io",
|
|
144
|
+
api_key="hsk_...",
|
|
145
|
+
)
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Self-hosted
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
HindsightMemoryService.from_url(hindsight_api_url="http://localhost:8888")
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Error Handling
|
|
155
|
+
|
|
156
|
+
All `add_*` and `search_memory` methods are resilient: Hindsight failures are logged but never propagate to the `Runner`. The explicit tools raise `HindsightError` on failure so the agent can react.
|
|
157
|
+
|
|
158
|
+
## Requirements
|
|
159
|
+
|
|
160
|
+
- Python 3.10+
|
|
161
|
+
- `google-adk>=2.0`
|
|
162
|
+
- `hindsight-client>=0.4.0`
|
|
163
|
+
|
|
164
|
+
## License
|
|
165
|
+
|
|
166
|
+
MIT
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# hindsight-google-adk
|
|
2
|
+
|
|
3
|
+
Persistent long-term memory for [Google ADK](https://adk.dev/) agents via [Hindsight](https://vectorize.io/hindsight).
|
|
4
|
+
|
|
5
|
+
The package gives you two complementary patterns:
|
|
6
|
+
|
|
7
|
+
- **`HindsightMemoryService`** — Implements ADK's `BaseMemoryService`. Pass it to `Runner(memory_service=...)` and sessions are automatically retained on completion; agents calling `search_memory` get results back from Hindsight.
|
|
8
|
+
- **`create_hindsight_tools(...)`** — Returns a list of ADK `FunctionTool` instances (`hindsight_retain`, `hindsight_recall`, `hindsight_reflect`) the model can call inside a turn.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pip install hindsight-google-adk
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Quick Start: Automatic Memory
|
|
17
|
+
|
|
18
|
+
```python
|
|
19
|
+
import asyncio
|
|
20
|
+
from google.adk.agents import LlmAgent
|
|
21
|
+
from google.adk.runners import Runner
|
|
22
|
+
from google.adk.sessions import InMemorySessionService
|
|
23
|
+
|
|
24
|
+
from hindsight_google_adk import HindsightMemoryService
|
|
25
|
+
|
|
26
|
+
memory = HindsightMemoryService.from_url(
|
|
27
|
+
hindsight_api_url="https://api.hindsight.vectorize.io",
|
|
28
|
+
api_key="hsk_...",
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
agent = LlmAgent(name="assistant", model="gemini-2.0-flash")
|
|
32
|
+
|
|
33
|
+
runner = Runner(
|
|
34
|
+
app_name="my-app",
|
|
35
|
+
agent=agent,
|
|
36
|
+
session_service=InMemorySessionService(),
|
|
37
|
+
memory_service=memory,
|
|
38
|
+
)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
When a session ends, `Runner` calls `add_session_to_memory`, which retains the session's events to a Hindsight bank keyed by `(app_name, user_id)`. When the agent (or another call) invokes `search_memory(app_name, user_id, query)`, the integration runs a Hindsight recall and returns the results as ADK `MemoryEntry` objects.
|
|
42
|
+
|
|
43
|
+
## Quick Start: Explicit Tools
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from google.adk.agents import LlmAgent
|
|
47
|
+
from hindsight_google_adk import create_hindsight_tools
|
|
48
|
+
|
|
49
|
+
tools = create_hindsight_tools(
|
|
50
|
+
bank_id="user-123",
|
|
51
|
+
hindsight_api_url="https://api.hindsight.vectorize.io",
|
|
52
|
+
api_key="hsk_...",
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
agent = LlmAgent(name="assistant", model="gemini-2.0-flash", tools=tools)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The agent now has three tools (toggle with `include_retain` / `include_recall` / `include_reflect`):
|
|
59
|
+
|
|
60
|
+
- `hindsight_retain(content)` — store information to long-term memory
|
|
61
|
+
- `hindsight_recall(query)` — search memory and return matches
|
|
62
|
+
- `hindsight_reflect(query)` — synthesize a coherent answer from memory
|
|
63
|
+
|
|
64
|
+
## Global Configuration
|
|
65
|
+
|
|
66
|
+
For shared defaults, call `configure(...)` once at startup:
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
from hindsight_google_adk import configure
|
|
70
|
+
|
|
71
|
+
configure(
|
|
72
|
+
hindsight_api_url="https://api.hindsight.vectorize.io",
|
|
73
|
+
api_key=None, # falls back to HINDSIGHT_API_KEY env var
|
|
74
|
+
bank_id_template="{app_name}::{user_id}",
|
|
75
|
+
budget="mid",
|
|
76
|
+
max_tokens=4096,
|
|
77
|
+
)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Subsequent `HindsightMemoryService.from_url()` and `create_hindsight_tools()` calls use the global config as a fallback.
|
|
81
|
+
|
|
82
|
+
## Bank ID Derivation
|
|
83
|
+
|
|
84
|
+
By default, each `(app_name, user_id)` pair gets its own bank: `"{app_name}::{user_id}"`. Override with `bank_id_template`:
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
# Per-user bank shared across apps
|
|
88
|
+
HindsightMemoryService.from_url(..., bank_id_template="user::{user_id}")
|
|
89
|
+
|
|
90
|
+
# Static bank shared across all users
|
|
91
|
+
HindsightMemoryService.from_url(..., bank_id_template="my-shared-bank")
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Configuration Reference
|
|
95
|
+
|
|
96
|
+
| Argument | Default | Description |
|
|
97
|
+
|---|---|---|
|
|
98
|
+
| `hindsight_api_url` | `https://api.hindsight.vectorize.io` | Hindsight API URL (Cloud by default). |
|
|
99
|
+
| `api_key` | `HINDSIGHT_API_KEY` env | Bearer token for Hindsight Cloud. |
|
|
100
|
+
| `bank_id_template` | `"{app_name}::{user_id}"` | Format string for deriving the bank id. |
|
|
101
|
+
| `budget` | `"mid"` | Recall budget: `low`/`mid`/`high`. |
|
|
102
|
+
| `max_tokens` | `4096` | Max tokens for recall results. |
|
|
103
|
+
| `tags` | `None` | Extra tags added to retains. `app:` and `user:` are always added. |
|
|
104
|
+
| `recall_tags` | `None` | Extra tags appended to recall queries. `user:` is always added. |
|
|
105
|
+
| `recall_tags_match` | `"any"` | Tag match mode: `any` / `all` / `any_strict` / `all_strict`. |
|
|
106
|
+
| `mission` | `None` | If set, the bank is created (idempotent) on first use with this fact-extraction mission. |
|
|
107
|
+
| `context` | `"google-adk"` | Provenance label attached to retained content. |
|
|
108
|
+
|
|
109
|
+
## Memory Scoping with Tags
|
|
110
|
+
|
|
111
|
+
Each retained session/event carries `app:<app_name>` and `user:<user_id>` tags. Recall queries automatically include `user:<user_id>` so users never see each other's memories. Pass `tags=[...]` to extend the retain set or `recall_tags=[...]` to filter recall further.
|
|
112
|
+
|
|
113
|
+
## Connection Modes
|
|
114
|
+
|
|
115
|
+
### Hindsight Cloud (recommended)
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
HindsightMemoryService.from_url(
|
|
119
|
+
hindsight_api_url="https://api.hindsight.vectorize.io",
|
|
120
|
+
api_key="hsk_...",
|
|
121
|
+
)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Self-hosted
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
HindsightMemoryService.from_url(hindsight_api_url="http://localhost:8888")
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Error Handling
|
|
131
|
+
|
|
132
|
+
All `add_*` and `search_memory` methods are resilient: Hindsight failures are logged but never propagate to the `Runner`. The explicit tools raise `HindsightError` on failure so the agent can react.
|
|
133
|
+
|
|
134
|
+
## Requirements
|
|
135
|
+
|
|
136
|
+
- Python 3.10+
|
|
137
|
+
- `google-adk>=2.0`
|
|
138
|
+
- `hindsight-client>=0.4.0`
|
|
139
|
+
|
|
140
|
+
## License
|
|
141
|
+
|
|
142
|
+
MIT
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Hindsight memory integration for Google ADK agents.
|
|
2
|
+
|
|
3
|
+
Provides two complementary patterns:
|
|
4
|
+
|
|
5
|
+
- **Automatic memory** (``HindsightMemoryService``):
|
|
6
|
+
Implements ADK's ``BaseMemoryService``. Pass an instance to
|
|
7
|
+
``Runner(memory_service=...)`` and sessions are retained on completion,
|
|
8
|
+
with ``search_memory`` queries served from Hindsight.
|
|
9
|
+
|
|
10
|
+
- **Explicit tools** (``create_hindsight_tools``):
|
|
11
|
+
ADK ``FunctionTool`` wrappers for retain / recall / reflect, so agents can
|
|
12
|
+
call Hindsight directly from inside a turn.
|
|
13
|
+
|
|
14
|
+
Usage::
|
|
15
|
+
|
|
16
|
+
from hindsight_google_adk import HindsightMemoryService, create_hindsight_tools
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from .config import (
|
|
20
|
+
HindsightAdkConfig,
|
|
21
|
+
configure,
|
|
22
|
+
get_config,
|
|
23
|
+
reset_config,
|
|
24
|
+
)
|
|
25
|
+
from .errors import HindsightError
|
|
26
|
+
from .memory import HindsightMemoryService
|
|
27
|
+
from .tools import create_hindsight_tools
|
|
28
|
+
|
|
29
|
+
__version__ = "0.1.0"
|
|
30
|
+
|
|
31
|
+
__all__ = [
|
|
32
|
+
"configure",
|
|
33
|
+
"get_config",
|
|
34
|
+
"reset_config",
|
|
35
|
+
"HindsightAdkConfig",
|
|
36
|
+
"HindsightError",
|
|
37
|
+
"HindsightMemoryService",
|
|
38
|
+
"create_hindsight_tools",
|
|
39
|
+
]
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Shared Hindsight client resolution logic."""
|
|
2
|
+
|
|
3
|
+
from importlib import metadata
|
|
4
|
+
from typing import Any, Optional
|
|
5
|
+
|
|
6
|
+
from hindsight_client import Hindsight
|
|
7
|
+
|
|
8
|
+
from .config import get_config
|
|
9
|
+
from .errors import HindsightError
|
|
10
|
+
|
|
11
|
+
try:
|
|
12
|
+
_VERSION = metadata.version("hindsight-google-adk")
|
|
13
|
+
except metadata.PackageNotFoundError:
|
|
14
|
+
_VERSION = "0.0.0"
|
|
15
|
+
_USER_AGENT = f"hindsight-google-adk/{_VERSION}"
|
|
16
|
+
|
|
17
|
+
# Per-operation timeouts (seconds)
|
|
18
|
+
TIMEOUT_RETAIN = 15.0
|
|
19
|
+
TIMEOUT_RECALL = 10.0
|
|
20
|
+
TIMEOUT_REFLECT = 30.0
|
|
21
|
+
TIMEOUT_BANK = 15.0
|
|
22
|
+
TIMEOUT_DEFAULT = 30.0
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def resolve_client(
|
|
26
|
+
client: Optional[Hindsight],
|
|
27
|
+
hindsight_api_url: Optional[str],
|
|
28
|
+
api_key: Optional[str],
|
|
29
|
+
) -> Hindsight:
|
|
30
|
+
"""Resolve a Hindsight client from explicit args or global config."""
|
|
31
|
+
if client is not None:
|
|
32
|
+
return client
|
|
33
|
+
|
|
34
|
+
config = get_config()
|
|
35
|
+
url = hindsight_api_url or (config.hindsight_api_url if config else None)
|
|
36
|
+
key = api_key or (config.api_key if config else None)
|
|
37
|
+
|
|
38
|
+
if url is None:
|
|
39
|
+
raise HindsightError(
|
|
40
|
+
"No Hindsight API URL configured. Pass client= or hindsight_api_url=, or call configure() first."
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
kwargs: dict[str, Any] = {"base_url": url, "timeout": TIMEOUT_DEFAULT, "user_agent": _USER_AGENT}
|
|
44
|
+
if key:
|
|
45
|
+
kwargs["api_key"] = key
|
|
46
|
+
return Hindsight(**kwargs)
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"""Global configuration for Hindsight-Google-ADK integration."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
DEFAULT_HINDSIGHT_API_URL = "https://api.hindsight.vectorize.io"
|
|
8
|
+
HINDSIGHT_API_KEY_ENV = "HINDSIGHT_API_KEY"
|
|
9
|
+
DEFAULT_BANK_ID_TEMPLATE = "{app_name}::{user_id}"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class HindsightAdkConfig:
|
|
14
|
+
"""Connection and default settings for the Google ADK integration.
|
|
15
|
+
|
|
16
|
+
Attributes:
|
|
17
|
+
hindsight_api_url: URL of the Hindsight API server.
|
|
18
|
+
api_key: API key for Hindsight authentication.
|
|
19
|
+
budget: Default recall budget level (low/mid/high).
|
|
20
|
+
max_tokens: Default maximum tokens for recall results.
|
|
21
|
+
tags: Default tags applied when storing memories.
|
|
22
|
+
recall_tags: Default tags to filter when searching memories.
|
|
23
|
+
recall_tags_match: Tag matching mode (any/all/any_strict/all_strict).
|
|
24
|
+
context: Source label for retain operations (default: "google-adk").
|
|
25
|
+
mission: Bank mission for fact extraction context.
|
|
26
|
+
bank_id_template: Format string used to derive a bank id from
|
|
27
|
+
``app_name`` and ``user_id`` (default: ``"{app_name}::{user_id}"``).
|
|
28
|
+
verbose: Enable verbose logging.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
hindsight_api_url: str = DEFAULT_HINDSIGHT_API_URL
|
|
32
|
+
api_key: Optional[str] = None
|
|
33
|
+
budget: str = "mid"
|
|
34
|
+
max_tokens: int = 4096
|
|
35
|
+
tags: Optional[list[str]] = None
|
|
36
|
+
recall_tags: Optional[list[str]] = None
|
|
37
|
+
recall_tags_match: str = "any"
|
|
38
|
+
context: str = "google-adk"
|
|
39
|
+
mission: Optional[str] = None
|
|
40
|
+
bank_id_template: str = DEFAULT_BANK_ID_TEMPLATE
|
|
41
|
+
verbose: bool = False
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
_global_config: Optional[HindsightAdkConfig] = None
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def configure(
|
|
48
|
+
hindsight_api_url: Optional[str] = None,
|
|
49
|
+
api_key: Optional[str] = None,
|
|
50
|
+
budget: str = "mid",
|
|
51
|
+
max_tokens: int = 4096,
|
|
52
|
+
tags: Optional[list[str]] = None,
|
|
53
|
+
recall_tags: Optional[list[str]] = None,
|
|
54
|
+
recall_tags_match: str = "any",
|
|
55
|
+
context: str = "google-adk",
|
|
56
|
+
mission: Optional[str] = None,
|
|
57
|
+
bank_id_template: str = DEFAULT_BANK_ID_TEMPLATE,
|
|
58
|
+
verbose: bool = False,
|
|
59
|
+
) -> HindsightAdkConfig:
|
|
60
|
+
"""Configure Hindsight connection and default settings.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
hindsight_api_url: Hindsight API URL (default: production cloud).
|
|
64
|
+
api_key: API key. Falls back to ``HINDSIGHT_API_KEY`` env var.
|
|
65
|
+
budget: Default recall budget (low/mid/high).
|
|
66
|
+
max_tokens: Default max tokens for recall results.
|
|
67
|
+
tags: Default tags for retain operations.
|
|
68
|
+
recall_tags: Default tags to filter recall/search.
|
|
69
|
+
recall_tags_match: Tag matching mode.
|
|
70
|
+
context: Source label for retain operations.
|
|
71
|
+
mission: Bank mission for fact extraction context.
|
|
72
|
+
bank_id_template: Format string for deriving bank ids from
|
|
73
|
+
``app_name`` and ``user_id``.
|
|
74
|
+
verbose: Enable verbose logging.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
The configured ``HindsightAdkConfig``.
|
|
78
|
+
"""
|
|
79
|
+
global _global_config
|
|
80
|
+
|
|
81
|
+
resolved_url = hindsight_api_url or DEFAULT_HINDSIGHT_API_URL
|
|
82
|
+
resolved_key = api_key or os.environ.get(HINDSIGHT_API_KEY_ENV)
|
|
83
|
+
|
|
84
|
+
_global_config = HindsightAdkConfig(
|
|
85
|
+
hindsight_api_url=resolved_url,
|
|
86
|
+
api_key=resolved_key,
|
|
87
|
+
budget=budget,
|
|
88
|
+
max_tokens=max_tokens,
|
|
89
|
+
tags=tags,
|
|
90
|
+
recall_tags=recall_tags,
|
|
91
|
+
recall_tags_match=recall_tags_match,
|
|
92
|
+
context=context,
|
|
93
|
+
mission=mission,
|
|
94
|
+
bank_id_template=bank_id_template,
|
|
95
|
+
verbose=verbose,
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
return _global_config
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def get_config() -> Optional[HindsightAdkConfig]:
|
|
102
|
+
"""Get the current global configuration."""
|
|
103
|
+
return _global_config
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def reset_config() -> None:
|
|
107
|
+
"""Reset global configuration to None."""
|
|
108
|
+
global _global_config
|
|
109
|
+
_global_config = None
|