dasein-core 0.2.5__tar.gz → 0.2.6__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.
Files changed (29) hide show
  1. {dasein_core-0.2.5/src/dasein_core.egg-info → dasein_core-0.2.6}/PKG-INFO +1 -1
  2. {dasein_core-0.2.5 → dasein_core-0.2.6}/examples/dasein_examples.ipynb +502 -502
  3. {dasein_core-0.2.5 → dasein_core-0.2.6}/pyproject.toml +1 -1
  4. {dasein_core-0.2.5 → dasein_core-0.2.6}/src/dasein/api.py +77 -1
  5. {dasein_core-0.2.5 → dasein_core-0.2.6}/src/dasein/services/post_run_client.py +2 -0
  6. {dasein_core-0.2.5 → dasein_core-0.2.6}/src/dasein/services/service_adapter.py +3 -2
  7. {dasein_core-0.2.5 → dasein_core-0.2.6/src/dasein_core.egg-info}/PKG-INFO +1 -1
  8. {dasein_core-0.2.5 → dasein_core-0.2.6}/LICENSE +0 -0
  9. {dasein_core-0.2.5 → dasein_core-0.2.6}/MANIFEST.in +0 -0
  10. {dasein_core-0.2.5 → dasein_core-0.2.6}/README.md +0 -0
  11. {dasein_core-0.2.5 → dasein_core-0.2.6}/setup.cfg +0 -0
  12. {dasein_core-0.2.5 → dasein_core-0.2.6}/setup.py +0 -0
  13. {dasein_core-0.2.5 → dasein_core-0.2.6}/src/dasein/__init__.py +0 -0
  14. {dasein_core-0.2.5 → dasein_core-0.2.6}/src/dasein/advice_format.py +0 -0
  15. {dasein_core-0.2.5 → dasein_core-0.2.6}/src/dasein/capture.py +0 -0
  16. {dasein_core-0.2.5 → dasein_core-0.2.6}/src/dasein/config.py +0 -0
  17. {dasein_core-0.2.5 → dasein_core-0.2.6}/src/dasein/events.py +0 -0
  18. {dasein_core-0.2.5 → dasein_core-0.2.6}/src/dasein/extractors.py +0 -0
  19. {dasein_core-0.2.5 → dasein_core-0.2.6}/src/dasein/injection_strategies.py +0 -0
  20. {dasein_core-0.2.5 → dasein_core-0.2.6}/src/dasein/injector.py +0 -0
  21. {dasein_core-0.2.5 → dasein_core-0.2.6}/src/dasein/services/__init__.py +0 -0
  22. {dasein_core-0.2.5 → dasein_core-0.2.6}/src/dasein/services/pre_run_client.py +0 -0
  23. {dasein_core-0.2.5 → dasein_core-0.2.6}/src/dasein/services/service_config.py +0 -0
  24. {dasein_core-0.2.5 → dasein_core-0.2.6}/src/dasein/trace_buffer.py +0 -0
  25. {dasein_core-0.2.5 → dasein_core-0.2.6}/src/dasein/types.py +0 -0
  26. {dasein_core-0.2.5 → dasein_core-0.2.6}/src/dasein_core.egg-info/SOURCES.txt +0 -0
  27. {dasein_core-0.2.5 → dasein_core-0.2.6}/src/dasein_core.egg-info/dependency_links.txt +0 -0
  28. {dasein_core-0.2.5 → dasein_core-0.2.6}/src/dasein_core.egg-info/requires.txt +0 -0
  29. {dasein_core-0.2.5 → dasein_core-0.2.6}/src/dasein_core.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dasein-core
3
- Version: 0.2.5
3
+ Version: 0.2.6
4
4
  Summary: Universal memory for agentic AI. Attach a brain to any LangChain/LangGraph agent in a single line.
5
5
  Author-email: Dasein Team <support@dasein.ai>
6
6
  License: MIT
@@ -1,502 +1,502 @@
1
- {
2
- "cells": [
3
- {
4
- "cell_type": "markdown",
5
- "metadata": {},
6
- "source": [
7
- "# 🧠 Dasein Examples: Universal Memory for Agentic AI\n",
8
- "\n",
9
- "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/nickswami/dasein-core/blob/main/examples/dasein_examples.ipynb)\n",
10
- "\n",
11
- "This notebook demonstrates **Dasein** - a universal memory system that learns from your agent's execution history and automatically improves performance, reduces costs, and increases reliability.\n",
12
- "\n",
13
- "## What You'll Learn\n",
14
- "\n",
15
- "1. **SQL Agent** - Learn query patterns for database interactions\n",
16
- "2. **Browser Agent** - Learn web scraping and navigation strategies\n",
17
- "3. **Deep Research Agent** - Optimize multi-agent research workflows\n",
18
- "\n",
19
- "## Key Features\n",
20
- "\n",
21
- "- ✨ **Zero-friction integration** - Wrap any agent in one line\n",
22
- "- 🧠 **Automatic learning** - Agents learn from successes and failures\n",
23
- "- 📊 **Performance tracking** - See token usage, timing, and improvement metrics\n",
24
- "- 🔄 **Retry logic** - Intelligent retry with learned optimizations\n",
25
- "- ☁️ **Cloud-powered** - Distributed rule synthesis and storage\n"
26
- ]
27
- },
28
- {
29
- "cell_type": "markdown",
30
- "metadata": {},
31
- "source": [
32
- "## Installation\n"
33
- ]
34
- },
35
- {
36
- "cell_type": "code",
37
- "execution_count": null,
38
- "metadata": {},
39
- "outputs": [],
40
- "source": [
41
- "# Install Dasein and dependencies\n",
42
- "!pip install -q dasein-core\n",
43
- "\n",
44
- "# For browser agent example (Use Case 2)\n",
45
- "!pip install -q playwright\n",
46
- "!playwright install chromium\n",
47
- "\n",
48
- "# For deep research agent (Use Case 3)\n",
49
- "!pip install -q git+https://github.com/langchain-ai/open_deep_research.git\n"
50
- ]
51
- },
52
- {
53
- "cell_type": "markdown",
54
- "metadata": {},
55
- "source": [
56
- "## Setup API Keys\n",
57
- "\n",
58
- "Replace the placeholders below with your actual API keys:\n",
59
- "\n",
60
- "- **GOOGLE_API_KEY**: Get from [Google AI Studio](https://makersuite.google.com/app/apikey)\n",
61
- "- **TAVILY_API_KEY**: Get from [Tavily](https://tavily.com) (free tier available, 1000 searches/month)\n"
62
- ]
63
- },
64
- {
65
- "cell_type": "code",
66
- "execution_count": null,
67
- "metadata": {},
68
- "outputs": [],
69
- "source": [
70
- "import os\n",
71
- "\n",
72
- "# ⚠️ REPLACE THESE WITH YOUR ACTUAL API KEYS\n",
73
- "os.environ[\"GOOGLE_API_KEY\"] = \"YOUR_GOOGLE_API_KEY_HERE\"\n",
74
- "os.environ[\"TAVILY_API_KEY\"] = \"YOUR_TAVILY_API_KEY_HERE\" # Only needed for Use Case 3\n",
75
- "\n",
76
- "# Suppress warnings\n",
77
- "os.environ[\"GOOGLE_CLOUD_DISABLE_DIRECT_PATH\"] = \"true\"\n",
78
- "\n",
79
- "print(\"✅ API keys configured\")\n",
80
- "print(\"\\n⚠️ Note: You may see dependency warnings in Colab - these are safe to ignore.\")\n",
81
- "print(\"⚠️ Note: Brief timeout warnings on first run are normal (cold start) - services will activate automatically.\")\n"
82
- ]
83
- },
84
- {
85
- "cell_type": "markdown",
86
- "metadata": {},
87
- "source": [
88
- "---\n",
89
- "\n",
90
- "# Use Case 1: SQL Agent with Learning\n",
91
- "\n",
92
- "This example demonstrates how Dasein learns SQL query patterns and improves database agent performance.\n",
93
- "\n",
94
- "**What Happens:**\n",
95
- "1. **Baseline Run**: Agent queries the Chinook database without optimization\n",
96
- "2. **Learning**: Dasein captures the execution trace and sends it to cloud services for rule synthesis\n",
97
- "3. **Enhanced Run**: Agent runs again with learned rules injected, showing improved performance\n",
98
- "\n",
99
- "**Expected Improvements:**\n",
100
- "- 30-50% reduction in tokens used\n",
101
- "- Fewer SQL query iterations\n",
102
- "- Better query formulation\n"
103
- ]
104
- },
105
- {
106
- "cell_type": "code",
107
- "execution_count": null,
108
- "metadata": {},
109
- "outputs": [],
110
- "source": [
111
- "import urllib.request\n",
112
- "from pathlib import Path\n",
113
- "\n",
114
- "# Download Chinook sample database\n",
115
- "db_path = Path(\"chinook.db\")\n",
116
- "if not db_path.exists():\n",
117
- " print(\"Downloading Chinook database...\")\n",
118
- " urllib.request.urlretrieve(\n",
119
- " \"https://raw.githubusercontent.com/lerocha/chinook-database/master/ChinookDatabase/DataSources/Chinook_Sqlite.sqlite\",\n",
120
- " str(db_path)\n",
121
- " )\n",
122
- " print(\"✅ Database downloaded\")\n",
123
- "else:\n",
124
- " print(\"✅ Database already exists\")\n"
125
- ]
126
- },
127
- {
128
- "cell_type": "code",
129
- "execution_count": null,
130
- "metadata": {},
131
- "outputs": [],
132
- "source": [
133
- "from langchain_community.utilities import SQLDatabase\n",
134
- "from langchain_community.agent_toolkits import SQLDatabaseToolkit\n",
135
- "from langchain_community.agent_toolkits.sql.base import create_sql_agent\n",
136
- "from langchain_google_genai import ChatGoogleGenerativeAI\n",
137
- "from dasein import cognate\n",
138
- "\n",
139
- "# Set up SQL agent\n",
140
- "print(\"Setting up SQL agent...\")\n",
141
- "db = SQLDatabase.from_uri(f\"sqlite:///{db_path}\")\n",
142
- "llm = ChatGoogleGenerativeAI(model=\"gemini-2.5-flash\", temperature=0)\n",
143
- "toolkit = SQLDatabaseToolkit(db=db, llm=llm)\n",
144
- "agent = create_sql_agent(llm=llm, toolkit=toolkit, verbose=True, handle_parsing_errors=True)\n",
145
- "\n",
146
- "print(\"✅ SQL agent created\")\n"
147
- ]
148
- },
149
- {
150
- "cell_type": "code",
151
- "execution_count": null,
152
- "metadata": {},
153
- "outputs": [],
154
- "source": [
155
- "# Wrap with Dasein for automatic learning and improvement\n",
156
- "agent = cognate(\n",
157
- " agent,\n",
158
- " retry=2, # Run twice: baseline + enhanced\n",
159
- " performance_tracking=True, # Show improvement metrics\n",
160
- " verbose=False # Set to True to see rule injection details\n",
161
- ")\n",
162
- "\n",
163
- "# Run the query - Dasein handles everything automatically!\n",
164
- "query = \"Which media format accounts for the highest number of individual line-item sales?\"\n",
165
- "\n",
166
- "print(f\"\\nQuery: {query}\\n\")\n",
167
- "print(\"=\" * 70)\n",
168
- "print(\"PHASE 1: Baseline run...\")\n",
169
- "print(\"PHASE 2: Enhanced run with learned rules...\")\n",
170
- "print(\"=\" * 70)\n",
171
- "\n",
172
- "result = agent.invoke({\"input\": query})\n",
173
- "\n",
174
- "print(f\"\\n✅ Final Answer: {result.get('output', '')}\")\n",
175
- "print(\"\\n📊 Check the performance metrics above to see improvement!\")\n"
176
- ]
177
- },
178
- {
179
- "cell_type": "markdown",
180
- "metadata": {},
181
- "source": [
182
- "---\n",
183
- "\n",
184
- "# Use Case 2: Browser Agent with Learning\n",
185
- "\n",
186
- "This example demonstrates how Dasein learns web scraping and navigation patterns.\n",
187
- "\n",
188
- "**What Happens:**\n",
189
- "1. **Baseline Run**: Browser agent navigates to a website without optimization\n",
190
- "2. **Learning**: Dasein learns which tools to use, navigation patterns, and element selection strategies\n",
191
- "3. **Enhanced Run**: Agent runs again with learned rules, showing faster and more efficient browsing\n",
192
- "\n",
193
- "**Expected Improvements:**\n",
194
- "- Fewer navigation steps\n",
195
- "- Better tool selection\n",
196
- "- More efficient element targeting\n",
197
- "- Reduced token usage\n"
198
- ]
199
- },
200
- {
201
- "cell_type": "code",
202
- "execution_count": null,
203
- "metadata": {},
204
- "outputs": [],
205
- "source": [
206
- "from langchain_community.agent_toolkits import PlayWrightBrowserToolkit\n",
207
- "from langchain_google_genai import ChatGoogleGenerativeAI\n",
208
- "from langgraph.prebuilt import create_react_agent\n",
209
- "from dasein import cognate\n",
210
- "import asyncio\n",
211
- "from playwright.async_api import async_playwright\n",
212
- "\n",
213
- "async def create_browser_agent():\n",
214
- " \"\"\"Create a Playwright browser agent.\"\"\"\n",
215
- " print(\"Setting up Playwright browser agent...\")\n",
216
- " \n",
217
- " # Create browser\n",
218
- " playwright = await async_playwright().start()\n",
219
- " async_browser = await playwright.chromium.launch(headless=True)\n",
220
- " \n",
221
- " # Create toolkit and tools\n",
222
- " toolkit = PlayWrightBrowserToolkit.from_browser(async_browser=async_browser)\n",
223
- " tools = toolkit.get_tools()\n",
224
- " \n",
225
- " print(f\"Available browser tools: {[tool.name for tool in tools]}\")\n",
226
- " \n",
227
- " # Create LLM\n",
228
- " llm = ChatGoogleGenerativeAI(\n",
229
- " model=\"gemini-2.5-flash\",\n",
230
- " temperature=0,\n",
231
- " request_timeout=180,\n",
232
- " max_retries=2\n",
233
- " )\n",
234
- " \n",
235
- " # Create agent\n",
236
- " agent_chain = create_react_agent(model=llm, tools=tools)\n",
237
- " agent_chain = agent_chain.with_config({\"recursion_limit\": 75})\n",
238
- " agent_chain.llm = llm # Add LLM reference for Dasein\n",
239
- " \n",
240
- " print(\"✅ Browser agent created\")\n",
241
- " return agent_chain\n",
242
- "\n",
243
- "# Create the agent\n",
244
- "browser_agent = await create_browser_agent()\n"
245
- ]
246
- },
247
- {
248
- "cell_type": "code",
249
- "execution_count": null,
250
- "metadata": {},
251
- "outputs": [],
252
- "source": [
253
- "# Wrap with Dasein\n",
254
- "browser_agent = cognate(\n",
255
- " browser_agent,\n",
256
- " retry=2,\n",
257
- " performance_tracking=True,\n",
258
- " verbose=False # Set to True to see rule injection details\n",
259
- ")\n",
260
- "\n",
261
- "# Test query\n",
262
- "query = \"Go to https://python.langchain.com and find if there's a tutorial on creating a browsing agent.\"\n",
263
- "\n",
264
- "print(f\"\\nQuery: {query}\\n\")\n",
265
- "print(\"=\" * 70)\n",
266
- "print(\"PHASE 1: Baseline run...\")\n",
267
- "print(\"PHASE 2: Enhanced run with learned rules...\")\n",
268
- "print(\"=\" * 70)\n",
269
- "\n",
270
- "result = await browser_agent.ainvoke({\"messages\": [(\"user\", query)]})\n",
271
- "\n",
272
- "print(f\"\\n✅ Final Answer: {result}\")\n",
273
- "print(\"\\n📊 Check the performance metrics above to see improvement!\")\n"
274
- ]
275
- },
276
- {
277
- "cell_type": "markdown",
278
- "metadata": {},
279
- "source": [
280
- "---\n",
281
- "\n",
282
- "# Use Case 3: Deep Research Agent with Learning\n",
283
- "\n",
284
- "This example demonstrates Dasein with LangChain's **Open Deep Research Agent** - a complex multi-agent system that orchestrates research tasks.\n",
285
- "\n",
286
- "**What Happens:**\n",
287
- "1. **Baseline Run**: Multi-agent research system runs without optimization\n",
288
- " - Supervisor delegates to sub-agents\n",
289
- " - Parallel research with Tavily search\n",
290
- " - Context accumulation and synthesis\n",
291
- " - Typically uses 15x more tokens than normal chat!\n",
292
- "\n",
293
- "2. **Learning**: Dasein learns:\n",
294
- " - Better search query formulation\n",
295
- " - Context filtering to reduce token bloat\n",
296
- " - Improved delegation strategies\n",
297
- " - Efficient tool usage patterns\n",
298
- "\n",
299
- "3. **Enhanced Run**: Agent runs with learned rules\n",
300
- "\n",
301
- "**Expected Improvements:**\n",
302
- "- 20-40% reduction in tokens used\n",
303
- "- Fewer redundant searches\n",
304
- "- Better query formulation\n",
305
- "- Faster convergence to quality results\n",
306
- "\n",
307
- "**Requirements:**\n",
308
- "- TAVILY_API_KEY (free tier: 1000 searches/month)\n"
309
- ]
310
- },
311
- {
312
- "cell_type": "code",
313
- "execution_count": null,
314
- "metadata": {},
315
- "outputs": [],
316
- "source": [
317
- "# Critical fix: Force LangChain to use Google GenAI instead of Vertex AI\n",
318
- "from langchain.chat_models import base as chat_models_base\n",
319
- "from langchain_google_genai import ChatGoogleGenerativeAI\n",
320
- "\n",
321
- "original_init_helper = chat_models_base._init_chat_model_helper\n",
322
- "_model_cache = {}\n",
323
- "_patch_logged = set()\n",
324
- "\n",
325
- "def patched_init_helper(*args, **kwargs):\n",
326
- " \"\"\"Force gemini models to use ChatGoogleGenerativeAI.\"\"\"\n",
327
- " model = kwargs.get('model', '')\n",
328
- " if not model and args:\n",
329
- " model = args[0] if len(args) > 0 and isinstance(args[0], str) else ''\n",
330
- " \n",
331
- " if model and 'gemini' in model.lower():\n",
332
- " if model not in _patch_logged:\n",
333
- " print(f\"🔧 Using ChatGoogleGenerativeAI for {model}\")\n",
334
- " _patch_logged.add(model)\n",
335
- " \n",
336
- " if model not in _model_cache:\n",
337
- " _model_cache[model] = ChatGoogleGenerativeAI(model=model)\n",
338
- " return _model_cache[model]\n",
339
- " return original_init_helper(*args, **kwargs)\n",
340
- "\n",
341
- "chat_models_base._init_chat_model_helper = patched_init_helper\n",
342
- "print(\"✅ Patched LangChain to use Google GenAI\")\n"
343
- ]
344
- },
345
- {
346
- "cell_type": "code",
347
- "execution_count": null,
348
- "metadata": {},
349
- "outputs": [],
350
- "source": [
351
- "from open_deep_research.deep_researcher import deep_researcher_builder\n",
352
- "from open_deep_research.configuration import Configuration\n",
353
- "from dasein import cognate\n",
354
- "import asyncio\n",
355
- "\n",
356
- "async def create_research_agent():\n",
357
- " \"\"\"Create Open Deep Research agent.\"\"\"\n",
358
- " print(\"Setting up Open Deep Research Agent...\")\n",
359
- " print(\"Source: https://github.com/langchain-ai/open_deep_research\\n\")\n",
360
- " \n",
361
- " # Configure with Gemini models and Tavily search\n",
362
- " config = Configuration(\n",
363
- " summarization_model=\"gemini-2.5-flash\",\n",
364
- " research_model=\"gemini-2.5-flash\",\n",
365
- " compression_model=\"gemini-2.5-flash\",\n",
366
- " final_report_model=\"gemini-2.5-flash\",\n",
367
- " allow_clarification=False,\n",
368
- " max_concurrent_research_units=2,\n",
369
- " max_researcher_iterations=4,\n",
370
- " max_react_tool_calls=8,\n",
371
- " )\n",
372
- " \n",
373
- " print(\"Configuration:\")\n",
374
- " print(f\" - Models: {config.research_model}\")\n",
375
- " print(f\" - Search API: Tavily\")\n",
376
- " print(f\" - Max concurrent researchers: {config.max_concurrent_research_units}\\n\")\n",
377
- " \n",
378
- " # Create the deep researcher graph\n",
379
- " graph = deep_researcher_builder.compile()\n",
380
- " \n",
381
- " print(\"✅ Research agent created\\n\")\n",
382
- " print(\"Graph structure:\")\n",
383
- " print(\" 1. Brief Generation\")\n",
384
- " print(\" 2. Research Supervisor\")\n",
385
- " print(\" 3. Research Sub-Agents (parallel)\")\n",
386
- " print(\" 4. Report Writing\\n\")\n",
387
- " \n",
388
- " # Add LLM reference for Dasein\n",
389
- " graph.llm = ChatGoogleGenerativeAI(model=\"gemini-2.5-flash\", temperature=0)\n",
390
- " \n",
391
- " return graph\n",
392
- "\n",
393
- "# Create the research agent\n",
394
- "research_agent = await create_research_agent()\n"
395
- ]
396
- },
397
- {
398
- "cell_type": "code",
399
- "execution_count": null,
400
- "metadata": {},
401
- "outputs": [],
402
- "source": [
403
- "# Wrap with Dasein\n",
404
- "research_agent = cognate(\n",
405
- " research_agent,\n",
406
- " retry=2,\n",
407
- " performance_tracking=True,\n",
408
- " verbose=False # Set to True to see rule injection details\n",
409
- ")\n",
410
- "\n",
411
- "# Research query\n",
412
- "query = \"\"\"Research and compare LangChain vs LlamaIndex for building LLM applications.\n",
413
- "\n",
414
- "I want to understand:\n",
415
- "1. Their core philosophies and approaches\n",
416
- "2. Key features and strengths\n",
417
- "3. Which use cases each is best suited for\n",
418
- "\n",
419
- "Provide a concise comparison with sources.\"\"\"\n",
420
- "\n",
421
- "print(f\"Research Query: {query}\\n\")\n",
422
- "print(\"=\" * 70)\n",
423
- "print(\"This will trigger:\")\n",
424
- "print(\" - Supervisor creating 2 sub-agents (one per framework)\")\n",
425
- "print(\" - Parallel research with Tavily search\")\n",
426
- "print(\" - Multiple search rounds per sub-agent\")\n",
427
- "print(\" - Synthesis and report writing\\n\")\n",
428
- "print(\"PHASE 1: Baseline run...\")\n",
429
- "print(\"PHASE 2: Enhanced run with learned rules...\")\n",
430
- "print(\"=\" * 70)\n",
431
- "\n",
432
- "result = await research_agent.ainvoke(\n",
433
- " {\"messages\": [(\"user\", query)]},\n",
434
- " config={\n",
435
- " \"configurable\": {\n",
436
- " \"allow_clarification\": False,\n",
437
- " \"summarization_model\": \"gemini-2.5-flash\",\n",
438
- " \"research_model\": \"gemini-2.5-flash\",\n",
439
- " }\n",
440
- " }\n",
441
- ")\n",
442
- "\n",
443
- "# Display report (truncated for readability)\n",
444
- "report = str(result.get('report', result))\n",
445
- "if len(report) > 500:\n",
446
- " print(f\"\\n✅ Research Report (truncated):\\n{report[:500]}...\\n[{len(report)} total chars]\")\n",
447
- "else:\n",
448
- " print(f\"\\n✅ Research Report:\\n{report}\")\n",
449
- "\n",
450
- "print(\"\\n📊 Check the performance metrics above to see massive token savings!\")\n"
451
- ]
452
- },
453
- {
454
- "cell_type": "markdown",
455
- "metadata": {},
456
- "source": [
457
- "---\n",
458
- "\n",
459
- "## Summary\n",
460
- "\n",
461
- "You've just seen **Dasein** in action across three different agent types:\n",
462
- "\n",
463
- "1. **SQL Agent** - Learned query optimization patterns\n",
464
- "2. **Browser Agent** - Learned navigation and tool usage strategies\n",
465
- "3. **Deep Research Agent** - Learned to optimize complex multi-agent workflows\n",
466
- "\n",
467
- "### Key Takeaways\n",
468
- "\n",
469
- "- ✨ **One-line integration**: `cognate(agent)` is all you need\n",
470
- "- 🧠 **Automatic learning**: Agents improve themselves without manual rule engineering\n",
471
- "- 📊 **Transparent metrics**: See exactly how much you're improving\n",
472
- "- ☁️ **Cloud-powered**: Rules are stored and synthesized using distributed services\n",
473
- "- 🔄 **Intelligent retry**: `retry=2` automatically runs baseline + enhanced\n",
474
- "\n",
475
- "### Next Steps\n",
476
- "\n",
477
- "1. **Try your own agents** - Dasein works with any LangChain/LangGraph agent\n",
478
- "2. **Customize optimization** - Use the `weights` parameter to optimize for what matters to you\n",
479
- "3. **Build rule libraries** - Run multiple times to accumulate learned rules\n",
480
- "4. **Scale up** - The more you use Dasein, the smarter your agents become\n",
481
- "\n",
482
- "### Resources\n",
483
- "\n",
484
- "- 📖 [Documentation](https://github.com/nickswami/dasein-core#readme)\n",
485
- "- 💻 [GitHub](https://github.com/nickswami/dasein-core)\n",
486
- "- 💬 [Discord Community](https://discord.gg/dasein)\n",
487
- "- 🐛 [Report Issues](https://github.com/nickswami/dasein-core/issues)\n",
488
- "\n",
489
- "---\n",
490
- "\n",
491
- "**Built with ❤️ for the agentic AI community**\n"
492
- ]
493
- }
494
- ],
495
- "metadata": {
496
- "language_info": {
497
- "name": "python"
498
- }
499
- },
500
- "nbformat": 4,
501
- "nbformat_minor": 2
502
- }
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {},
6
+ "source": [
7
+ "# 🧠 Dasein Examples: Universal Memory for Agentic AI\n",
8
+ "\n",
9
+ "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/nickswami/dasein-core/blob/main/examples/dasein_examples.ipynb)\n",
10
+ "\n",
11
+ "This notebook demonstrates **Dasein** - a universal memory system that learns from your agent's execution history and automatically improves performance, reduces costs, and increases reliability.\n",
12
+ "\n",
13
+ "## What You'll Learn\n",
14
+ "\n",
15
+ "1. **SQL Agent** - Learn query patterns for database interactions\n",
16
+ "2. **Browser Agent** - Learn web scraping and navigation strategies\n",
17
+ "3. **Deep Research Agent** - Optimize multi-agent research workflows\n",
18
+ "\n",
19
+ "## Key Features\n",
20
+ "\n",
21
+ "- ✨ **Zero-friction integration** - Wrap any agent in one line\n",
22
+ "- 🧠 **Automatic learning** - Agents learn from successes and failures\n",
23
+ "- 📊 **Performance tracking** - See token usage, timing, and improvement metrics\n",
24
+ "- 🔄 **Retry logic** - Intelligent retry with learned optimizations\n",
25
+ "- ☁️ **Cloud-powered** - Distributed rule synthesis and storage\n"
26
+ ]
27
+ },
28
+ {
29
+ "cell_type": "markdown",
30
+ "metadata": {},
31
+ "source": [
32
+ "## Installation\n"
33
+ ]
34
+ },
35
+ {
36
+ "cell_type": "code",
37
+ "execution_count": null,
38
+ "metadata": {},
39
+ "outputs": [],
40
+ "source": [
41
+ "# Install Dasein and dependencies\n",
42
+ "!pip install -q dasein-core\n",
43
+ "\n",
44
+ "# For browser agent example (Use Case 2)\n",
45
+ "!pip install -q playwright\n",
46
+ "!playwright install chromium\n",
47
+ "\n",
48
+ "# For deep research agent (Use Case 3)\n",
49
+ "!pip install -q git+https://github.com/langchain-ai/open_deep_research.git\n"
50
+ ]
51
+ },
52
+ {
53
+ "cell_type": "markdown",
54
+ "metadata": {},
55
+ "source": [
56
+ "## Setup API Keys\n",
57
+ "\n",
58
+ "Replace the placeholders below with your actual API keys:\n",
59
+ "\n",
60
+ "- **GOOGLE_API_KEY**: Get from [Google AI Studio](https://makersuite.google.com/app/apikey)\n",
61
+ "- **TAVILY_API_KEY**: Get from [Tavily](https://tavily.com) (free tier available, 1000 searches/month)\n"
62
+ ]
63
+ },
64
+ {
65
+ "cell_type": "code",
66
+ "execution_count": null,
67
+ "metadata": {},
68
+ "outputs": [],
69
+ "source": [
70
+ "import os\n",
71
+ "\n",
72
+ "# ⚠️ REPLACE THESE WITH YOUR ACTUAL API KEYS\n",
73
+ "os.environ[\"GOOGLE_API_KEY\"] = \"YOUR_GOOGLE_API_KEY_HERE\"\n",
74
+ "os.environ[\"TAVILY_API_KEY\"] = \"YOUR_TAVILY_API_KEY_HERE\" # Only needed for Use Case 3\n",
75
+ "\n",
76
+ "# Suppress warnings\n",
77
+ "os.environ[\"GOOGLE_CLOUD_DISABLE_DIRECT_PATH\"] = \"true\"\n",
78
+ "\n",
79
+ "print(\"✅ API keys configured\")\n",
80
+ "print(\"\\n⚠️ Note: You may see dependency warnings in Colab - these are safe to ignore.\")\n",
81
+ "print(\"⚠️ Note: Brief timeout warnings on first run are normal (cold start) - services will activate automatically.\")\n"
82
+ ]
83
+ },
84
+ {
85
+ "cell_type": "markdown",
86
+ "metadata": {},
87
+ "source": [
88
+ "---\n",
89
+ "\n",
90
+ "# Use Case 1: SQL Agent with Learning\n",
91
+ "\n",
92
+ "This example demonstrates how Dasein learns SQL query patterns and improves database agent performance.\n",
93
+ "\n",
94
+ "**What Happens:**\n",
95
+ "1. **Baseline Run**: Agent queries the Chinook database without optimization\n",
96
+ "2. **Learning**: Dasein captures the execution trace and sends it to cloud services for rule synthesis\n",
97
+ "3. **Enhanced Run**: Agent runs again with learned rules injected, showing improved performance\n",
98
+ "\n",
99
+ "**Expected Improvements:**\n",
100
+ "- 30-50% reduction in tokens used\n",
101
+ "- Fewer SQL query iterations\n",
102
+ "- Better query formulation\n"
103
+ ]
104
+ },
105
+ {
106
+ "cell_type": "code",
107
+ "execution_count": null,
108
+ "metadata": {},
109
+ "outputs": [],
110
+ "source": [
111
+ "import urllib.request\n",
112
+ "from pathlib import Path\n",
113
+ "\n",
114
+ "# Download Chinook sample database\n",
115
+ "db_path = Path(\"chinook.db\")\n",
116
+ "if not db_path.exists():\n",
117
+ " print(\"Downloading Chinook database...\")\n",
118
+ " urllib.request.urlretrieve(\n",
119
+ " \"https://raw.githubusercontent.com/lerocha/chinook-database/master/ChinookDatabase/DataSources/Chinook_Sqlite.sqlite\",\n",
120
+ " str(db_path)\n",
121
+ " )\n",
122
+ " print(\"✅ Database downloaded\")\n",
123
+ "else:\n",
124
+ " print(\"✅ Database already exists\")\n"
125
+ ]
126
+ },
127
+ {
128
+ "cell_type": "code",
129
+ "execution_count": null,
130
+ "metadata": {},
131
+ "outputs": [],
132
+ "source": [
133
+ "from langchain_community.utilities import SQLDatabase\n",
134
+ "from langchain_community.agent_toolkits import SQLDatabaseToolkit\n",
135
+ "from langchain_community.agent_toolkits.sql.base import create_sql_agent\n",
136
+ "from langchain_google_genai import ChatGoogleGenerativeAI\n",
137
+ "from dasein import cognate\n",
138
+ "\n",
139
+ "# Set up SQL agent\n",
140
+ "print(\"Setting up SQL agent...\")\n",
141
+ "db = SQLDatabase.from_uri(f\"sqlite:///{db_path}\")\n",
142
+ "llm = ChatGoogleGenerativeAI(model=\"gemini-2.5-flash\", temperature=0)\n",
143
+ "toolkit = SQLDatabaseToolkit(db=db, llm=llm)\n",
144
+ "agent = create_sql_agent(llm=llm, toolkit=toolkit, verbose=True, handle_parsing_errors=True)\n",
145
+ "\n",
146
+ "print(\"✅ SQL agent created\")\n"
147
+ ]
148
+ },
149
+ {
150
+ "cell_type": "code",
151
+ "execution_count": null,
152
+ "metadata": {},
153
+ "outputs": [],
154
+ "source": [
155
+ "# Wrap with Dasein for automatic learning and improvement\n",
156
+ "agent = cognate(\n",
157
+ " agent,\n",
158
+ " retry=2, # Run twice: baseline + enhanced\n",
159
+ " performance_tracking=True, # Show improvement metrics\n",
160
+ " verbose=False # Set to True to see rule injection details\n",
161
+ ")\n",
162
+ "\n",
163
+ "# Run the query - Dasein handles everything automatically!\n",
164
+ "query = \"Which media format accounts for the highest number of individual line-item sales?\"\n",
165
+ "\n",
166
+ "print(f\"\\nQuery: {query}\\n\")\n",
167
+ "print(\"=\" * 70)\n",
168
+ "print(\"PHASE 1: Baseline run...\")\n",
169
+ "print(\"PHASE 2: Enhanced run with learned rules...\")\n",
170
+ "print(\"=\" * 70)\n",
171
+ "\n",
172
+ "result = agent.invoke({\"input\": query})\n",
173
+ "\n",
174
+ "print(f\"\\n✅ Final Answer: {result.get('output', '')}\")\n",
175
+ "print(\"\\n📊 Check the performance metrics above to see improvement!\")\n"
176
+ ]
177
+ },
178
+ {
179
+ "cell_type": "markdown",
180
+ "metadata": {},
181
+ "source": [
182
+ "---\n",
183
+ "\n",
184
+ "# Use Case 2: Browser Agent with Learning\n",
185
+ "\n",
186
+ "This example demonstrates how Dasein learns web scraping and navigation patterns.\n",
187
+ "\n",
188
+ "**What Happens:**\n",
189
+ "1. **Baseline Run**: Browser agent navigates to a website without optimization\n",
190
+ "2. **Learning**: Dasein learns which tools to use, navigation patterns, and element selection strategies\n",
191
+ "3. **Enhanced Run**: Agent runs again with learned rules, showing faster and more efficient browsing\n",
192
+ "\n",
193
+ "**Expected Improvements:**\n",
194
+ "- Fewer navigation steps\n",
195
+ "- Better tool selection\n",
196
+ "- More efficient element targeting\n",
197
+ "- Reduced token usage\n"
198
+ ]
199
+ },
200
+ {
201
+ "cell_type": "code",
202
+ "execution_count": null,
203
+ "metadata": {},
204
+ "outputs": [],
205
+ "source": [
206
+ "from langchain_community.agent_toolkits import PlayWrightBrowserToolkit\n",
207
+ "from langchain_google_genai import ChatGoogleGenerativeAI\n",
208
+ "from langgraph.prebuilt import create_react_agent\n",
209
+ "from dasein import cognate\n",
210
+ "import asyncio\n",
211
+ "from playwright.async_api import async_playwright\n",
212
+ "\n",
213
+ "async def create_browser_agent():\n",
214
+ " \"\"\"Create a Playwright browser agent.\"\"\"\n",
215
+ " print(\"Setting up Playwright browser agent...\")\n",
216
+ " \n",
217
+ " # Create browser\n",
218
+ " playwright = await async_playwright().start()\n",
219
+ " async_browser = await playwright.chromium.launch(headless=True)\n",
220
+ " \n",
221
+ " # Create toolkit and tools\n",
222
+ " toolkit = PlayWrightBrowserToolkit.from_browser(async_browser=async_browser)\n",
223
+ " tools = toolkit.get_tools()\n",
224
+ " \n",
225
+ " print(f\"Available browser tools: {[tool.name for tool in tools]}\")\n",
226
+ " \n",
227
+ " # Create LLM\n",
228
+ " llm = ChatGoogleGenerativeAI(\n",
229
+ " model=\"gemini-2.5-flash\",\n",
230
+ " temperature=0,\n",
231
+ " request_timeout=180,\n",
232
+ " max_retries=2\n",
233
+ " )\n",
234
+ " \n",
235
+ " # Create agent\n",
236
+ " agent_chain = create_react_agent(model=llm, tools=tools)\n",
237
+ " agent_chain = agent_chain.with_config({\"recursion_limit\": 75})\n",
238
+ " agent_chain.llm = llm # Add LLM reference for Dasein\n",
239
+ " \n",
240
+ " print(\"✅ Browser agent created\")\n",
241
+ " return agent_chain\n",
242
+ "\n",
243
+ "# Create the agent\n",
244
+ "browser_agent = await create_browser_agent()\n"
245
+ ]
246
+ },
247
+ {
248
+ "cell_type": "code",
249
+ "execution_count": null,
250
+ "metadata": {},
251
+ "outputs": [],
252
+ "source": [
253
+ "# Wrap with Dasein\n",
254
+ "browser_agent = cognate(\n",
255
+ " browser_agent,\n",
256
+ " retry=2,\n",
257
+ " performance_tracking=True,\n",
258
+ " verbose=False # Set to True to see rule injection details\n",
259
+ ")\n",
260
+ "\n",
261
+ "# Test query\n",
262
+ "query = \"Go to the LangChain site (https://python.langchain.com). Is there a tutorial on how to create a browsing agent? If so where is it?\"\n",
263
+ "\n",
264
+ "print(f\"\\nQuery: {query}\\n\")\n",
265
+ "print(\"=\" * 70)\n",
266
+ "print(\"PHASE 1: Baseline run...\")\n",
267
+ "print(\"PHASE 2: Enhanced run with learned rules...\")\n",
268
+ "print(\"=\" * 70)\n",
269
+ "\n",
270
+ "result = await browser_agent.ainvoke({\"messages\": [(\"user\", query)]})\n",
271
+ "\n",
272
+ "print(f\"\\n✅ Final Answer: {result}\")\n",
273
+ "print(\"\\n📊 Check the performance metrics above to see improvement!\")\n"
274
+ ]
275
+ },
276
+ {
277
+ "cell_type": "markdown",
278
+ "metadata": {},
279
+ "source": [
280
+ "---\n",
281
+ "\n",
282
+ "# Use Case 3: Deep Research Agent with Learning\n",
283
+ "\n",
284
+ "This example demonstrates Dasein with LangChain's **Open Deep Research Agent** - a complex multi-agent system that orchestrates research tasks.\n",
285
+ "\n",
286
+ "**What Happens:**\n",
287
+ "1. **Baseline Run**: Multi-agent research system runs without optimization\n",
288
+ " - Supervisor delegates to sub-agents\n",
289
+ " - Parallel research with Tavily search\n",
290
+ " - Context accumulation and synthesis\n",
291
+ " - Typically uses 15x more tokens than normal chat!\n",
292
+ "\n",
293
+ "2. **Learning**: Dasein learns:\n",
294
+ " - Better search query formulation\n",
295
+ " - Context filtering to reduce token bloat\n",
296
+ " - Improved delegation strategies\n",
297
+ " - Efficient tool usage patterns\n",
298
+ "\n",
299
+ "3. **Enhanced Run**: Agent runs with learned rules\n",
300
+ "\n",
301
+ "**Expected Improvements:**\n",
302
+ "- 20-40% reduction in tokens used\n",
303
+ "- Fewer redundant searches\n",
304
+ "- Better query formulation\n",
305
+ "- Faster convergence to quality results\n",
306
+ "\n",
307
+ "**Requirements:**\n",
308
+ "- TAVILY_API_KEY (free tier: 1000 searches/month)\n"
309
+ ]
310
+ },
311
+ {
312
+ "cell_type": "code",
313
+ "execution_count": null,
314
+ "metadata": {},
315
+ "outputs": [],
316
+ "source": [
317
+ "# Critical fix: Force LangChain to use Google GenAI instead of Vertex AI\n",
318
+ "from langchain.chat_models import base as chat_models_base\n",
319
+ "from langchain_google_genai import ChatGoogleGenerativeAI\n",
320
+ "\n",
321
+ "original_init_helper = chat_models_base._init_chat_model_helper\n",
322
+ "_model_cache = {}\n",
323
+ "_patch_logged = set()\n",
324
+ "\n",
325
+ "def patched_init_helper(*args, **kwargs):\n",
326
+ " \"\"\"Force gemini models to use ChatGoogleGenerativeAI.\"\"\"\n",
327
+ " model = kwargs.get('model', '')\n",
328
+ " if not model and args:\n",
329
+ " model = args[0] if len(args) > 0 and isinstance(args[0], str) else ''\n",
330
+ " \n",
331
+ " if model and 'gemini' in model.lower():\n",
332
+ " if model not in _patch_logged:\n",
333
+ " print(f\"🔧 Using ChatGoogleGenerativeAI for {model}\")\n",
334
+ " _patch_logged.add(model)\n",
335
+ " \n",
336
+ " if model not in _model_cache:\n",
337
+ " _model_cache[model] = ChatGoogleGenerativeAI(model=model)\n",
338
+ " return _model_cache[model]\n",
339
+ " return original_init_helper(*args, **kwargs)\n",
340
+ "\n",
341
+ "chat_models_base._init_chat_model_helper = patched_init_helper\n",
342
+ "print(\"✅ Patched LangChain to use Google GenAI\")\n"
343
+ ]
344
+ },
345
+ {
346
+ "cell_type": "code",
347
+ "execution_count": null,
348
+ "metadata": {},
349
+ "outputs": [],
350
+ "source": [
351
+ "from open_deep_research.deep_researcher import deep_researcher_builder\n",
352
+ "from open_deep_research.configuration import Configuration\n",
353
+ "from dasein import cognate\n",
354
+ "import asyncio\n",
355
+ "\n",
356
+ "async def create_research_agent():\n",
357
+ " \"\"\"Create Open Deep Research agent.\"\"\"\n",
358
+ " print(\"Setting up Open Deep Research Agent...\")\n",
359
+ " print(\"Source: https://github.com/langchain-ai/open_deep_research\\n\")\n",
360
+ " \n",
361
+ " # Configure with Gemini models and Tavily search\n",
362
+ " config = Configuration(\n",
363
+ " summarization_model=\"gemini-2.5-flash\",\n",
364
+ " research_model=\"gemini-2.5-flash\",\n",
365
+ " compression_model=\"gemini-2.5-flash\",\n",
366
+ " final_report_model=\"gemini-2.5-flash\",\n",
367
+ " allow_clarification=False,\n",
368
+ " max_concurrent_research_units=2,\n",
369
+ " max_researcher_iterations=4,\n",
370
+ " max_react_tool_calls=8,\n",
371
+ " )\n",
372
+ " \n",
373
+ " print(\"Configuration:\")\n",
374
+ " print(f\" - Models: {config.research_model}\")\n",
375
+ " print(f\" - Search API: Tavily\")\n",
376
+ " print(f\" - Max concurrent researchers: {config.max_concurrent_research_units}\\n\")\n",
377
+ " \n",
378
+ " # Create the deep researcher graph\n",
379
+ " graph = deep_researcher_builder.compile()\n",
380
+ " \n",
381
+ " print(\"✅ Research agent created\\n\")\n",
382
+ " print(\"Graph structure:\")\n",
383
+ " print(\" 1. Brief Generation\")\n",
384
+ " print(\" 2. Research Supervisor\")\n",
385
+ " print(\" 3. Research Sub-Agents (parallel)\")\n",
386
+ " print(\" 4. Report Writing\\n\")\n",
387
+ " \n",
388
+ " # Add LLM reference for Dasein\n",
389
+ " graph.llm = ChatGoogleGenerativeAI(model=\"gemini-2.5-flash\", temperature=0)\n",
390
+ " \n",
391
+ " return graph\n",
392
+ "\n",
393
+ "# Create the research agent\n",
394
+ "research_agent = await create_research_agent()\n"
395
+ ]
396
+ },
397
+ {
398
+ "cell_type": "code",
399
+ "execution_count": null,
400
+ "metadata": {},
401
+ "outputs": [],
402
+ "source": [
403
+ "# Wrap with Dasein\n",
404
+ "research_agent = cognate(\n",
405
+ " research_agent,\n",
406
+ " retry=2,\n",
407
+ " performance_tracking=True,\n",
408
+ " verbose=False # Set to True to see rule injection details\n",
409
+ ")\n",
410
+ "\n",
411
+ "# Research query\n",
412
+ "query = \"\"\"Research and compare LangChain vs LlamaIndex for building LLM applications.\n",
413
+ "\n",
414
+ "I want to understand:\n",
415
+ "1. Their core philosophies and approaches\n",
416
+ "2. Key features and strengths\n",
417
+ "3. Which use cases each is best suited for\n",
418
+ "\n",
419
+ "Provide a concise comparison with sources.\"\"\"\n",
420
+ "\n",
421
+ "print(f\"Research Query: {query}\\n\")\n",
422
+ "print(\"=\" * 70)\n",
423
+ "print(\"This will trigger:\")\n",
424
+ "print(\" - Supervisor creating 2 sub-agents (one per framework)\")\n",
425
+ "print(\" - Parallel research with Tavily search\")\n",
426
+ "print(\" - Multiple search rounds per sub-agent\")\n",
427
+ "print(\" - Synthesis and report writing\\n\")\n",
428
+ "print(\"PHASE 1: Baseline run...\")\n",
429
+ "print(\"PHASE 2: Enhanced run with learned rules...\")\n",
430
+ "print(\"=\" * 70)\n",
431
+ "\n",
432
+ "result = await research_agent.ainvoke(\n",
433
+ " {\"messages\": [(\"user\", query)]},\n",
434
+ " config={\n",
435
+ " \"configurable\": {\n",
436
+ " \"allow_clarification\": False,\n",
437
+ " \"summarization_model\": \"gemini-2.5-flash\",\n",
438
+ " \"research_model\": \"gemini-2.5-flash\",\n",
439
+ " }\n",
440
+ " }\n",
441
+ ")\n",
442
+ "\n",
443
+ "# Display report (truncated for readability)\n",
444
+ "report = str(result.get('report', result))\n",
445
+ "if len(report) > 500:\n",
446
+ " print(f\"\\n✅ Research Report (truncated):\\n{report[:500]}...\\n[{len(report)} total chars]\")\n",
447
+ "else:\n",
448
+ " print(f\"\\n✅ Research Report:\\n{report}\")\n",
449
+ "\n",
450
+ "print(\"\\n📊 Check the performance metrics above to see massive token savings!\")\n"
451
+ ]
452
+ },
453
+ {
454
+ "cell_type": "markdown",
455
+ "metadata": {},
456
+ "source": [
457
+ "---\n",
458
+ "\n",
459
+ "## Summary\n",
460
+ "\n",
461
+ "You've just seen **Dasein** in action across three different agent types:\n",
462
+ "\n",
463
+ "1. **SQL Agent** - Learned query optimization patterns\n",
464
+ "2. **Browser Agent** - Learned navigation and tool usage strategies\n",
465
+ "3. **Deep Research Agent** - Learned to optimize complex multi-agent workflows\n",
466
+ "\n",
467
+ "### Key Takeaways\n",
468
+ "\n",
469
+ "- ✨ **One-line integration**: `cognate(agent)` is all you need\n",
470
+ "- 🧠 **Automatic learning**: Agents improve themselves without manual rule engineering\n",
471
+ "- 📊 **Transparent metrics**: See exactly how much you're improving\n",
472
+ "- ☁️ **Cloud-powered**: Rules are stored and synthesized using distributed services\n",
473
+ "- 🔄 **Intelligent retry**: `retry=2` automatically runs baseline + enhanced\n",
474
+ "\n",
475
+ "### Next Steps\n",
476
+ "\n",
477
+ "1. **Try your own agents** - Dasein works with any LangChain/LangGraph agent\n",
478
+ "2. **Customize optimization** - Use the `weights` parameter to optimize for what matters to you\n",
479
+ "3. **Build rule libraries** - Run multiple times to accumulate learned rules\n",
480
+ "4. **Scale up** - The more you use Dasein, the smarter your agents become\n",
481
+ "\n",
482
+ "### Resources\n",
483
+ "\n",
484
+ "- 📖 [Documentation](https://github.com/nickswami/dasein-core#readme)\n",
485
+ "- 💻 [GitHub](https://github.com/nickswami/dasein-core)\n",
486
+ "- 💬 [Discord Community](https://discord.gg/dasein)\n",
487
+ "- 🐛 [Report Issues](https://github.com/nickswami/dasein-core/issues)\n",
488
+ "\n",
489
+ "---\n",
490
+ "\n",
491
+ "**Built with ❤️ for the agentic AI community**\n"
492
+ ]
493
+ }
494
+ ],
495
+ "metadata": {
496
+ "language_info": {
497
+ "name": "python"
498
+ }
499
+ },
500
+ "nbformat": 4,
501
+ "nbformat_minor": 2
502
+ }
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "dasein-core"
7
- version = "0.2.5"
7
+ version = "0.2.6"
8
8
  description = "Universal memory for agentic AI. Attach a brain to any LangChain/LangGraph agent in a single line."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
@@ -2825,6 +2825,81 @@ Follow these rules when planning your actions."""
2825
2825
  return getattr(agent, 'agent_id', None) or f"agent_{id(agent)}"
2826
2826
 
2827
2827
  agent_fingerprint = _minimal_agent_fingerprint(self._agent)
2828
+
2829
+ # Extract tool metadata for Stage 3.5 tool grounding
2830
+ def _extract_tool_metadata(agent):
2831
+ """
2832
+ Extract tool metadata (name, description, args_schema) from agent.
2833
+
2834
+ CRITICAL: Extracts ALL available tools from the agent, not just tools used in trace.
2835
+ Why: If agent used wrong tool (e.g., extract_text instead of get_elements),
2836
+ the trace won't show the correct tool. Stage 3.5 needs to see all options
2837
+ to suggest better alternatives.
2838
+ """
2839
+ tools_metadata = []
2840
+ tools_to_process = []
2841
+
2842
+ # Get ALL tools from agent (LangChain or LangGraph) - not filtered by trace usage
2843
+ tools_attr = getattr(agent, 'tools', None)
2844
+ if tools_attr:
2845
+ try:
2846
+ tools_to_process = list(tools_attr)
2847
+ except Exception:
2848
+ pass
2849
+ elif getattr(agent, 'toolkit', None):
2850
+ tk = getattr(agent, 'toolkit')
2851
+ tk_tools = getattr(tk, 'tools', None) or getattr(tk, 'get_tools', None)
2852
+ try:
2853
+ tools_to_process = list(tk_tools() if callable(tk_tools) else tk_tools or [])
2854
+ except Exception:
2855
+ pass
2856
+
2857
+ # Also try LangGraph tools from compiled graph
2858
+ if hasattr(agent, 'nodes') and 'tools' in agent.nodes:
2859
+ tools_node = agent.nodes['tools']
2860
+ if hasattr(tools_node, 'node') and hasattr(tools_node.node, 'steps'):
2861
+ for step in tools_node.node.steps:
2862
+ if hasattr(step, 'tools_by_name'):
2863
+ tools_to_process.extend(step.tools_by_name.values())
2864
+ break
2865
+
2866
+ # Extract metadata from each tool
2867
+ for tool in tools_to_process:
2868
+ try:
2869
+ tool_meta = {
2870
+ 'name': getattr(tool, 'name', str(tool.__class__.__name__)),
2871
+ 'description': getattr(tool, 'description', ''),
2872
+ }
2873
+
2874
+ # Extract args_schema if available
2875
+ if hasattr(tool, 'args_schema') and tool.args_schema:
2876
+ try:
2877
+ # Try Pydantic v2 method
2878
+ if hasattr(tool.args_schema, 'model_json_schema'):
2879
+ tool_meta['args_schema'] = tool.args_schema.model_json_schema()
2880
+ # Fallback to Pydantic v1 method
2881
+ elif hasattr(tool.args_schema, 'schema'):
2882
+ tool_meta['args_schema'] = tool.args_schema.schema()
2883
+ else:
2884
+ tool_meta['args_schema'] = {}
2885
+ except Exception:
2886
+ tool_meta['args_schema'] = {}
2887
+ else:
2888
+ tool_meta['args_schema'] = {}
2889
+
2890
+ tools_metadata.append(tool_meta)
2891
+ except Exception as e:
2892
+ # Skip tools that fail to extract
2893
+ pass
2894
+
2895
+ return tools_metadata
2896
+
2897
+ tools_metadata = _extract_tool_metadata(self._agent)
2898
+ print(f"[DASEIN] Extracted metadata for {len(tools_metadata)} tools")
2899
+ if tools_metadata:
2900
+ print(f"[DASEIN] Sample tool: {tools_metadata[0].get('name', 'unknown')}")
2901
+ else:
2902
+ print(f"[DASEIN] WARNING: No tools extracted! Agent type: {type(self._agent)}")
2828
2903
 
2829
2904
  response = self._service_adapter.synthesize_rules(
2830
2905
  run_id=None, # Will use stored run_id from pre-run phase
@@ -2839,7 +2914,8 @@ Follow these rules when planning your actions."""
2839
2914
  agent_fingerprint=agent_fingerprint, # Reuse fingerprint from pre-run (line 2613)
2840
2915
  step_id=self._current_step_id, # Pass step_id for parallel execution tracking
2841
2916
  post_run_mode=self._post_run, # Pass post_run mode ("full" or "kpi_only")
2842
- wait_for_synthesis=wait_for_synthesis # Wait for synthesis on retry runs (except last)
2917
+ wait_for_synthesis=wait_for_synthesis, # Wait for synthesis on retry runs (except last)
2918
+ tools_metadata=tools_metadata # Tool metadata for Stage 3.5 tool grounding
2843
2919
  )
2844
2920
 
2845
2921
  # response is a dict from ServiceAdapter; handle accordingly
@@ -32,6 +32,7 @@ class RuleSynthesisRequest:
32
32
  skip_synthesis: bool = False
33
33
  wait_for_synthesis: bool = False
34
34
  step_id: Optional[str] = None
35
+ tools_metadata: Optional[List[Dict[str, Any]]] = None # Tool metadata for Stage 3.5 grounding
35
36
 
36
37
 
37
38
  @dataclass
@@ -95,6 +96,7 @@ class PostRunClient:
95
96
  "performance_tracking_id": request.performance_tracking_id,
96
97
  "skip_synthesis": request.skip_synthesis,
97
98
  "wait_for_synthesis": request.wait_for_synthesis,
99
+ "tools_metadata": request.tools_metadata or [], # Tool metadata for Stage 3.5 grounding
98
100
  }
99
101
 
100
102
  logger.info(f"Synthesizing rules for run: {request.run_id}")
@@ -95,7 +95,7 @@ class ServiceAdapter:
95
95
  max_rules: Optional[int] = 5, performance_tracking_id: Optional[str] = None,
96
96
  skip_synthesis: bool = False, agent_fingerprint: Optional[str] = None,
97
97
  step_id: Optional[str] = None, post_run_mode: str = "full",
98
- wait_for_synthesis: bool = False) -> Dict[str, Any]:
98
+ wait_for_synthesis: bool = False, tools_metadata: Optional[List[Dict[str, Any]]] = None) -> Dict[str, Any]:
99
99
  """
100
100
  Synthesize rules from run telemetry (replaces local rule synthesis)
101
101
 
@@ -138,7 +138,8 @@ class ServiceAdapter:
138
138
  performance_tracking_id=performance_tracking_id,
139
139
  skip_synthesis=should_skip_synthesis,
140
140
  wait_for_synthesis=wait_for_synthesis,
141
- step_id=step_id
141
+ step_id=step_id,
142
+ tools_metadata=tools_metadata
142
143
  )
143
144
 
144
145
  response = self.post_run_client.synthesize_rules(request)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dasein-core
3
- Version: 0.2.5
3
+ Version: 0.2.6
4
4
  Summary: Universal memory for agentic AI. Attach a brain to any LangChain/LangGraph agent in a single line.
5
5
  Author-email: Dasein Team <support@dasein.ai>
6
6
  License: MIT
File without changes
File without changes
File without changes
File without changes
File without changes