dao-ai 0.1.12__tar.gz → 0.1.14__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 (304) hide show
  1. {dao_ai-0.1.12 → dao_ai-0.1.14}/PKG-INFO +4 -3
  2. {dao_ai-0.1.12 → dao_ai-0.1.14}/README.md +3 -2
  3. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/15_complete_applications/hardware_store_lakebase.yaml +3 -2
  4. {dao_ai-0.1.12 → dao_ai-0.1.14}/docs/key-capabilities.md +69 -14
  5. {dao_ai-0.1.12 → dao_ai-0.1.14}/notebooks/07_run_evaluation.py +2 -0
  6. {dao_ai-0.1.12 → dao_ai-0.1.14}/pyproject.toml +1 -1
  7. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/apps/handlers.py +22 -1
  8. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/config.py +55 -32
  9. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/tools/genie.py +72 -20
  10. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/tools/mcp.py +36 -13
  11. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/tools/slack.py +13 -2
  12. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/tools/sql.py +7 -3
  13. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/tools/unity_catalog.py +32 -10
  14. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/tools/vector_search.py +61 -35
  15. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_databricks.py +38 -40
  16. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_reranking.py +8 -5
  17. {dao_ai-0.1.12 → dao_ai-0.1.14}/.gitignore +0 -0
  18. {dao_ai-0.1.12 → dao_ai-0.1.14}/.python-version +0 -0
  19. {dao_ai-0.1.12 → dao_ai-0.1.14}/CHANGELOG.md +0 -0
  20. {dao_ai-0.1.12 → dao_ai-0.1.14}/CONTRIBUTING.md +0 -0
  21. {dao_ai-0.1.12 → dao_ai-0.1.14}/LICENSE +0 -0
  22. {dao_ai-0.1.12 → dao_ai-0.1.14}/Makefile +0 -0
  23. {dao_ai-0.1.12 → dao_ai-0.1.14}/app.yaml +0 -0
  24. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/01_getting_started/README.md +0 -0
  25. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/01_getting_started/minimal.yaml +0 -0
  26. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/02_mcp/README.md +0 -0
  27. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/02_mcp/custom_mcp.yaml +0 -0
  28. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/02_mcp/external_mcp.yaml +0 -0
  29. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/02_mcp/filtered_mcp.yaml +0 -0
  30. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/02_mcp/managed_mcp.yaml +0 -0
  31. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/02_mcp/slack_integration.yaml +0 -0
  32. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/03_reranking/README.md +0 -0
  33. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/03_reranking/vector_search_with_reranking.yaml +0 -0
  34. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/04_genie/README.md +0 -0
  35. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/04_genie/genie_basic.yaml +0 -0
  36. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/04_genie/genie_lru_cache.yaml +0 -0
  37. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/04_genie/genie_semantic_cache.yaml +0 -0
  38. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/04_genie/genie_with_conversation_id.yaml +0 -0
  39. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/05_memory/README.md +0 -0
  40. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/05_memory/conversation_summarization.yaml +0 -0
  41. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/05_memory/in_memory_basic.yaml +0 -0
  42. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/05_memory/lakebase_persistence.yaml +0 -0
  43. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/05_memory/postgres_persistence.yaml +0 -0
  44. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/06_on_behalf_of_user/README.md +0 -0
  45. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/06_on_behalf_of_user/obo_basic.yaml +0 -0
  46. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/07_human_in_the_loop/README.md +0 -0
  47. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/07_human_in_the_loop/human_in_the_loop.yaml +0 -0
  48. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/08_guardrails/README.md +0 -0
  49. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/08_guardrails/guardrails_basic.yaml +0 -0
  50. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/09_structured_output/README.md +0 -0
  51. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/09_structured_output/structured_output.yaml +0 -0
  52. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/10_agent_integrations/README.md +0 -0
  53. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/10_agent_integrations/agent_bricks.yaml +0 -0
  54. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/10_agent_integrations/kasal.yaml +0 -0
  55. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/11_prompt_engineering/README.md +0 -0
  56. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/11_prompt_engineering/prompt_optimization.yaml +0 -0
  57. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/11_prompt_engineering/prompt_registry.yaml +0 -0
  58. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/12_middleware/README.md +0 -0
  59. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/12_middleware/combined_middleware.yaml +0 -0
  60. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/12_middleware/context_management.yaml +0 -0
  61. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/12_middleware/custom_field_validation.yaml +0 -0
  62. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/12_middleware/limit_middleware.yaml +0 -0
  63. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/12_middleware/logging_middleware.yaml +0 -0
  64. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/12_middleware/pii_middleware.yaml +0 -0
  65. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/12_middleware/retry_middleware.yaml +0 -0
  66. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/12_middleware/tool_selector_middleware.yaml +0 -0
  67. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/13_orchestration/README.md +0 -0
  68. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/13_orchestration/supervisor_pattern.yaml +0 -0
  69. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/13_orchestration/swarm_pattern.yaml +0 -0
  70. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/14_basic_tools/README.md +0 -0
  71. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/14_basic_tools/sql_tool_example.yaml +0 -0
  72. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/15_complete_applications/README.md +0 -0
  73. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/15_complete_applications/brick_store.yaml +0 -0
  74. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/15_complete_applications/deep_research.yaml +0 -0
  75. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/15_complete_applications/executive_assistant.yaml +0 -0
  76. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/15_complete_applications/genie_and_genie_mcp.yaml +0 -0
  77. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/15_complete_applications/genie_vector_search_hybrid.yaml +0 -0
  78. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/15_complete_applications/hardware_store.yaml +0 -0
  79. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/15_complete_applications/hardware_store_swarm.yaml +0 -0
  80. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/15_complete_applications/quick_serve_restaurant.yaml +0 -0
  81. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/15_complete_applications/reservations_system.yaml +0 -0
  82. {dao_ai-0.1.12 → dao_ai-0.1.14}/config/examples/README.md +0 -0
  83. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/dais2025/appointments.sql +0 -0
  84. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/dais2025/appointments_data.sql +0 -0
  85. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/dais2025/brand_rep_demo_data.sql +0 -0
  86. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/dais2025/brand_rep_demo_queries.sql +0 -0
  87. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/dais2025/brand_rep_demo_tables.sql +0 -0
  88. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/dais2025/brand_rep_demo_validation.sql +0 -0
  89. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/dais2025/customers.sql +0 -0
  90. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/dais2025/customers_data.sql +0 -0
  91. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/dais2025/dim_stores.sql +0 -0
  92. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/dais2025/dim_stores_data.sql +0 -0
  93. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/dais2025/employee_performance.sql +0 -0
  94. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/dais2025/employee_performance_data.sql +0 -0
  95. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/dais2025/employee_tasks.sql +0 -0
  96. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/dais2025/employee_tasks_data.sql +0 -0
  97. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/dais2025/inventory.sql +0 -0
  98. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/dais2025/inventory_data.sql +0 -0
  99. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/dais2025/managers.sql +0 -0
  100. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/dais2025/managers_data.sql +0 -0
  101. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/dais2025/product_data.sql +0 -0
  102. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/dais2025/products.sql +0 -0
  103. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/dais2025/task_assignments.sql +0 -0
  104. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/hardware_store/inventory.snappy.parquet +0 -0
  105. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/hardware_store/inventory.sql +0 -0
  106. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/hardware_store/products.snappy.parquet +0 -0
  107. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/hardware_store/products.sql +0 -0
  108. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/quick_serve_restaurant/.gitkeep +0 -0
  109. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/quick_serve_restaurant/fulfil_item_orders.sql +0 -0
  110. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/quick_serve_restaurant/items_description.csv +0 -0
  111. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/quick_serve_restaurant/items_description.sql +0 -0
  112. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/quick_serve_restaurant/items_raw.csv +0 -0
  113. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/quick_serve_restaurant/items_raw.sql +0 -0
  114. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/quick_serve_restaurant/orders_raw.csv +0 -0
  115. {dao_ai-0.1.12 → dao_ai-0.1.14}/data/quick_serve_restaurant/orders_raw.sql +0 -0
  116. {dao_ai-0.1.12 → dao_ai-0.1.14}/databricks.yaml.template +0 -0
  117. {dao_ai-0.1.12 → dao_ai-0.1.14}/docs/architecture.md +0 -0
  118. {dao_ai-0.1.12 → dao_ai-0.1.14}/docs/cli-reference.md +0 -0
  119. {dao_ai-0.1.12 → dao_ai-0.1.14}/docs/configuration-reference.md +0 -0
  120. {dao_ai-0.1.12 → dao_ai-0.1.14}/docs/contributing.md +0 -0
  121. {dao_ai-0.1.12 → dao_ai-0.1.14}/docs/examples.md +0 -0
  122. {dao_ai-0.1.12 → dao_ai-0.1.14}/docs/faq.md +0 -0
  123. {dao_ai-0.1.12 → dao_ai-0.1.14}/docs/hardware_store/README.md +0 -0
  124. {dao_ai-0.1.12 → dao_ai-0.1.14}/docs/hardware_store/retail_supervisor.png +0 -0
  125. {dao_ai-0.1.12 → dao_ai-0.1.14}/docs/hardware_store/retail_swarm.png +0 -0
  126. {dao_ai-0.1.12 → dao_ai-0.1.14}/docs/images/genie.png +0 -0
  127. {dao_ai-0.1.12 → dao_ai-0.1.14}/docs/python-api.md +0 -0
  128. {dao_ai-0.1.12 → dao_ai-0.1.14}/docs/quick_serve_restaurant/.gitkeep +0 -0
  129. {dao_ai-0.1.12 → dao_ai-0.1.14}/docs/quick_serve_restaurant/quick-serve-restaurant.png +0 -0
  130. {dao_ai-0.1.12 → dao_ai-0.1.14}/docs/why-dao.md +0 -0
  131. {dao_ai-0.1.12 → dao_ai-0.1.14}/environment.yaml +0 -0
  132. {dao_ai-0.1.12 → dao_ai-0.1.14}/examples/dais2025/examples.yaml +0 -0
  133. {dao_ai-0.1.12 → dao_ai-0.1.14}/examples/deep_research/examples.yaml +0 -0
  134. {dao_ai-0.1.12 → dao_ai-0.1.14}/examples/executive_assistant/examples.yaml +0 -0
  135. {dao_ai-0.1.12 → dao_ai-0.1.14}/examples/hardware_store/examples.yaml +0 -0
  136. {dao_ai-0.1.12 → dao_ai-0.1.14}/examples/quick_serve_restaurant/.gitkeep +0 -0
  137. {dao_ai-0.1.12 → dao_ai-0.1.14}/examples/quick_serve_restaurant/examples.yaml +0 -0
  138. {dao_ai-0.1.12 → dao_ai-0.1.14}/functions/dais2025/extract_store_numbers.sql +0 -0
  139. {dao_ai-0.1.12 → dao_ai-0.1.14}/functions/dais2025/find_inventory_by_sku.sql +0 -0
  140. {dao_ai-0.1.12 → dao_ai-0.1.14}/functions/dais2025/find_inventory_by_upc.sql +0 -0
  141. {dao_ai-0.1.12 → dao_ai-0.1.14}/functions/dais2025/find_product_by_sku.sql +0 -0
  142. {dao_ai-0.1.12 → dao_ai-0.1.14}/functions/dais2025/find_product_by_upc.sql +0 -0
  143. {dao_ai-0.1.12 → dao_ai-0.1.14}/functions/dais2025/find_store_by_number.sql +0 -0
  144. {dao_ai-0.1.12 → dao_ai-0.1.14}/functions/dais2025/find_store_inventory_by_sku.sql +0 -0
  145. {dao_ai-0.1.12 → dao_ai-0.1.14}/functions/dais2025/find_store_inventory_by_upc.sql +0 -0
  146. {dao_ai-0.1.12 → dao_ai-0.1.14}/functions/hardware_store/find_inventory_by_sku.sql +0 -0
  147. {dao_ai-0.1.12 → dao_ai-0.1.14}/functions/hardware_store/find_inventory_by_upc.sql +0 -0
  148. {dao_ai-0.1.12 → dao_ai-0.1.14}/functions/hardware_store/find_product_by_sku.sql +0 -0
  149. {dao_ai-0.1.12 → dao_ai-0.1.14}/functions/hardware_store/find_product_by_upc.sql +0 -0
  150. {dao_ai-0.1.12 → dao_ai-0.1.14}/functions/hardware_store/find_store_inventory_by_sku.sql +0 -0
  151. {dao_ai-0.1.12 → dao_ai-0.1.14}/functions/hardware_store/find_store_inventory_by_upc.sql +0 -0
  152. {dao_ai-0.1.12 → dao_ai-0.1.14}/functions/quick_serve_restaurant/.gitkeep +0 -0
  153. {dao_ai-0.1.12 → dao_ai-0.1.14}/functions/quick_serve_restaurant/insert_coffee_order.sql +0 -0
  154. {dao_ai-0.1.12 → dao_ai-0.1.14}/functions/quick_serve_restaurant/lookup_items_by_descriptions.sql +0 -0
  155. {dao_ai-0.1.12 → dao_ai-0.1.14}/functions/quick_serve_restaurant/match_historical_item_order_by_date.sql +0 -0
  156. {dao_ai-0.1.12 → dao_ai-0.1.14}/functions/quick_serve_restaurant/match_item_by_description_and_price.sql +0 -0
  157. {dao_ai-0.1.12 → dao_ai-0.1.14}/notebooks/01_ingest_and_transform.py +0 -0
  158. {dao_ai-0.1.12 → dao_ai-0.1.14}/notebooks/02_provision_vector_search.py +0 -0
  159. {dao_ai-0.1.12 → dao_ai-0.1.14}/notebooks/03_provision_lakebase.py +0 -0
  160. {dao_ai-0.1.12 → dao_ai-0.1.14}/notebooks/04_unity_catalog_tools.py +0 -0
  161. {dao_ai-0.1.12 → dao_ai-0.1.14}/notebooks/05_deploy_agent.py +0 -0
  162. {dao_ai-0.1.12 → dao_ai-0.1.14}/notebooks/06_generate_evaluation_data.py +0 -0
  163. {dao_ai-0.1.12 → dao_ai-0.1.14}/notebooks/08_run_examples.py +0 -0
  164. {dao_ai-0.1.12 → dao_ai-0.1.14}/notebooks/09_evaluate_inferences.py +0 -0
  165. {dao_ai-0.1.12 → dao_ai-0.1.14}/notebooks/10_optimize_prompts.py +0 -0
  166. {dao_ai-0.1.12 → dao_ai-0.1.14}/notebooks/99_scratchpad.py +0 -0
  167. {dao_ai-0.1.12 → dao_ai-0.1.14}/requirements.txt +0 -0
  168. {dao_ai-0.1.12 → dao_ai-0.1.14}/schemas/bundle_config_schema.json +0 -0
  169. {dao_ai-0.1.12 → dao_ai-0.1.14}/schemas/model_config_schema.json +0 -0
  170. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dais2025/__init__.py +0 -0
  171. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dais2025/models.py +0 -0
  172. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dais2025/tools/__init__.py +0 -0
  173. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dais2025/tools/customer.py +0 -0
  174. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dais2025/tools/employee.py +0 -0
  175. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dais2025/tools/executive.py +0 -0
  176. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dais2025/tools/genie.py +0 -0
  177. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dais2025/tools/inventory.py +0 -0
  178. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dais2025/tools/models.py +0 -0
  179. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dais2025/tools/store.py +0 -0
  180. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/__init__.py +0 -0
  181. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/apps/__init__.py +0 -0
  182. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/apps/model_serving.py +0 -0
  183. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/apps/resources.py +0 -0
  184. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/apps/server.py +0 -0
  185. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/catalog.py +0 -0
  186. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/cli.py +0 -0
  187. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/genie/__init__.py +0 -0
  188. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/genie/cache/__init__.py +0 -0
  189. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/genie/cache/base.py +0 -0
  190. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/genie/cache/core.py +0 -0
  191. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/genie/cache/lru.py +0 -0
  192. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/genie/cache/semantic.py +0 -0
  193. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/genie/core.py +0 -0
  194. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/graph.py +0 -0
  195. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/hooks/__init__.py +0 -0
  196. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/hooks/core.py +0 -0
  197. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/logging.py +0 -0
  198. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/memory/__init__.py +0 -0
  199. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/memory/base.py +0 -0
  200. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/memory/core.py +0 -0
  201. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/memory/databricks.py +0 -0
  202. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/memory/postgres.py +0 -0
  203. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/messages.py +0 -0
  204. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/middleware/__init__.py +0 -0
  205. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/middleware/assertions.py +0 -0
  206. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/middleware/base.py +0 -0
  207. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/middleware/context_editing.py +0 -0
  208. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/middleware/core.py +0 -0
  209. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/middleware/guardrails.py +0 -0
  210. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/middleware/human_in_the_loop.py +0 -0
  211. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/middleware/message_validation.py +0 -0
  212. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/middleware/model_call_limit.py +0 -0
  213. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/middleware/model_retry.py +0 -0
  214. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/middleware/pii.py +0 -0
  215. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/middleware/summarization.py +0 -0
  216. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/middleware/tool_call_limit.py +0 -0
  217. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/middleware/tool_retry.py +0 -0
  218. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/middleware/tool_selector.py +0 -0
  219. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/models.py +0 -0
  220. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/nodes.py +0 -0
  221. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/optimization.py +0 -0
  222. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/orchestration/__init__.py +0 -0
  223. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/orchestration/core.py +0 -0
  224. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/orchestration/supervisor.py +0 -0
  225. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/orchestration/swarm.py +0 -0
  226. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/prompts.py +0 -0
  227. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/providers/__init__.py +0 -0
  228. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/providers/base.py +0 -0
  229. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/providers/databricks.py +0 -0
  230. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/state.py +0 -0
  231. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/tools/__init__.py +0 -0
  232. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/tools/agent.py +0 -0
  233. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/tools/core.py +0 -0
  234. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/tools/email.py +0 -0
  235. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/tools/memory.py +0 -0
  236. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/tools/python.py +0 -0
  237. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/tools/search.py +0 -0
  238. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/tools/time.py +0 -0
  239. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/types.py +0 -0
  240. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/utils.py +0 -0
  241. {dao_ai-0.1.12 → dao_ai-0.1.14}/src/dao_ai/vector_search.py +0 -0
  242. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/config/test_model_config.yaml +0 -0
  243. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/conftest.py +0 -0
  244. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/middleware/test_context_editing.py +0 -0
  245. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/middleware/test_model_call_limit.py +0 -0
  246. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/middleware/test_model_retry.py +0 -0
  247. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/middleware/test_pii.py +0 -0
  248. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/middleware/test_tool_call_limit.py +0 -0
  249. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/middleware/test_tool_retry.py +0 -0
  250. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/middleware/test_tool_selector.py +0 -0
  251. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_agent_response_format.py +0 -0
  252. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_assertions_middleware.py +0 -0
  253. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_catalog.py +0 -0
  254. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_chat_history.py +0 -0
  255. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_config.py +0 -0
  256. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_function_parsing.py +0 -0
  257. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_genie.py +0 -0
  258. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_genie_conversation_ids_in_outputs.py +0 -0
  259. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_genie_databricks_integration.py +0 -0
  260. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_genie_room_model.py +0 -0
  261. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_guardrail_retry.py +0 -0
  262. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_hitl_config_model.py +0 -0
  263. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_hitl_responses_agent.py +0 -0
  264. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_hooks.py +0 -0
  265. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_human_in_the_loop.py +0 -0
  266. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_inference.py +0 -0
  267. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_inference_integration.py +0 -0
  268. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_input_output_structure.py +0 -0
  269. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_interrupt_type.py +0 -0
  270. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_llm_interrupt_handling.py +0 -0
  271. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_mcp.py +0 -0
  272. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_mcp_filtering.py +0 -0
  273. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_mcp_filtering_integration.py +0 -0
  274. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_mcp_function_model.py +0 -0
  275. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_message_validation_middleware.py +0 -0
  276. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_messages.py +0 -0
  277. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_models.py +0 -0
  278. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_optimization.py +0 -0
  279. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_postgres_integration.py +0 -0
  280. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_prompt_optimizations.py +0 -0
  281. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_prompts.py +0 -0
  282. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_reranking_integration.py +0 -0
  283. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_resources_model_genie_integration.py +0 -0
  284. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_response_format.py +0 -0
  285. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_responses_agent_structured_output_unit.py +0 -0
  286. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_semantic_cache_context.py +0 -0
  287. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_sql_tool.py +0 -0
  288. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_sql_tool_integration.py +0 -0
  289. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_state.py +0 -0
  290. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_summarization_inference.py +0 -0
  291. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_swarm_middleware.py +0 -0
  292. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_tools.py +0 -0
  293. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_types.py +0 -0
  294. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_unity_catalog.py +0 -0
  295. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_utils.py +0 -0
  296. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_utils_type_from_fqn.py +0 -0
  297. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_vector_search.py +0 -0
  298. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/test_warehouse_model.py +0 -0
  299. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/dao_ai/weather_server_mcp.py +0 -0
  300. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/hardware_store/.gitkeep +0 -0
  301. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/hardware_store/test_graph.py +0 -0
  302. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/images/doritos_upc.png +0 -0
  303. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/images/lays_upc.png +0 -0
  304. {dao_ai-0.1.12 → dao_ai-0.1.14}/tests/quick_serve_restaurant/.gitkeep +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dao-ai
3
- Version: 0.1.12
3
+ Version: 0.1.14
4
4
  Summary: DAO AI: A modular, multi-agent orchestration framework for complex AI workflows. Supports agent handoff, tool integration, and dynamic configuration via YAML.
5
5
  Project-URL: Homepage, https://github.com/natefleming/dao-ai
6
6
  Project-URL: Documentation, https://natefleming.github.io/dao-ai
@@ -125,7 +125,7 @@ DAO AI Builder generates valid YAML configurations that work seamlessly with thi
125
125
  - **[Architecture](docs/architecture.md)** - Understand how DAO works under the hood
126
126
 
127
127
  ### Core Concepts
128
- - **[Key Capabilities](docs/key-capabilities.md)** - Explore 14 powerful features for production agents
128
+ - **[Key Capabilities](docs/key-capabilities.md)** - Explore 15 powerful features for production agents
129
129
  - **[Configuration Reference](docs/configuration-reference.md)** - Complete YAML configuration guide
130
130
  - **[Examples](docs/examples.md)** - Ready-to-use example configurations
131
131
 
@@ -148,7 +148,7 @@ Before you begin, you'll need:
148
148
  - **Python 3.11 or newer** installed on your computer ([download here](https://www.python.org/downloads/))
149
149
  - **A Databricks workspace** (ask your IT team or see [Databricks docs](https://docs.databricks.com/))
150
150
  - Access to **Unity Catalog** (your organization's data catalog)
151
- - **Model Serving** enabled (for deploying AI agents)
151
+ - **Model Serving** or **Databricks Apps** enabled (for deploying AI agents)
152
152
  - *Optional*: Vector Search, Genie (for advanced features)
153
153
 
154
154
  **Not sure if you have access?** Your Databricks administrator can grant you permissions.
@@ -345,6 +345,7 @@ DAO provides powerful capabilities for building production-ready AI agents:
345
345
 
346
346
  | Feature | Description |
347
347
  |---------|-------------|
348
+ | **Dual Deployment Targets** | Deploy to Databricks Model Serving or Databricks Apps with a single config |
348
349
  | **Multi-Tool Support** | Python functions, Unity Catalog, MCP, Agent Endpoints |
349
350
  | **On-Behalf-Of User** | Per-user permissions and governance |
350
351
  | **Advanced Caching** | Two-tier (LRU + Semantic) caching for cost optimization |
@@ -46,7 +46,7 @@ DAO AI Builder generates valid YAML configurations that work seamlessly with thi
46
46
  - **[Architecture](docs/architecture.md)** - Understand how DAO works under the hood
47
47
 
48
48
  ### Core Concepts
49
- - **[Key Capabilities](docs/key-capabilities.md)** - Explore 14 powerful features for production agents
49
+ - **[Key Capabilities](docs/key-capabilities.md)** - Explore 15 powerful features for production agents
50
50
  - **[Configuration Reference](docs/configuration-reference.md)** - Complete YAML configuration guide
51
51
  - **[Examples](docs/examples.md)** - Ready-to-use example configurations
52
52
 
@@ -69,7 +69,7 @@ Before you begin, you'll need:
69
69
  - **Python 3.11 or newer** installed on your computer ([download here](https://www.python.org/downloads/))
70
70
  - **A Databricks workspace** (ask your IT team or see [Databricks docs](https://docs.databricks.com/))
71
71
  - Access to **Unity Catalog** (your organization's data catalog)
72
- - **Model Serving** enabled (for deploying AI agents)
72
+ - **Model Serving** or **Databricks Apps** enabled (for deploying AI agents)
73
73
  - *Optional*: Vector Search, Genie (for advanced features)
74
74
 
75
75
  **Not sure if you have access?** Your Databricks administrator can grant you permissions.
@@ -266,6 +266,7 @@ DAO provides powerful capabilities for building production-ready AI agents:
266
266
 
267
267
  | Feature | Description |
268
268
  |---------|-------------|
269
+ | **Dual Deployment Targets** | Deploy to Databricks Model Serving or Databricks Apps with a single config |
269
270
  | **Multi-Tool Support** | Python functions, Unity Catalog, MCP, Agent Endpoints |
270
271
  | **On-Behalf-Of User** | Per-user permissions and governance |
271
272
  | **Advanced Caching** | Two-tier (LRU + Semantic) caching for cost optimization |
@@ -15,14 +15,15 @@
15
15
  variables:
16
16
  client_id: &client_id
17
17
  options:
18
- - env: RETAIL_AI_DATABRICKS_CLIENT_ID # Service principal client ID
19
18
  - scope: retail_consumer_goods
20
19
  secret: RETAIL_AI_DATABRICKS_CLIENT_ID
20
+ - env: RETAIL_AI_DATABRICKS_CLIENT_ID # Service principal client ID
21
+
21
22
  client_secret: &client_secret
22
23
  options:
23
- - env: RETAIL_AI_DATABRICKS_CLIENT_SECRET # Service principal secret
24
24
  - scope: retail_consumer_goods
25
25
  secret: RETAIL_AI_DATABRICKS_CLIENT_SECRET
26
+ - env: RETAIL_AI_DATABRICKS_CLIENT_SECRET # Service principal secret
26
27
 
27
28
  schemas:
28
29
  retail_schema: &retail_schema
@@ -2,7 +2,62 @@
2
2
 
3
3
  These are the powerful features that make DAO production-ready. Don't worry if some seem complex — you can start simple and add these capabilities as you need them.
4
4
 
5
- ## 1. Multi-Tool Support
5
+ ## 1. Dual Deployment Targets
6
+
7
+ **What is this?** DAO agents can be deployed to either **Databricks Model Serving** or **Databricks Apps** using the same configuration, giving you flexibility in how you expose your agent.
8
+
9
+ **Why this matters:**
10
+ - **Model Serving**: Traditional endpoint for inference workloads, autoscaling, pay-per-token pricing
11
+ - **Databricks Apps**: Full web applications with custom UI, background jobs, and richer integrations
12
+ - **Single Configuration**: Switch deployment targets with one line change — no code rewrite needed
13
+ - **Environment Consistency**: Same YAML config works in both environments
14
+
15
+ **Comparison:**
16
+
17
+ | Feature | Model Serving | Databricks Apps |
18
+ |---------|--------------|-----------------|
19
+ | **Use Case** | Inference API endpoint | Full web application |
20
+ | **Scaling** | Auto-scales based on load | Manual scaling configuration |
21
+ | **UI** | API only | Custom web UI possible |
22
+ | **Pricing** | Pay per token/request | Compute-based |
23
+ | **Deployment Speed** | ~2-5 minutes | ~2-5 minutes |
24
+ | **Best For** | API integrations, high throughput | Interactive apps, custom UX |
25
+
26
+ **How to configure:**
27
+
28
+ ```yaml
29
+ app:
30
+ name: my_agent
31
+ deployment_target: model_serving # or 'apps'
32
+
33
+ # Model Serving specific options (only used when deployment_target: model_serving)
34
+ endpoint_name: my_agent_endpoint
35
+ workload_size: Small
36
+ scale_to_zero: true
37
+
38
+ agents:
39
+ - *my_agent
40
+ ```
41
+
42
+ **Deploy to Model Serving:**
43
+ ```bash
44
+ dao-ai deploy -c config.yaml --target model_serving
45
+ ```
46
+
47
+ **Deploy to Databricks Apps:**
48
+ ```bash
49
+ dao-ai deploy -c config.yaml --target apps
50
+ ```
51
+
52
+ **CLI override:** The `--target` flag always takes precedence over the YAML config, making it easy to deploy the same config to different environments.
53
+
54
+ **Behind the scenes:**
55
+ - Model Serving deployments create an MLflow model and serving endpoint
56
+ - Apps deployments create a Databricks App with MLflow experiment tracking
57
+ - Both share the same agent code, tools, and orchestration logic
58
+ - Environment variables and secrets are automatically configured for each platform
59
+
60
+ ## 2. Multi-Tool Support
6
61
 
7
62
  **What are tools?** Tools are actions an agent can perform — like querying a database, calling an API, or running custom code.
8
63
 
@@ -57,7 +112,7 @@ tools:
57
112
  connection: *github_connection
58
113
  ```
59
114
 
60
- ## 2. On-Behalf-Of User Support
115
+ ## 3. On-Behalf-Of User Support
61
116
 
62
117
  **What is this?** Many Databricks resources (like SQL warehouses, Genie spaces, and LLMs) can operate "on behalf of" the end user, using their permissions instead of the agent's service account credentials.
63
118
 
@@ -104,7 +159,7 @@ The same agent code enforces different permissions for each user automatically.
104
159
  - The user must have the necessary permissions on the underlying resources
105
160
  - Not all Databricks resources support on-behalf-of functionality
106
161
 
107
- ## 3. Advanced Caching (Genie Queries)
162
+ ## 4. Advanced Caching (Genie Queries)
108
163
 
109
164
  **Why caching matters:** When users ask similar questions repeatedly, you don't want to pay for the same AI processing over and over. Caching stores results so you can reuse them.
110
165
 
@@ -234,7 +289,7 @@ This works by embedding both the current question *and* recent conversation turn
234
289
 
235
290
  For more details on semantic cache configuration, see [docs/semantic_cache_weight_configuration.md](semantic_cache_weight_configuration.md).
236
291
 
237
- ## 4. Vector Search Reranking
292
+ ## 5. Vector Search Reranking
238
293
 
239
294
  **The problem:** Vector search (semantic similarity) is fast but sometimes returns loosely related results. It's like a librarian who quickly grabs 50 books that *might* be relevant.
240
295
 
@@ -321,7 +376,7 @@ rerank:
321
376
 
322
377
  **Note:** Model weights are downloaded automatically on first use (~34MB for MiniLM-L-12-v2).
323
378
 
324
- ## 5. Human-in-the-Loop Approvals
379
+ ## 6. Human-in-the-Loop Approvals
325
380
 
326
381
  **Why this matters:** Some actions are too important to automate completely. For example, you might want human approval before an agent:
327
382
  - Deletes data
@@ -343,7 +398,7 @@ tools:
343
398
  review_prompt: "This operation will modify production data. Approve?"
344
399
  ```
345
400
 
346
- ## 6. Memory & State Persistence
401
+ ## 7. Memory & State Persistence
347
402
 
348
403
  **What is memory?** Your agent needs to remember past conversations. When a user asks "What about size XL?" the agent should remember they were talking about shirts.
349
404
 
@@ -395,7 +450,7 @@ memory:
395
450
  - **PostgreSQL**: When you need external database features or already have PostgreSQL infrastructure
396
451
  - **Lakebase**: When you want Databricks-native persistence with Unity Catalog governance
397
452
 
398
- ## 7. MLflow Prompt Registry Integration
453
+ ## 8. MLflow Prompt Registry Integration
399
454
 
400
455
  **The problem:** Prompts (instructions you give to AI models) need constant refinement. Hardcoding them in YAML means every change requires redeployment.
401
456
 
@@ -427,7 +482,7 @@ agents:
427
482
  prompt: *product_expert_prompt # Loaded from MLflow registry
428
483
  ```
429
484
 
430
- ## 8. Automated Prompt Optimization
485
+ ## 9. Automated Prompt Optimization
431
486
 
432
487
  **What is this?** Instead of manually tweaking prompts through trial and error, DAO can automatically test variations and find the best one.
433
488
 
@@ -452,7 +507,7 @@ optimizations:
452
507
  num_candidates: 5
453
508
  ```
454
509
 
455
- ## 9. Guardrails & Response Quality Middleware
510
+ ## 10. Guardrails & Response Quality Middleware
456
511
 
457
512
  **What are guardrails?** Safety and quality controls that validate agent responses before they reach users. Think of them as quality assurance checkpoints.
458
513
 
@@ -670,7 +725,7 @@ agents:
670
725
  prompt: *professional_tone_prompt
671
726
  ```
672
727
 
673
- ## 10. Conversation Summarization
728
+ ## 11. Conversation Summarization
674
729
 
675
730
  **The problem:** AI models have a maximum amount of text they can process (the "context window"). Long conversations eventually exceed this limit.
676
731
 
@@ -697,7 +752,7 @@ The `LoggingSummarizationMiddleware` provides detailed observability:
697
752
  INFO | Summarization: BEFORE 25 messages (~12500 tokens) → AFTER 3 messages (~2100 tokens) | Reduced by ~10400 tokens
698
753
  ```
699
754
 
700
- ## 11. Structured Output (Response Format)
755
+ ## 12. Structured Output (Response Format)
701
756
 
702
757
  **What is this?** A way to force your agent to return data in a specific JSON structure, making responses machine-readable and predictable.
703
758
 
@@ -749,7 +804,7 @@ See `config/examples/09_structured_output/structured_output.yaml` for a complete
749
804
 
750
805
  ---
751
806
 
752
- ## 12. Custom Input & Custom Output Support
807
+ ## 13. Custom Input & Custom Output Support
753
808
 
754
809
  **What is this?** A flexible system for passing custom configuration values to your agents and receiving enriched output with runtime state.
755
810
 
@@ -829,7 +884,7 @@ When invoked with the `custom_inputs` above, the prompt automatically populates:
829
884
  - `session` state is automatically maintained and returned in `custom_outputs`
830
885
  - Backward compatible with legacy flat custom_inputs format
831
886
 
832
- ## 13. Middleware (Input Validation, Logging, Monitoring)
887
+ ## 14. Middleware (Input Validation, Logging, Monitoring)
833
888
 
834
889
  **What is middleware?** Middleware are functions that wrap around agent execution to add cross-cutting concerns like validation, logging, authentication, and monitoring. They run before and after the agent processes requests.
835
890
 
@@ -1049,7 +1104,7 @@ agents:
1049
1104
 
1050
1105
  ---
1051
1106
 
1052
- ## 14. Hook System
1107
+ ## 15. Hook System
1053
1108
 
1054
1109
  **What are hooks?** Hooks let you run custom code at specific moments in your agent's lifecycle — like "before starting" or "when shutting down".
1055
1110
 
@@ -225,6 +225,8 @@ def tool_call_efficiency(trace: Trace) -> Feedback:
225
225
  value=True,
226
226
  rationale=f"Efficient tool usage: {len(tool_calls)} successful calls"
227
227
  )
228
+
229
+
228
230
 
229
231
  # COMMAND ----------
230
232
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "dao-ai"
7
- version = "0.1.12"
7
+ version = "0.1.14"
8
8
  description = "DAO AI: A modular, multi-agent orchestration framework for complex AI workflows. Supports agent handoff, tool integration, and dynamic configuration via YAML."
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -14,7 +14,7 @@ from typing import AsyncGenerator
14
14
 
15
15
  import mlflow
16
16
  from dotenv import load_dotenv
17
- from mlflow.genai.agent_server import invoke, stream
17
+ from mlflow.genai.agent_server import get_request_headers, invoke, stream
18
18
  from mlflow.types.responses import (
19
19
  ResponsesAgentRequest,
20
20
  ResponsesAgentResponse,
@@ -25,6 +25,23 @@ from dao_ai.config import AppConfig
25
25
  from dao_ai.logging import configure_logging
26
26
  from dao_ai.models import LanggraphResponsesAgent
27
27
 
28
+
29
+ def _inject_headers_into_request(request: ResponsesAgentRequest) -> None:
30
+ """Inject request headers into custom_inputs for Context propagation.
31
+
32
+ Captures headers from the MLflow AgentServer context (where they're available)
33
+ and injects them into request.custom_inputs.configurable.headers so they
34
+ flow through to Context and can be used for OBO authentication.
35
+ """
36
+ headers: dict[str, str] = get_request_headers()
37
+ if headers:
38
+ if request.custom_inputs is None:
39
+ request.custom_inputs = {}
40
+ if "configurable" not in request.custom_inputs:
41
+ request.custom_inputs["configurable"] = {}
42
+ request.custom_inputs["configurable"]["headers"] = headers
43
+
44
+
28
45
  # Load environment variables from .env.local if it exists
29
46
  load_dotenv(dotenv_path=".env.local", override=True)
30
47
 
@@ -61,6 +78,8 @@ async def non_streaming(request: ResponsesAgentRequest) -> ResponsesAgentRespons
61
78
  Returns:
62
79
  ResponsesAgentResponse with the complete output
63
80
  """
81
+ # Capture headers while in the AgentServer async context (before they're lost)
82
+ _inject_headers_into_request(request)
64
83
  return await _responses_agent.apredict(request)
65
84
 
66
85
 
@@ -80,5 +99,7 @@ async def streaming(
80
99
  Yields:
81
100
  ResponsesAgentStreamEvent objects as they are generated
82
101
  """
102
+ # Capture headers while in the AgentServer async context (before they're lost)
103
+ _inject_headers_into_request(request)
83
104
  async for event in _responses_agent.apredict_stream(request):
84
105
  yield event
@@ -7,6 +7,7 @@ from enum import Enum
7
7
  from os import PathLike
8
8
  from pathlib import Path
9
9
  from typing import (
10
+ TYPE_CHECKING,
10
11
  Any,
11
12
  Callable,
12
13
  Iterator,
@@ -18,6 +19,9 @@ from typing import (
18
19
  Union,
19
20
  )
20
21
 
22
+ if TYPE_CHECKING:
23
+ from dao_ai.state import Context
24
+
21
25
  from databricks.sdk import WorkspaceClient
22
26
  from databricks.sdk.credentials_provider import (
23
27
  CredentialsStrategy,
@@ -284,8 +288,8 @@ class IsDatabricksResource(ABC, BaseModel):
284
288
 
285
289
  Authentication priority:
286
290
  1. On-Behalf-Of User (on_behalf_of_user=True):
287
- - Forwarded headers (Databricks Apps)
288
- - ModelServingUserCredentials (Model Serving)
291
+ - Uses ModelServingUserCredentials (Model Serving)
292
+ - For Databricks Apps with headers, use workspace_client_from(context)
289
293
  2. Service Principal (client_id + client_secret + workspace_host)
290
294
  3. PAT (pat + workspace_host)
291
295
  4. Ambient/default authentication
@@ -294,36 +298,6 @@ class IsDatabricksResource(ABC, BaseModel):
294
298
 
295
299
  # Check for OBO first (highest priority)
296
300
  if self.on_behalf_of_user:
297
- # NEW: In Databricks Apps, use forwarded headers for per-user auth
298
- try:
299
- from mlflow.genai.agent_server import get_request_headers
300
-
301
- headers = get_request_headers()
302
- forwarded_token = headers.get("x-forwarded-access-token")
303
-
304
- if forwarded_token:
305
- forwarded_user = headers.get("x-forwarded-user", "unknown")
306
- logger.debug(
307
- f"Creating WorkspaceClient for {self.__class__.__name__} "
308
- f"with OBO using forwarded token from Databricks Apps",
309
- forwarded_user=forwarded_user,
310
- )
311
- # Use workspace_host if configured, otherwise SDK will auto-detect
312
- workspace_host_value: str | None = (
313
- normalize_host(value_of(self.workspace_host))
314
- if self.workspace_host
315
- else None
316
- )
317
- return WorkspaceClient(
318
- host=workspace_host_value,
319
- token=forwarded_token,
320
- auth_type="pat",
321
- )
322
- except (ImportError, LookupError):
323
- # mlflow not available or headers not set - fall through to Model Serving
324
- pass
325
-
326
- # Fall back to Model Serving OBO (existing behavior)
327
301
  credentials_strategy: CredentialsStrategy = ModelServingUserCredentials()
328
302
  logger.debug(
329
303
  f"Creating WorkspaceClient for {self.__class__.__name__} "
@@ -382,6 +356,55 @@ class IsDatabricksResource(ABC, BaseModel):
382
356
  )
383
357
  return WorkspaceClient()
384
358
 
359
+ def workspace_client_from(self, context: "Context | None") -> WorkspaceClient:
360
+ """
361
+ Get a WorkspaceClient using headers from the provided Context.
362
+
363
+ Use this method from tools that have access to ToolRuntime[Context].
364
+ This allows OBO authentication to work in Databricks Apps where headers
365
+ are captured at request entry and passed through the Context.
366
+
367
+ Args:
368
+ context: Runtime context containing headers for OBO auth.
369
+ If None or no headers, falls back to workspace_client property.
370
+
371
+ Returns:
372
+ WorkspaceClient configured with appropriate authentication.
373
+ """
374
+ from dao_ai.utils import normalize_host
375
+
376
+ # Check if we have headers in context for OBO
377
+ if context and context.headers and self.on_behalf_of_user:
378
+ headers = context.headers
379
+ # Try both lowercase and title-case header names (HTTP headers are case-insensitive)
380
+ forwarded_token = headers.get("x-forwarded-access-token") or headers.get(
381
+ "X-Forwarded-Access-Token"
382
+ )
383
+
384
+ if forwarded_token:
385
+ forwarded_user = headers.get("x-forwarded-user") or headers.get(
386
+ "X-Forwarded-User", "unknown"
387
+ )
388
+ logger.debug(
389
+ f"Creating WorkspaceClient for {self.__class__.__name__} "
390
+ f"with OBO using forwarded token from Context",
391
+ forwarded_user=forwarded_user,
392
+ )
393
+ # Use workspace_host if configured, otherwise SDK will auto-detect
394
+ workspace_host_value: str | None = (
395
+ normalize_host(value_of(self.workspace_host))
396
+ if self.workspace_host
397
+ else None
398
+ )
399
+ return WorkspaceClient(
400
+ host=workspace_host_value,
401
+ token=forwarded_token,
402
+ auth_type="pat",
403
+ )
404
+
405
+ # Fall back to existing workspace_client property
406
+ return self.workspace_client
407
+
385
408
 
386
409
  class DeploymentTarget(str, Enum):
387
410
  """Target platform for agent deployment."""
@@ -139,29 +139,53 @@ Returns:
139
139
  GenieResponse: A response object containing the conversation ID and result from Genie."""
140
140
  tool_description = tool_description + function_docs
141
141
 
142
- genie: Genie = Genie(
143
- space_id=space_id,
144
- client=genie_room.workspace_client,
145
- truncate_results=truncate_results,
146
- )
142
+ # Cache for genie service - created lazily on first call
143
+ # This allows us to use workspace_client_from with runtime context for OBO
144
+ _cached_genie_service: GenieServiceBase | None = None
145
+
146
+ def _get_genie_service(context: Context | None) -> GenieServiceBase:
147
+ """Get or create the Genie service, using context for OBO auth if available."""
148
+ nonlocal _cached_genie_service
149
+
150
+ # Use cached service if available (for non-OBO or after first call)
151
+ # For OBO, we need fresh workspace client each time to use the user's token
152
+ if _cached_genie_service is not None and not genie_room.on_behalf_of_user:
153
+ return _cached_genie_service
154
+
155
+ # Get workspace client using context for OBO support
156
+ from databricks.sdk import WorkspaceClient
147
157
 
148
- genie_service: GenieServiceBase = GenieService(genie)
149
-
150
- # Wrap with semantic cache first (checked second due to decorator pattern)
151
- if semantic_cache_parameters is not None:
152
- genie_service = SemanticCacheService(
153
- impl=genie_service,
154
- parameters=semantic_cache_parameters,
155
- workspace_client=genie_room.workspace_client, # Pass workspace client for conversation history
156
- ).initialize() # Eagerly initialize to fail fast and create table
157
-
158
- # Wrap with LRU cache last (checked first - fast O(1) exact match)
159
- if lru_cache_parameters is not None:
160
- genie_service = LRUCacheService(
161
- impl=genie_service,
162
- parameters=lru_cache_parameters,
158
+ workspace_client: WorkspaceClient = genie_room.workspace_client_from(context)
159
+
160
+ genie: Genie = Genie(
161
+ space_id=space_id,
162
+ client=workspace_client,
163
+ truncate_results=truncate_results,
163
164
  )
164
165
 
166
+ genie_service: GenieServiceBase = GenieService(genie)
167
+
168
+ # Wrap with semantic cache first (checked second due to decorator pattern)
169
+ if semantic_cache_parameters is not None:
170
+ genie_service = SemanticCacheService(
171
+ impl=genie_service,
172
+ parameters=semantic_cache_parameters,
173
+ workspace_client=workspace_client,
174
+ ).initialize()
175
+
176
+ # Wrap with LRU cache last (checked first - fast O(1) exact match)
177
+ if lru_cache_parameters is not None:
178
+ genie_service = LRUCacheService(
179
+ impl=genie_service,
180
+ parameters=lru_cache_parameters,
181
+ )
182
+
183
+ # Cache for non-OBO scenarios
184
+ if not genie_room.on_behalf_of_user:
185
+ _cached_genie_service = genie_service
186
+
187
+ return genie_service
188
+
165
189
  @tool(
166
190
  name_or_callable=tool_name,
167
191
  description=tool_description,
@@ -177,6 +201,10 @@ GenieResponse: A response object containing the conversation ID and result from
177
201
  # Access state through runtime
178
202
  state: AgentState = runtime.state
179
203
  tool_call_id: str = runtime.tool_call_id
204
+ context: Context | None = runtime.context
205
+
206
+ # Get genie service with OBO support via context
207
+ genie_service: GenieServiceBase = _get_genie_service(context)
180
208
 
181
209
  # Ensure space_id is a string for state keys
182
210
  space_id_str: str = str(space_id)
@@ -194,6 +222,14 @@ GenieResponse: A response object containing the conversation ID and result from
194
222
  conversation_id=existing_conversation_id,
195
223
  )
196
224
 
225
+ # Log the prompt being sent to Genie
226
+ logger.trace(
227
+ "Sending prompt to Genie",
228
+ space_id=space_id_str,
229
+ conversation_id=existing_conversation_id,
230
+ prompt=question[:500] + "..." if len(question) > 500 else question,
231
+ )
232
+
197
233
  # Call ask_question which always returns CacheResult with cache metadata
198
234
  cache_result: CacheResult = genie_service.ask_question(
199
235
  question, conversation_id=existing_conversation_id
@@ -211,6 +247,22 @@ GenieResponse: A response object containing the conversation ID and result from
211
247
  cache_key=cache_key,
212
248
  )
213
249
 
250
+ # Log truncated response for debugging
251
+ result_preview: str = str(genie_response.result)
252
+ if len(result_preview) > 500:
253
+ result_preview = result_preview[:500] + "..."
254
+ logger.trace(
255
+ "Genie response content",
256
+ question=question[:100] + "..." if len(question) > 100 else question,
257
+ query=genie_response.query,
258
+ description=(
259
+ genie_response.description[:200] + "..."
260
+ if genie_response.description and len(genie_response.description) > 200
261
+ else genie_response.description
262
+ ),
263
+ result_preview=result_preview,
264
+ )
265
+
214
266
  # Update session state with cache information
215
267
  if persist_conversation:
216
268
  session.genie.update_space(