nvidia-nat 1.4.0a20251112__py3-none-any.whl → 1.4.0a20260113__py3-none-any.whl

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 (492) hide show
  1. aiq/__init__.py +1 -1
  2. nat/{front_ends/mcp → agent/auto_memory_wrapper}/__init__.py +1 -1
  3. nat/agent/auto_memory_wrapper/agent.py +278 -0
  4. nat/agent/auto_memory_wrapper/register.py +227 -0
  5. nat/agent/auto_memory_wrapper/state.py +30 -0
  6. nat/agent/base.py +1 -1
  7. nat/agent/dual_node.py +1 -1
  8. nat/agent/prompt_optimizer/prompt.py +1 -1
  9. nat/agent/prompt_optimizer/register.py +1 -1
  10. nat/agent/react_agent/agent.py +16 -9
  11. nat/agent/react_agent/output_parser.py +2 -2
  12. nat/agent/react_agent/prompt.py +3 -2
  13. nat/agent/react_agent/register.py +2 -2
  14. nat/agent/react_agent/register_per_user_agent.py +104 -0
  15. nat/agent/reasoning_agent/reasoning_agent.py +1 -1
  16. nat/agent/register.py +3 -1
  17. nat/agent/responses_api_agent/__init__.py +1 -1
  18. nat/agent/responses_api_agent/register.py +1 -1
  19. nat/agent/rewoo_agent/agent.py +9 -4
  20. nat/agent/rewoo_agent/prompt.py +1 -1
  21. nat/agent/rewoo_agent/register.py +1 -1
  22. nat/agent/tool_calling_agent/agent.py +5 -4
  23. nat/agent/tool_calling_agent/register.py +1 -1
  24. nat/authentication/__init__.py +1 -1
  25. nat/authentication/api_key/__init__.py +1 -1
  26. nat/authentication/api_key/api_key_auth_provider.py +1 -1
  27. nat/authentication/api_key/api_key_auth_provider_config.py +22 -7
  28. nat/authentication/api_key/register.py +1 -1
  29. nat/authentication/credential_validator/__init__.py +1 -1
  30. nat/authentication/credential_validator/bearer_token_validator.py +1 -1
  31. nat/authentication/exceptions/__init__.py +1 -1
  32. nat/authentication/exceptions/api_key_exceptions.py +1 -1
  33. nat/authentication/http_basic_auth/http_basic_auth_provider.py +1 -1
  34. nat/authentication/http_basic_auth/register.py +1 -1
  35. nat/authentication/interfaces.py +1 -1
  36. nat/authentication/oauth2/__init__.py +1 -1
  37. nat/authentication/oauth2/oauth2_auth_code_flow_provider.py +1 -1
  38. nat/authentication/oauth2/oauth2_auth_code_flow_provider_config.py +1 -1
  39. nat/authentication/oauth2/oauth2_resource_server_config.py +1 -1
  40. nat/authentication/oauth2/register.py +1 -1
  41. nat/authentication/register.py +1 -1
  42. nat/builder/builder.py +563 -1
  43. nat/builder/child_builder.py +385 -0
  44. nat/builder/component_utils.py +34 -4
  45. nat/builder/context.py +34 -1
  46. nat/builder/embedder.py +1 -1
  47. nat/builder/eval_builder.py +19 -7
  48. nat/builder/evaluator.py +1 -1
  49. nat/builder/framework_enum.py +3 -1
  50. nat/builder/front_end.py +1 -1
  51. nat/builder/function.py +113 -5
  52. nat/builder/function_base.py +1 -1
  53. nat/builder/function_info.py +1 -1
  54. nat/builder/intermediate_step_manager.py +1 -1
  55. nat/builder/llm.py +1 -1
  56. nat/builder/per_user_workflow_builder.py +843 -0
  57. nat/builder/retriever.py +1 -1
  58. nat/builder/sync_builder.py +571 -0
  59. nat/builder/user_interaction_manager.py +1 -1
  60. nat/builder/workflow.py +5 -3
  61. nat/builder/workflow_builder.py +619 -378
  62. nat/cli/__init__.py +1 -1
  63. nat/cli/cli_utils/config_override.py +1 -1
  64. nat/cli/cli_utils/validation.py +32 -1
  65. nat/cli/commands/configure/channel/add.py +1 -1
  66. nat/cli/commands/configure/channel/channel.py +1 -1
  67. nat/cli/commands/configure/channel/remove.py +1 -1
  68. nat/cli/commands/configure/channel/update.py +1 -1
  69. nat/cli/commands/configure/configure.py +1 -1
  70. nat/cli/commands/evaluate.py +87 -13
  71. nat/cli/commands/finetune.py +132 -0
  72. nat/cli/commands/info/__init__.py +1 -1
  73. nat/cli/commands/info/info.py +1 -1
  74. nat/cli/commands/info/list_channels.py +1 -1
  75. nat/cli/commands/info/list_components.py +1 -1
  76. nat/cli/commands/object_store/__init__.py +1 -1
  77. nat/cli/commands/object_store/object_store.py +1 -1
  78. nat/cli/commands/optimize.py +1 -1
  79. nat/cli/commands/{mcp → red_teaming}/__init__.py +1 -1
  80. nat/cli/commands/red_teaming/red_teaming.py +138 -0
  81. nat/cli/commands/red_teaming/red_teaming_utils.py +73 -0
  82. nat/cli/commands/registry/__init__.py +1 -1
  83. nat/cli/commands/registry/publish.py +1 -1
  84. nat/cli/commands/registry/pull.py +1 -1
  85. nat/cli/commands/registry/registry.py +1 -1
  86. nat/cli/commands/registry/remove.py +1 -1
  87. nat/cli/commands/registry/search.py +1 -1
  88. nat/cli/commands/sizing/__init__.py +1 -1
  89. nat/cli/commands/sizing/calc.py +1 -1
  90. nat/cli/commands/sizing/sizing.py +1 -1
  91. nat/cli/commands/start.py +1 -1
  92. nat/cli/commands/uninstall.py +1 -1
  93. nat/cli/commands/validate.py +1 -1
  94. nat/cli/commands/workflow/__init__.py +1 -1
  95. nat/cli/commands/workflow/workflow.py +1 -1
  96. nat/cli/commands/workflow/workflow_commands.py +3 -2
  97. nat/cli/entrypoint.py +15 -37
  98. nat/cli/main.py +2 -2
  99. nat/cli/plugin_loader.py +69 -0
  100. nat/cli/register_workflow.py +233 -5
  101. nat/cli/type_registry.py +237 -3
  102. nat/control_flow/register.py +1 -1
  103. nat/control_flow/router_agent/agent.py +1 -1
  104. nat/control_flow/router_agent/prompt.py +1 -1
  105. nat/control_flow/router_agent/register.py +1 -1
  106. nat/control_flow/sequential_executor.py +28 -7
  107. nat/data_models/__init__.py +1 -1
  108. nat/data_models/agent.py +1 -1
  109. nat/data_models/api_server.py +38 -3
  110. nat/data_models/authentication.py +1 -1
  111. nat/data_models/common.py +1 -1
  112. nat/data_models/component.py +9 -1
  113. nat/data_models/component_ref.py +45 -1
  114. nat/data_models/config.py +78 -1
  115. nat/data_models/dataset_handler.py +15 -2
  116. nat/data_models/discovery_metadata.py +1 -1
  117. nat/data_models/embedder.py +1 -1
  118. nat/data_models/evaluate.py +6 -1
  119. nat/data_models/evaluator.py +1 -1
  120. nat/data_models/finetuning.py +260 -0
  121. nat/data_models/front_end.py +1 -1
  122. nat/data_models/function.py +15 -2
  123. nat/data_models/function_dependencies.py +1 -1
  124. nat/data_models/gated_field_mixin.py +1 -1
  125. nat/data_models/interactive.py +1 -1
  126. nat/data_models/intermediate_step.py +29 -2
  127. nat/data_models/invocation_node.py +1 -1
  128. nat/data_models/llm.py +1 -1
  129. nat/data_models/logging.py +1 -1
  130. nat/data_models/memory.py +1 -1
  131. nat/data_models/middleware.py +37 -0
  132. nat/data_models/object_store.py +1 -1
  133. nat/data_models/openai_mcp.py +1 -1
  134. nat/data_models/optimizable.py +1 -1
  135. nat/data_models/optimizer.py +1 -1
  136. nat/data_models/profiler.py +1 -1
  137. nat/data_models/registry_handler.py +1 -1
  138. nat/data_models/retriever.py +1 -1
  139. nat/data_models/retry_mixin.py +1 -1
  140. nat/data_models/runtime_enum.py +26 -0
  141. nat/data_models/span.py +1 -1
  142. nat/data_models/step_adaptor.py +1 -1
  143. nat/data_models/streaming.py +1 -1
  144. nat/data_models/swe_bench_model.py +1 -1
  145. nat/data_models/telemetry_exporter.py +1 -1
  146. nat/data_models/thinking_mixin.py +1 -1
  147. nat/data_models/ttc_strategy.py +1 -1
  148. nat/embedder/azure_openai_embedder.py +1 -1
  149. nat/embedder/nim_embedder.py +1 -1
  150. nat/embedder/openai_embedder.py +1 -1
  151. nat/embedder/register.py +1 -1
  152. nat/eval/__init__.py +1 -1
  153. nat/eval/config.py +8 -1
  154. nat/eval/dataset_handler/dataset_downloader.py +1 -1
  155. nat/eval/dataset_handler/dataset_filter.py +1 -1
  156. nat/eval/dataset_handler/dataset_handler.py +4 -2
  157. nat/eval/evaluate.py +226 -81
  158. nat/eval/evaluator/__init__.py +1 -1
  159. nat/eval/evaluator/base_evaluator.py +2 -2
  160. nat/eval/evaluator/evaluator_model.py +3 -2
  161. nat/eval/intermediate_step_adapter.py +1 -1
  162. nat/eval/llm_validator.py +336 -0
  163. nat/eval/rag_evaluator/evaluate.py +17 -10
  164. nat/eval/rag_evaluator/register.py +1 -1
  165. nat/eval/red_teaming_evaluator/__init__.py +14 -0
  166. nat/eval/red_teaming_evaluator/data_models.py +66 -0
  167. nat/eval/red_teaming_evaluator/evaluate.py +327 -0
  168. nat/eval/red_teaming_evaluator/filter_conditions.py +75 -0
  169. nat/eval/red_teaming_evaluator/register.py +55 -0
  170. nat/eval/register.py +2 -1
  171. nat/eval/remote_workflow.py +1 -1
  172. nat/eval/runners/__init__.py +1 -1
  173. nat/eval/runners/config.py +1 -1
  174. nat/eval/runners/multi_eval_runner.py +1 -1
  175. nat/eval/runners/red_teaming_runner/__init__.py +24 -0
  176. nat/eval/runners/red_teaming_runner/config.py +282 -0
  177. nat/eval/runners/red_teaming_runner/report_utils.py +707 -0
  178. nat/eval/runners/red_teaming_runner/runner.py +867 -0
  179. nat/eval/runtime_evaluator/__init__.py +1 -1
  180. nat/eval/runtime_evaluator/evaluate.py +1 -1
  181. nat/eval/runtime_evaluator/register.py +1 -1
  182. nat/eval/runtime_event_subscriber.py +1 -1
  183. nat/eval/swe_bench_evaluator/evaluate.py +1 -1
  184. nat/eval/swe_bench_evaluator/register.py +1 -1
  185. nat/eval/trajectory_evaluator/evaluate.py +2 -2
  186. nat/eval/trajectory_evaluator/register.py +1 -1
  187. nat/eval/tunable_rag_evaluator/evaluate.py +5 -5
  188. nat/eval/tunable_rag_evaluator/register.py +1 -1
  189. nat/eval/usage_stats.py +1 -1
  190. nat/eval/utils/eval_trace_ctx.py +1 -1
  191. nat/eval/utils/output_uploader.py +1 -1
  192. nat/eval/utils/tqdm_position_registry.py +1 -1
  193. nat/eval/utils/weave_eval.py +1 -1
  194. nat/experimental/decorators/experimental_warning_decorator.py +1 -1
  195. nat/experimental/test_time_compute/editing/iterative_plan_refinement_editor.py +1 -1
  196. nat/experimental/test_time_compute/editing/llm_as_a_judge_editor.py +1 -1
  197. nat/experimental/test_time_compute/editing/motivation_aware_summarization.py +1 -1
  198. nat/experimental/test_time_compute/functions/execute_score_select_function.py +1 -1
  199. nat/experimental/test_time_compute/functions/multi_llm_judge_function.py +88 -0
  200. nat/experimental/test_time_compute/functions/plan_select_execute_function.py +1 -1
  201. nat/experimental/test_time_compute/functions/ttc_tool_orchestration_function.py +1 -1
  202. nat/experimental/test_time_compute/functions/ttc_tool_wrapper_function.py +1 -1
  203. nat/experimental/test_time_compute/models/editor_config.py +1 -1
  204. nat/experimental/test_time_compute/models/scoring_config.py +1 -1
  205. nat/experimental/test_time_compute/models/search_config.py +20 -2
  206. nat/experimental/test_time_compute/models/selection_config.py +33 -2
  207. nat/experimental/test_time_compute/models/stage_enums.py +1 -1
  208. nat/experimental/test_time_compute/models/strategy_base.py +1 -1
  209. nat/experimental/test_time_compute/models/tool_use_config.py +1 -1
  210. nat/experimental/test_time_compute/models/ttc_item.py +1 -1
  211. nat/experimental/test_time_compute/register.py +4 -1
  212. nat/experimental/test_time_compute/scoring/llm_based_agent_scorer.py +1 -1
  213. nat/experimental/test_time_compute/scoring/llm_based_plan_scorer.py +1 -1
  214. nat/experimental/test_time_compute/scoring/motivation_aware_scorer.py +1 -1
  215. nat/experimental/test_time_compute/search/multi_llm_generation.py +115 -0
  216. nat/experimental/test_time_compute/search/multi_llm_planner.py +1 -1
  217. nat/experimental/test_time_compute/search/multi_query_retrieval_search.py +1 -1
  218. nat/experimental/test_time_compute/search/single_shot_multi_plan_planner.py +1 -1
  219. nat/experimental/test_time_compute/selection/best_of_n_selector.py +1 -1
  220. nat/experimental/test_time_compute/selection/llm_based_agent_output_selector.py +1 -1
  221. nat/experimental/test_time_compute/selection/llm_based_output_merging_selector.py +1 -1
  222. nat/experimental/test_time_compute/selection/llm_based_plan_selector.py +1 -1
  223. nat/experimental/test_time_compute/selection/llm_judge_selection.py +127 -0
  224. nat/experimental/test_time_compute/selection/threshold_selector.py +1 -1
  225. nat/finetuning/__init__.py +24 -0
  226. nat/finetuning/finetuning_runtime.py +143 -0
  227. nat/finetuning/interfaces/__init__.py +24 -0
  228. nat/finetuning/interfaces/finetuning_runner.py +261 -0
  229. nat/finetuning/interfaces/trainer_adapter.py +103 -0
  230. nat/finetuning/interfaces/trajectory_builder.py +115 -0
  231. nat/finetuning/utils/__init__.py +15 -0
  232. nat/finetuning/utils/parsers/__init__.py +15 -0
  233. nat/finetuning/utils/parsers/adk_parser.py +141 -0
  234. nat/finetuning/utils/parsers/base_parser.py +238 -0
  235. nat/finetuning/utils/parsers/common.py +91 -0
  236. nat/finetuning/utils/parsers/langchain_parser.py +267 -0
  237. nat/finetuning/utils/parsers/llama_index_parser.py +218 -0
  238. nat/front_ends/__init__.py +1 -1
  239. nat/front_ends/console/__init__.py +1 -1
  240. nat/front_ends/console/authentication_flow_handler.py +1 -1
  241. nat/front_ends/console/console_front_end_config.py +4 -1
  242. nat/front_ends/console/console_front_end_plugin.py +5 -4
  243. nat/front_ends/console/register.py +1 -1
  244. nat/front_ends/cron/__init__.py +1 -1
  245. nat/front_ends/fastapi/__init__.py +1 -1
  246. nat/front_ends/fastapi/async_job.py +128 -0
  247. nat/front_ends/fastapi/auth_flow_handlers/http_flow_handler.py +1 -1
  248. nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py +13 -9
  249. nat/front_ends/fastapi/dask_client_mixin.py +1 -1
  250. nat/front_ends/fastapi/fastapi_front_end_config.py +23 -1
  251. nat/front_ends/fastapi/fastapi_front_end_controller.py +1 -1
  252. nat/front_ends/fastapi/fastapi_front_end_plugin.py +25 -30
  253. nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py +318 -59
  254. nat/front_ends/fastapi/html_snippets/__init__.py +1 -1
  255. nat/front_ends/fastapi/html_snippets/auth_code_grant_success.py +1 -1
  256. nat/front_ends/fastapi/intermediate_steps_subscriber.py +12 -1
  257. nat/front_ends/fastapi/job_store.py +23 -11
  258. nat/front_ends/fastapi/main.py +1 -1
  259. nat/front_ends/fastapi/message_handler.py +27 -4
  260. nat/front_ends/fastapi/message_validator.py +54 -2
  261. nat/front_ends/fastapi/register.py +1 -1
  262. nat/front_ends/fastapi/response_helpers.py +16 -15
  263. nat/front_ends/fastapi/step_adaptor.py +1 -1
  264. nat/front_ends/fastapi/utils.py +1 -1
  265. nat/front_ends/register.py +1 -2
  266. nat/front_ends/simple_base/__init__.py +1 -1
  267. nat/front_ends/simple_base/simple_front_end_plugin_base.py +6 -4
  268. nat/llm/aws_bedrock_llm.py +1 -1
  269. nat/llm/azure_openai_llm.py +10 -1
  270. nat/llm/dynamo_llm.py +363 -0
  271. nat/llm/huggingface_llm.py +177 -0
  272. nat/llm/litellm_llm.py +1 -1
  273. nat/llm/nim_llm.py +1 -1
  274. nat/llm/openai_llm.py +1 -1
  275. nat/llm/register.py +3 -1
  276. nat/llm/utils/__init__.py +1 -1
  277. nat/llm/utils/env_config_value.py +1 -1
  278. nat/llm/utils/error.py +1 -1
  279. nat/llm/utils/thinking.py +1 -1
  280. nat/memory/__init__.py +1 -1
  281. nat/memory/interfaces.py +1 -1
  282. nat/memory/models.py +1 -1
  283. nat/meta/pypi.md +1 -1
  284. nat/middleware/__init__.py +35 -0
  285. nat/middleware/cache/__init__.py +14 -0
  286. nat/middleware/cache/cache_middleware.py +253 -0
  287. nat/middleware/cache/cache_middleware_config.py +44 -0
  288. nat/middleware/cache/register.py +33 -0
  289. nat/middleware/defense/__init__.py +14 -0
  290. nat/middleware/defense/defense_middleware.py +362 -0
  291. nat/middleware/defense/defense_middleware_content_guard.py +455 -0
  292. nat/middleware/defense/defense_middleware_data_models.py +91 -0
  293. nat/middleware/defense/defense_middleware_output_verifier.py +440 -0
  294. nat/middleware/defense/defense_middleware_pii.py +356 -0
  295. nat/middleware/defense/register.py +82 -0
  296. nat/middleware/dynamic/__init__.py +14 -0
  297. nat/middleware/dynamic/dynamic_function_middleware.py +962 -0
  298. nat/middleware/dynamic/dynamic_middleware_config.py +132 -0
  299. nat/middleware/dynamic/register.py +34 -0
  300. nat/middleware/function_middleware.py +370 -0
  301. nat/middleware/logging/__init__.py +14 -0
  302. nat/middleware/logging/logging_middleware.py +67 -0
  303. nat/middleware/logging/logging_middleware_config.py +28 -0
  304. nat/middleware/logging/register.py +33 -0
  305. nat/middleware/middleware.py +298 -0
  306. nat/middleware/red_teaming/__init__.py +14 -0
  307. nat/middleware/red_teaming/red_teaming_middleware.py +344 -0
  308. nat/middleware/red_teaming/red_teaming_middleware_config.py +112 -0
  309. nat/middleware/red_teaming/register.py +47 -0
  310. nat/middleware/register.py +22 -0
  311. nat/middleware/utils/__init__.py +14 -0
  312. nat/middleware/utils/workflow_inventory.py +155 -0
  313. nat/object_store/__init__.py +1 -1
  314. nat/object_store/in_memory_object_store.py +1 -1
  315. nat/object_store/interfaces.py +1 -1
  316. nat/object_store/models.py +1 -1
  317. nat/object_store/register.py +1 -1
  318. nat/observability/__init__.py +1 -1
  319. nat/observability/exporter/__init__.py +1 -1
  320. nat/observability/exporter/base_exporter.py +1 -1
  321. nat/observability/exporter/exporter.py +1 -1
  322. nat/observability/exporter/file_exporter.py +1 -1
  323. nat/observability/exporter/processing_exporter.py +1 -1
  324. nat/observability/exporter/raw_exporter.py +1 -1
  325. nat/observability/exporter/span_exporter.py +7 -1
  326. nat/observability/exporter_manager.py +1 -1
  327. nat/observability/mixin/__init__.py +1 -1
  328. nat/observability/mixin/batch_config_mixin.py +1 -1
  329. nat/observability/mixin/collector_config_mixin.py +1 -1
  330. nat/observability/mixin/file_mixin.py +1 -1
  331. nat/observability/mixin/file_mode.py +1 -1
  332. nat/observability/mixin/redaction_config_mixin.py +1 -1
  333. nat/observability/mixin/resource_conflict_mixin.py +1 -1
  334. nat/observability/mixin/serialize_mixin.py +1 -1
  335. nat/observability/mixin/tagging_config_mixin.py +1 -1
  336. nat/observability/mixin/type_introspection_mixin.py +1 -1
  337. nat/observability/processor/__init__.py +1 -1
  338. nat/observability/processor/batching_processor.py +1 -1
  339. nat/observability/processor/callback_processor.py +1 -1
  340. nat/observability/processor/falsy_batch_filter_processor.py +1 -1
  341. nat/observability/processor/intermediate_step_serializer.py +1 -1
  342. nat/observability/processor/processor.py +1 -1
  343. nat/observability/processor/processor_factory.py +1 -1
  344. nat/observability/processor/redaction/__init__.py +1 -1
  345. nat/observability/processor/redaction/contextual_redaction_processor.py +1 -1
  346. nat/observability/processor/redaction/contextual_span_redaction_processor.py +1 -1
  347. nat/observability/processor/redaction/redaction_processor.py +1 -1
  348. nat/observability/processor/redaction/span_header_redaction_processor.py +1 -1
  349. nat/observability/processor/span_tagging_processor.py +1 -1
  350. nat/observability/register.py +1 -1
  351. nat/observability/utils/__init__.py +1 -1
  352. nat/observability/utils/dict_utils.py +1 -1
  353. nat/observability/utils/time_utils.py +1 -1
  354. nat/profiler/calc/__init__.py +1 -1
  355. nat/profiler/calc/calc_runner.py +3 -3
  356. nat/profiler/calc/calculations.py +1 -1
  357. nat/profiler/calc/data_models.py +1 -1
  358. nat/profiler/calc/plot.py +30 -3
  359. nat/profiler/callbacks/agno_callback_handler.py +1 -1
  360. nat/profiler/callbacks/base_callback_class.py +1 -1
  361. nat/profiler/callbacks/langchain_callback_handler.py +33 -3
  362. nat/profiler/callbacks/llama_index_callback_handler.py +13 -10
  363. nat/profiler/callbacks/semantic_kernel_callback_handler.py +1 -1
  364. nat/profiler/callbacks/token_usage_base_model.py +1 -1
  365. nat/profiler/data_frame_row.py +1 -1
  366. nat/profiler/data_models.py +1 -1
  367. nat/profiler/decorators/framework_wrapper.py +32 -1
  368. nat/profiler/decorators/function_tracking.py +1 -1
  369. nat/profiler/forecasting/config.py +1 -1
  370. nat/profiler/forecasting/model_trainer.py +1 -1
  371. nat/profiler/forecasting/models/__init__.py +1 -1
  372. nat/profiler/forecasting/models/forecasting_base_model.py +1 -1
  373. nat/profiler/forecasting/models/linear_model.py +1 -1
  374. nat/profiler/forecasting/models/random_forest_regressor.py +1 -1
  375. nat/profiler/inference_metrics_model.py +1 -1
  376. nat/profiler/inference_optimization/bottleneck_analysis/nested_stack_analysis.py +1 -1
  377. nat/profiler/inference_optimization/bottleneck_analysis/simple_stack_analysis.py +1 -1
  378. nat/profiler/inference_optimization/data_models.py +1 -1
  379. nat/profiler/inference_optimization/experimental/concurrency_spike_analysis.py +1 -1
  380. nat/profiler/inference_optimization/experimental/prefix_span_analysis.py +1 -1
  381. nat/profiler/inference_optimization/llm_metrics.py +1 -1
  382. nat/profiler/inference_optimization/prompt_caching.py +1 -1
  383. nat/profiler/inference_optimization/token_uniqueness.py +1 -1
  384. nat/profiler/inference_optimization/workflow_runtimes.py +1 -1
  385. nat/profiler/intermediate_property_adapter.py +1 -1
  386. nat/profiler/parameter_optimization/optimizable_utils.py +1 -1
  387. nat/profiler/parameter_optimization/optimizer_runtime.py +1 -1
  388. nat/profiler/parameter_optimization/parameter_optimizer.py +1 -1
  389. nat/profiler/parameter_optimization/parameter_selection.py +1 -1
  390. nat/profiler/parameter_optimization/pareto_visualizer.py +1 -1
  391. nat/profiler/parameter_optimization/prompt_optimizer.py +1 -1
  392. nat/profiler/parameter_optimization/update_helpers.py +1 -1
  393. nat/profiler/profile_runner.py +1 -1
  394. nat/profiler/utils.py +1 -1
  395. nat/registry_handlers/local/local_handler.py +1 -1
  396. nat/registry_handlers/local/register_local.py +1 -1
  397. nat/registry_handlers/metadata_factory.py +1 -1
  398. nat/registry_handlers/package_utils.py +1 -1
  399. nat/registry_handlers/pypi/pypi_handler.py +1 -1
  400. nat/registry_handlers/pypi/register_pypi.py +1 -1
  401. nat/registry_handlers/register.py +1 -1
  402. nat/registry_handlers/registry_handler_base.py +1 -1
  403. nat/registry_handlers/rest/register_rest.py +1 -1
  404. nat/registry_handlers/rest/rest_handler.py +1 -1
  405. nat/registry_handlers/schemas/headers.py +1 -1
  406. nat/registry_handlers/schemas/package.py +1 -1
  407. nat/registry_handlers/schemas/publish.py +1 -1
  408. nat/registry_handlers/schemas/pull.py +1 -1
  409. nat/registry_handlers/schemas/remove.py +1 -1
  410. nat/registry_handlers/schemas/search.py +1 -1
  411. nat/registry_handlers/schemas/status.py +1 -1
  412. nat/retriever/interface.py +1 -1
  413. nat/retriever/milvus/__init__.py +1 -1
  414. nat/retriever/milvus/register.py +12 -4
  415. nat/retriever/milvus/retriever.py +103 -41
  416. nat/retriever/models.py +1 -1
  417. nat/retriever/nemo_retriever/__init__.py +1 -1
  418. nat/retriever/nemo_retriever/register.py +1 -1
  419. nat/retriever/nemo_retriever/retriever.py +5 -5
  420. nat/retriever/register.py +1 -1
  421. nat/runtime/__init__.py +1 -1
  422. nat/runtime/loader.py +10 -3
  423. nat/runtime/metrics.py +180 -0
  424. nat/runtime/runner.py +13 -6
  425. nat/runtime/session.py +458 -32
  426. nat/runtime/user_metadata.py +1 -1
  427. nat/settings/global_settings.py +1 -1
  428. nat/tool/chat_completion.py +1 -1
  429. nat/tool/code_execution/README.md +1 -1
  430. nat/tool/code_execution/code_sandbox.py +2 -2
  431. nat/tool/code_execution/local_sandbox/Dockerfile.sandbox +1 -1
  432. nat/tool/code_execution/local_sandbox/__init__.py +1 -1
  433. nat/tool/code_execution/local_sandbox/local_sandbox_server.py +1 -1
  434. nat/tool/code_execution/local_sandbox/start_local_sandbox.sh +1 -1
  435. nat/tool/code_execution/register.py +1 -1
  436. nat/tool/code_execution/utils.py +1 -1
  437. nat/tool/datetime_tools.py +1 -1
  438. nat/tool/document_search.py +1 -1
  439. nat/tool/github_tools.py +1 -1
  440. nat/tool/memory_tools/add_memory_tool.py +1 -1
  441. nat/tool/memory_tools/delete_memory_tool.py +1 -1
  442. nat/tool/memory_tools/get_memory_tool.py +1 -1
  443. nat/tool/nvidia_rag.py +2 -2
  444. nat/tool/register.py +1 -1
  445. nat/tool/retriever.py +1 -1
  446. nat/tool/server_tools.py +1 -1
  447. nat/utils/__init__.py +8 -5
  448. nat/utils/callable_utils.py +1 -1
  449. nat/utils/data_models/schema_validator.py +1 -1
  450. nat/utils/debugging_utils.py +1 -1
  451. nat/utils/decorators.py +1 -1
  452. nat/utils/dump_distro_mapping.py +1 -1
  453. nat/utils/exception_handlers/automatic_retries.py +3 -3
  454. nat/utils/exception_handlers/schemas.py +1 -1
  455. nat/utils/io/model_processing.py +1 -1
  456. nat/utils/io/supress_logs.py +33 -0
  457. nat/utils/io/yaml_tools.py +1 -1
  458. nat/utils/log_levels.py +1 -1
  459. nat/utils/log_utils.py +13 -1
  460. nat/utils/metadata_utils.py +1 -1
  461. nat/utils/optional_imports.py +1 -1
  462. nat/utils/producer_consumer_queue.py +1 -1
  463. nat/utils/reactive/base/observable_base.py +1 -1
  464. nat/utils/reactive/base/observer_base.py +1 -1
  465. nat/utils/reactive/base/subject_base.py +1 -1
  466. nat/utils/reactive/observable.py +1 -1
  467. nat/utils/reactive/observer.py +1 -1
  468. nat/utils/reactive/subject.py +1 -1
  469. nat/utils/reactive/subscription.py +1 -1
  470. nat/utils/responses_api.py +1 -1
  471. nat/utils/settings/global_settings.py +1 -1
  472. nat/utils/string_utils.py +1 -1
  473. nat/utils/type_converter.py +18 -5
  474. nat/utils/type_utils.py +1 -1
  475. nat/utils/url_utils.py +1 -1
  476. {nvidia_nat-1.4.0a20251112.dist-info → nvidia_nat-1.4.0a20260113.dist-info}/METADATA +46 -15
  477. nvidia_nat-1.4.0a20260113.dist-info/RECORD +547 -0
  478. nvidia_nat-1.4.0a20260113.dist-info/entry_points.txt +38 -0
  479. nat/cli/commands/mcp/mcp.py +0 -986
  480. nat/front_ends/mcp/introspection_token_verifier.py +0 -73
  481. nat/front_ends/mcp/mcp_front_end_config.py +0 -109
  482. nat/front_ends/mcp/mcp_front_end_plugin.py +0 -151
  483. nat/front_ends/mcp/mcp_front_end_plugin_worker.py +0 -362
  484. nat/front_ends/mcp/memory_profiler.py +0 -320
  485. nat/front_ends/mcp/register.py +0 -27
  486. nat/front_ends/mcp/tool_converter.py +0 -321
  487. nvidia_nat-1.4.0a20251112.dist-info/RECORD +0 -481
  488. nvidia_nat-1.4.0a20251112.dist-info/entry_points.txt +0 -22
  489. {nvidia_nat-1.4.0a20251112.dist-info → nvidia_nat-1.4.0a20260113.dist-info}/WHEEL +0 -0
  490. {nvidia_nat-1.4.0a20251112.dist-info → nvidia_nat-1.4.0a20260113.dist-info}/licenses/LICENSE-3rd-party.txt +0 -0
  491. {nvidia_nat-1.4.0a20251112.dist-info → nvidia_nat-1.4.0a20260113.dist-info}/licenses/LICENSE.md +0 -0
  492. {nvidia_nat-1.4.0a20251112.dist-info → nvidia_nat-1.4.0a20260113.dist-info}/top_level.txt +0 -0
aiq/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -0,0 +1,278 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ import logging
17
+ from collections.abc import Awaitable
18
+ from collections.abc import Callable
19
+ from typing import Any
20
+
21
+ from langchain_core.messages import AIMessage
22
+ from langchain_core.messages import BaseMessage
23
+ from langchain_core.messages import HumanMessage
24
+ from langchain_core.messages import SystemMessage
25
+ from langgraph.graph import StateGraph
26
+ from langgraph.graph.state import CompiledStateGraph
27
+
28
+ from nat.builder.context import Context
29
+ from nat.data_models.api_server import ChatRequest
30
+ from nat.data_models.api_server import Message
31
+ from nat.data_models.api_server import UserMessageContentRoleType
32
+ from nat.memory.interfaces import MemoryEditor
33
+ from nat.memory.models import MemoryItem
34
+
35
+ from .state import AutoMemoryWrapperState
36
+
37
+ logger = logging.getLogger(__name__)
38
+
39
+
40
+ class AutoMemoryWrapperGraph:
41
+ """
42
+ Wraps any NAT agent to add automatic memory capture and retrieval.
43
+
44
+ The wrapper treats the inner agent as a black-box function that receives
45
+ a ChatRequest with multiple messages (including system messages with memory
46
+ context). The inner agent manages its own internal state (ReActGraphState,
47
+ ReWOOGraphState, etc.) - the wrapper never sees it.
48
+ """
49
+
50
+ def __init__(
51
+ self,
52
+ inner_agent_fn: Callable[
53
+ [ChatRequest], Awaitable[Any]], # Inner agent as a Function (receives ChatRequest with multiple messages)
54
+ memory_editor: MemoryEditor, # Zep/Mem0/Redis memory client
55
+ save_user_messages: bool = True, # Auto-save user messages
56
+ retrieve_memory: bool = True, # Auto-retrieve before agent
57
+ save_ai_responses: bool = True, # Auto-save agent responses
58
+ search_params: dict[str, Any] | None = None, # Backend-specific search parameters
59
+ add_params: dict[str, Any] | None = None # Backend-specific add parameters
60
+ ):
61
+ self.inner_agent_fn = inner_agent_fn
62
+ self.memory_editor = memory_editor
63
+ self.save_user_messages = save_user_messages
64
+ self.retrieve_memory = retrieve_memory
65
+ self.save_ai_responses = save_ai_responses
66
+ self.search_params = search_params or {}
67
+ self.add_params = add_params or {}
68
+ self._context = Context.get()
69
+
70
+ def _get_user_id_from_context(self) -> str:
71
+ """
72
+ Extract user_id from runtime context.
73
+
74
+ Priority order:
75
+ 1. user_manager.get_id() - For authenticated sessions (set via SessionManager.session())
76
+ 2. X-User-ID HTTP header - For testing/simple auth without middleware
77
+ 3. "default_user" - Fallback for development/testing without authentication
78
+
79
+ Returns:
80
+ str: The user ID for memory operations
81
+ """
82
+ # Priority 1: Get user_id from user_manager (for authenticated sessions)
83
+ user_manager = self._context.user_manager
84
+ if user_manager and hasattr(user_manager, 'get_id'):
85
+ try:
86
+ user_id = user_manager.get_id()
87
+ if user_id:
88
+ logger.debug(f"Using user_id from user_manager: {user_id}")
89
+ return user_id
90
+ except Exception as e:
91
+ logger.debug(f"Failed to get user_id from user_manager: {e}")
92
+
93
+ # Priority 2: Extract from X-User-ID HTTP header (temporary workaround for testing)
94
+ if self._context.metadata and self._context.metadata.headers:
95
+ user_id = self._context.metadata.headers.get("x-user-id")
96
+ if user_id:
97
+ logger.debug(f"Using user_id from X-User-ID header: {user_id}")
98
+ return user_id
99
+
100
+ # Fallback: default for development/testing
101
+ logger.debug("Using default user_id: default_user")
102
+ return "default_user"
103
+
104
+ def get_wrapper_node_count(self) -> int:
105
+ """
106
+ Calculate the number of wrapper nodes that will be added to the graph.
107
+
108
+ This is used to determine the recursion_limit overhead that the wrapper
109
+ adds on top of the inner agent's recursion needs.
110
+
111
+ Returns:
112
+ int: Number of nodes in the wrapper graph (1-4 depending on configuration)
113
+ """
114
+ count = 1 # inner_agent node is always present
115
+ if self.save_user_messages:
116
+ count += 1 # capture_user_message node
117
+ if self.retrieve_memory:
118
+ count += 1 # memory_retrieve node
119
+ if self.save_ai_responses:
120
+ count += 1 # capture_ai_response node
121
+ return count
122
+
123
+ @staticmethod
124
+ def _langchain_message_to_nat_message(lc_message: BaseMessage) -> Message:
125
+ """
126
+ Convert LangChain message to NAT Message format.
127
+
128
+ This is necessary to construct a proper ChatRequest with all messages
129
+ (including system messages with memory context) to pass to the inner agent.
130
+ """
131
+ if isinstance(lc_message, HumanMessage):
132
+ role = UserMessageContentRoleType.USER
133
+ elif isinstance(lc_message, AIMessage):
134
+ role = UserMessageContentRoleType.ASSISTANT
135
+ elif isinstance(lc_message, SystemMessage):
136
+ role = UserMessageContentRoleType.SYSTEM
137
+ else:
138
+ # Default to user for unknown message types
139
+ role = UserMessageContentRoleType.USER
140
+
141
+ return Message(role=role, content=str(lc_message.content))
142
+
143
+ async def capture_user_message_node(self, state: AutoMemoryWrapperState) -> AutoMemoryWrapperState:
144
+ """Captures user message to memory thread"""
145
+ if not self.save_user_messages or not state.messages:
146
+ return state
147
+
148
+ # Get the latest user message
149
+ user_message = state.messages[-1]
150
+ if isinstance(user_message, HumanMessage):
151
+ # Get user_id from runtime context
152
+ user_id = self._get_user_id_from_context()
153
+
154
+ # Add to memory
155
+ await self.memory_editor.add_items(
156
+ [MemoryItem(conversation=[{
157
+ "role": "user", "content": str(user_message.content)
158
+ }], user_id=user_id)],
159
+ **self.add_params)
160
+ return state
161
+
162
+ async def memory_retrieve_node(self, state: AutoMemoryWrapperState) -> AutoMemoryWrapperState:
163
+ """Retrieves relevant memory from memory store"""
164
+ if not self.retrieve_memory or not state.messages:
165
+ return state
166
+
167
+ # Get the latest user message
168
+ user_message = state.messages[-1]
169
+
170
+ # Get user_id from runtime context
171
+ user_id = self._get_user_id_from_context()
172
+
173
+ # Retrieve memory from memory provider
174
+ memory_items = await self.memory_editor.search(
175
+ query=user_message.content, # Reasonable default for memory retrieval
176
+ user_id=user_id,
177
+ **self.search_params # User-configured params (e.g., top_k, mode)
178
+ )
179
+
180
+ # Extract memory strings and inject as system message if available
181
+ if memory_items:
182
+ # Extract memory field from each MemoryItem
183
+ memory_strings = [item.memory for item in memory_items if item.memory]
184
+ if memory_strings:
185
+ memory_text = "\n".join(memory_strings)
186
+ memory_message = SystemMessage(content=f"Relevant context from memory:\n{memory_text}")
187
+ # Insert before the last user message
188
+ state.messages.insert(-1, memory_message)
189
+
190
+ return state
191
+
192
+ async def inner_agent_node(self, state: AutoMemoryWrapperState) -> AutoMemoryWrapperState:
193
+ """
194
+ Calls the inner agent with a ChatRequest containing all messages.
195
+
196
+ The inner agent receives a ChatRequest with multiple messages (including
197
+ system messages with memory context), processes them using its own internal
198
+ state (ReActGraphState, ReWOOGraphState, etc.), and returns a ChatResponse.
199
+ """
200
+ # Convert all LangChain messages to NAT Message format
201
+ nat_messages = [self._langchain_message_to_nat_message(msg) for msg in state.messages]
202
+ chat_request = ChatRequest(messages=nat_messages)
203
+
204
+ # Call inner agent with ChatRequest - it manages its own state internally
205
+ response = await self.inner_agent_fn.ainvoke(chat_request)
206
+
207
+ # Extract content from response based on type
208
+ if hasattr(response, 'choices') and response.choices:
209
+ # ChatResponse object - extract from choices[0].message.content
210
+ response_text = response.choices[0].message.content or ""
211
+ elif hasattr(response, 'output'):
212
+ # GenerateResponse object - use output field
213
+ response_text = response.output
214
+ elif hasattr(response, 'value'):
215
+ # Some other response type with value field
216
+ response_text = str(response.value)
217
+ elif isinstance(response, str):
218
+ # Already a string
219
+ response_text = response
220
+ else:
221
+ # Last resort: convert to string
222
+ response_text = str(response)
223
+
224
+ # Add response to wrapper state
225
+ state.messages.append(AIMessage(content=response_text))
226
+ return state
227
+
228
+ async def capture_ai_response_node(self, state: AutoMemoryWrapperState) -> AutoMemoryWrapperState:
229
+ """Captures agent response to memory"""
230
+ if not self.save_ai_responses or not state.messages:
231
+ return state
232
+
233
+ # Get the latest AI message
234
+ ai_message = state.messages[-1]
235
+ if isinstance(ai_message, AIMessage):
236
+ # Get user_id from runtime context
237
+ user_id = self._get_user_id_from_context()
238
+
239
+ # Add to memory
240
+ await self.memory_editor.add_items(
241
+ [MemoryItem(conversation=[{
242
+ "role": "assistant", "content": str(ai_message.content)
243
+ }], user_id=user_id)],
244
+ **self.add_params)
245
+ return state
246
+
247
+ def build_graph(self) -> CompiledStateGraph:
248
+ """Wraps inner agent with memory nodes"""
249
+ workflow = StateGraph(AutoMemoryWrapperState)
250
+
251
+ # Add nodes
252
+ if self.save_user_messages:
253
+ workflow.add_node("capture_user_message", self.capture_user_message_node)
254
+ if self.retrieve_memory:
255
+ workflow.add_node("memory_retrieve", self.memory_retrieve_node)
256
+ workflow.add_node("inner_agent", self.inner_agent_node)
257
+ if self.save_ai_responses:
258
+ workflow.add_node("capture_ai_response", self.capture_ai_response_node)
259
+
260
+ # Connect nodes based on enabled features
261
+ workflow.set_entry_point("capture_user_message" if self.save_user_messages else "memory_retrieve" if self.
262
+ retrieve_memory else "inner_agent")
263
+
264
+ if self.save_user_messages and self.retrieve_memory:
265
+ workflow.add_edge("capture_user_message", "memory_retrieve")
266
+ workflow.add_edge("memory_retrieve", "inner_agent")
267
+ elif self.save_user_messages:
268
+ workflow.add_edge("capture_user_message", "inner_agent")
269
+ elif self.retrieve_memory:
270
+ workflow.add_edge("memory_retrieve", "inner_agent")
271
+
272
+ if self.save_ai_responses:
273
+ workflow.add_edge("inner_agent", "capture_ai_response")
274
+ workflow.set_finish_point("capture_ai_response")
275
+ else:
276
+ workflow.set_finish_point("inner_agent")
277
+
278
+ return workflow.compile()
@@ -0,0 +1,227 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ import logging
17
+ from collections.abc import AsyncGenerator
18
+ from typing import Any
19
+
20
+ from pydantic import Field
21
+
22
+ from nat.builder.builder import Builder
23
+ from nat.builder.framework_enum import LLMFrameworkEnum
24
+ from nat.builder.function_info import FunctionInfo
25
+ from nat.cli.register_workflow import register_function
26
+ from nat.data_models.agent import AgentBaseConfig
27
+ from nat.data_models.component_ref import FunctionRef
28
+ from nat.data_models.component_ref import MemoryRef
29
+
30
+ logger = logging.getLogger(__name__)
31
+
32
+
33
+ class AutoMemoryAgentConfig(AgentBaseConfig, name="auto_memory_agent"):
34
+ """
35
+ Wraps any NAT agent to provide automatic memory capture and retrieval.
36
+
37
+ This agent automatically captures user messages, retrieves relevant context,
38
+ and stores agent responses without requiring the LLM to invoke memory tools.
39
+
40
+ **Use this when:**
41
+ - You want guaranteed memory capture (not dependent on LLM tool calling)
42
+ - You need consistent memory operations across all interactions
43
+ - Your memory backend (Zep, Mem0) is designed for automatic memory management
44
+
45
+ **Use tool-based memory when:**
46
+ - You want the LLM to decide when to access memory
47
+ - Memory operations should be selective based on context
48
+
49
+ **Example:**
50
+
51
+ .. code-block:: yaml
52
+
53
+ functions:
54
+ my_react_agent:
55
+ _type: react_agent
56
+ llm_name: nim_llm
57
+ tool_names: [calculator, web_search]
58
+
59
+ memory:
60
+ zep_memory:
61
+ _type: nat.plugins.zep_cloud/zep_memory
62
+
63
+ workflow:
64
+ _type: auto_memory_agent
65
+ inner_agent_name: my_react_agent
66
+ memory_name: zep_memory
67
+ llm_name: nim_llm
68
+ verbose: true
69
+
70
+ **Multi-tenant User Isolation:**
71
+
72
+ User ID is automatically extracted from runtime context (user_manager.get_id()) for proper
73
+ multi-tenant memory isolation. Set user_manager via SessionManager.session() in production.
74
+ Defaults to "default_user" for testing/development. See README.md for deployment examples.
75
+ """
76
+
77
+ # Memory configuration
78
+ memory_name: MemoryRef = Field(..., description="Name of the memory backend (from memory section of config)")
79
+
80
+ # Reference to inner agent by NAME (not inline config)
81
+ inner_agent_name: FunctionRef = Field(..., description="Name of the agent workflow to wrap with automatic memory")
82
+
83
+ # Feature flags
84
+ save_user_messages_to_memory: bool = Field(
85
+ default=True, description="Automatically save user messages to memory before agent processing")
86
+ retrieve_memory_for_every_response: bool = Field(
87
+ default=True,
88
+ description=("Automatically retrieve memory context before agent processing. "
89
+ "Set to false for save-only mode or when using tool-based retrieval."))
90
+ save_ai_messages_to_memory: bool = Field(
91
+ default=True, description="Automatically save AI agent responses to memory after generation")
92
+
93
+ # Memory retrieval configuration
94
+ search_params: dict[str, Any] = Field(
95
+ default_factory=dict,
96
+ description=(
97
+ "Backend-specific search parameters passed to memory_editor.search().\n"
98
+ "Common parameters:\n"
99
+ " - top_k (int): Maximum results to return (default: 5)\n"
100
+ " - mode (str): For Zep, 'basic' (fast) or 'summary' (comprehensive)\n\n"
101
+ "Additional parameters:\n"
102
+ " - Any additional parameters that the chosen memory backend supports in its search function\n\n"))
103
+
104
+ # Memory addition configuration
105
+ add_params: dict[str, Any] = Field(
106
+ default_factory=dict,
107
+ description=(
108
+ "Backend-specific parameters passed to memory_editor.add_items().\n"
109
+ "For Zep:\n"
110
+ " - ignore_roles (list[str]): Role types to exclude from graph memory (e.g., ['assistant'])\n"
111
+ " Available roles: norole, system, assistant, user, function, tool\n\n"
112
+ "Additional parameters:\n"
113
+ " - Any additional parameters that the chosen memory backend supports in its add_items function\n\n"))
114
+
115
+
116
+ @register_function(config_type=AutoMemoryAgentConfig, framework_wrappers=[LLMFrameworkEnum.LANGCHAIN])
117
+ async def auto_memory_agent(config: AutoMemoryAgentConfig, builder: Builder) -> AsyncGenerator[FunctionInfo, None]:
118
+ """
119
+ Build the auto-memory agent that wraps another agent.
120
+
121
+ The inner agent is retrieved as a Function that receives a ChatRequest with
122
+ multiple messages (including system messages with memory context). It manages
123
+ its own internal state (ReActGraphState, etc.) and the wrapper never manipulates
124
+ that state.
125
+ """
126
+ from langchain_core.messages.human import HumanMessage
127
+ from langgraph.graph.state import CompiledStateGraph
128
+
129
+ from nat.agent.auto_memory_wrapper.agent import AutoMemoryWrapperGraph
130
+ from nat.agent.auto_memory_wrapper.state import AutoMemoryWrapperState
131
+ from nat.agent.base import AGENT_LOG_PREFIX
132
+
133
+ # Get memory editor from builder
134
+ memory_editor = await builder.get_memory_client(config.memory_name)
135
+
136
+ # Get inner agent as a Function (not a dict config)
137
+ # This gives us a function that accepts ChatRequest with multiple messages
138
+ inner_agent_fn = await builder.get_function(config.inner_agent_name)
139
+
140
+ # Get inner agent config to calculate recursion limits
141
+ inner_agent_config = builder.get_function_config(config.inner_agent_name)
142
+
143
+ # Calculate recursion_limit based on inner agent's configuration
144
+ # This ensures the wrapper is transparent - users only configure the inner agent's limits
145
+ # and the wrapper automatically accounts for its own overhead
146
+ inner_max_calls = None
147
+
148
+ if hasattr(inner_agent_config, 'max_tool_calls'):
149
+ # ReAct agent and similar agents use max_tool_calls
150
+ value = inner_agent_config.max_tool_calls
151
+ if value is not None and isinstance(value, int | float):
152
+ inner_max_calls = value
153
+
154
+ if inner_max_calls is None and hasattr(inner_agent_config, 'max_iterations'):
155
+ # Some agents use max_iterations as an alias
156
+ value = inner_agent_config.max_iterations
157
+ if value is not None and isinstance(value, int | float):
158
+ inner_max_calls = value
159
+
160
+ if inner_max_calls is None and hasattr(inner_agent_config, 'tool_call_max_retries'):
161
+ # ReWOO agent uses tool_call_max_retries - needs more steps per retry
162
+ value = inner_agent_config.tool_call_max_retries
163
+ if value is not None and isinstance(value, int | float):
164
+ inner_max_calls = value * 3
165
+
166
+ if inner_max_calls is None:
167
+ # Safe default for agents without explicit limits
168
+ inner_max_calls = 15
169
+
170
+ # Use same calculation formula as react_agent for consistency
171
+ # Formula: (max_tool_calls + 1) * 2 allows proper tool calling cycles with retries
172
+ # See src/nat/agent/react_agent/register.py:145 for reference
173
+ inner_agent_recursion = (int(inner_max_calls) + 1) * 2
174
+
175
+ # Create wrapper
176
+ wrapper_graph = AutoMemoryWrapperGraph(inner_agent_fn=inner_agent_fn,
177
+ memory_editor=memory_editor,
178
+ save_user_messages=config.save_user_messages_to_memory,
179
+ retrieve_memory=config.retrieve_memory_for_every_response,
180
+ save_ai_responses=config.save_ai_messages_to_memory,
181
+ search_params=config.search_params,
182
+ add_params=config.add_params)
183
+
184
+ # Calculate total recursion limit: wrapper overhead + inner agent needs
185
+ wrapper_node_count = wrapper_graph.get_wrapper_node_count()
186
+ total_recursion_limit = wrapper_node_count + inner_agent_recursion
187
+
188
+ logger.debug(f"{AGENT_LOG_PREFIX} Auto-memory wrapper calculated recursion_limit={total_recursion_limit} "
189
+ f"(wrapper_overhead={wrapper_node_count} + inner_agent={inner_agent_recursion})")
190
+
191
+ # Build the graph
192
+ graph: CompiledStateGraph = wrapper_graph.build_graph()
193
+
194
+ async def _response_fn(input_message: str) -> str:
195
+ """
196
+ Main workflow entry function for the auto-memory agent.
197
+
198
+ Args:
199
+ input_message (str): The input message to process
200
+
201
+ Returns:
202
+ str: The response from the wrapped agent
203
+ """
204
+ try:
205
+ message = HumanMessage(content=input_message)
206
+ state = AutoMemoryWrapperState(messages=[message])
207
+
208
+ # Pass calculated recursion_limit to ensure wrapper + inner agent have enough steps
209
+ result_dict = await graph.ainvoke(state, config={'recursion_limit': total_recursion_limit})
210
+ result_state = AutoMemoryWrapperState(**result_dict)
211
+
212
+ output_message = result_state.messages[-1]
213
+ return str(output_message.content)
214
+
215
+ except Exception as ex:
216
+ logger.exception(f"{AGENT_LOG_PREFIX} Auto-memory agent failed with exception")
217
+ if config.verbose:
218
+ return str(ex)
219
+ return "Auto-memory agent failed"
220
+
221
+ try:
222
+ yield FunctionInfo.from_fn(_response_fn, description=config.description)
223
+ except GeneratorExit:
224
+ logger.debug("%s Workflow exited early!", AGENT_LOG_PREFIX)
225
+ raise
226
+ finally:
227
+ logger.debug("%s Cleaning up auto_memory_agent workflow.", AGENT_LOG_PREFIX)
@@ -0,0 +1,30 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ from langchain_core.messages import BaseMessage
17
+ from pydantic import BaseModel
18
+ from pydantic import Field
19
+
20
+
21
+ class AutoMemoryWrapperState(BaseModel):
22
+ """
23
+ Simple wrapper state - only needs to track messages.
24
+
25
+ The inner agent manages its own complex state internally
26
+ (ReActGraphState, ReWOOGraphState, etc.). The wrapper
27
+ never sees or manipulates the inner agent's state.
28
+ """
29
+ messages: list[BaseMessage] = Field(default_factory=list,
30
+ description="Conversation messages with context injection")
nat/agent/base.py CHANGED
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
nat/agent/dual_node.py CHANGED
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2021-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2021-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -33,6 +33,7 @@ from langchain_core.prompts import MessagesPlaceholder
33
33
  from langchain_core.runnables import Runnable
34
34
  from langchain_core.runnables.config import RunnableConfig
35
35
  from langchain_core.tools import BaseTool
36
+ from langgraph.runtime import DEFAULT_RUNTIME
36
37
  from pydantic import BaseModel
37
38
  from pydantic import Field
38
39
 
@@ -122,7 +123,7 @@ class ReActAgentGraph(DualNodeAgent):
122
123
  """
123
124
  # models that don't need (or don't support)a stop sequence
124
125
  smart_models = re.compile(r"gpt-?5", re.IGNORECASE)
125
- if any(smart_models.search(getattr(self.llm, model, "")) for model in ["model", "model_name"]):
126
+ if smart_models.search(str(getattr(self.llm, "model", ""))):
126
127
  # no need to bind any additional parameters to the LLM
127
128
  return self.llm
128
129
  # add a stop sequence to the LLM
@@ -162,7 +163,8 @@ class ReActAgentGraph(DualNodeAgent):
162
163
  {
163
164
  "question": question, "chat_history": chat_history
164
165
  },
165
- RunnableConfig(callbacks=self.callbacks) # type: ignore
166
+ RunnableConfig(callbacks=self.callbacks,
167
+ configurable={"__pregel_runtime": DEFAULT_RUNTIME}) # type: ignore
166
168
  )
167
169
 
168
170
  if self.detailed_logs:
@@ -184,10 +186,13 @@ class ReActAgentGraph(DualNodeAgent):
184
186
  logger.debug("%s Querying agent, attempt: %s", AGENT_LOG_PREFIX, attempt)
185
187
 
186
188
  output_message = await self._stream_llm(
187
- self.agent, {
189
+ self.agent,
190
+ {
188
191
  "question": question, "agent_scratchpad": agent_scratchpad, "chat_history": chat_history
189
192
  },
190
- RunnableConfig(callbacks=self.callbacks))
193
+ RunnableConfig(callbacks=self.callbacks,
194
+ configurable={"__pregel_runtime": DEFAULT_RUNTIME}) # type: ignore
195
+ )
191
196
 
192
197
  if self.detailed_logs:
193
198
  logger.info(AGENT_CALL_LOG_MESSAGE, question, output_message.content)
@@ -321,10 +326,12 @@ class ReActAgentGraph(DualNodeAgent):
321
326
  tool_input = tool_input_str
322
327
 
323
328
  # Call tool once with the determined input (either parsed dict or raw string)
324
- tool_response = await self._call_tool(requested_tool,
325
- tool_input,
326
- RunnableConfig(callbacks=self.callbacks),
327
- max_retries=self.tool_call_max_retries)
329
+ tool_response = await self._call_tool(
330
+ requested_tool,
331
+ tool_input,
332
+ RunnableConfig(callbacks=self.callbacks,
333
+ configurable={"__pregel_runtime": DEFAULT_RUNTIME}), # type: ignore
334
+ max_retries=self.tool_call_max_retries)
328
335
 
329
336
  if self.detailed_logs:
330
337
  self._log_tool_response(requested_tool.name, tool_input, str(tool_response.content))
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,7 +15,7 @@
15
15
 
16
16
  import re
17
17
 
18
- from langchain.agents.agent import AgentOutputParser
18
+ from langchain_classic.agents.agent import AgentOutputParser
19
19
  from langchain_core.agents import AgentAction
20
20
  from langchain_core.agents import AgentFinish
21
21
  from langchain_core.exceptions import LangChainException