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
@@ -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");
@@ -39,6 +39,9 @@ from pydantic import BaseModel
39
39
  from pydantic import Field
40
40
  from starlette.websockets import WebSocket
41
41
 
42
+ from nat.builder.context import Context
43
+ from nat.builder.eval_builder import WorkflowEvalBuilder
44
+ from nat.builder.evaluator import EvaluatorInfo
42
45
  from nat.builder.function import Function
43
46
  from nat.builder.workflow_builder import WorkflowBuilder
44
47
  from nat.data_models.api_server import ChatRequest
@@ -51,11 +54,15 @@ from nat.data_models.object_store import NoSuchKeyError
51
54
  from nat.eval.config import EvaluationRunOutput
52
55
  from nat.eval.evaluate import EvaluationRun
53
56
  from nat.eval.evaluate import EvaluationRunConfig
57
+ from nat.eval.evaluator.evaluator_model import EvalInput
58
+ from nat.front_ends.fastapi.async_job import run_generation
54
59
  from nat.front_ends.fastapi.auth_flow_handlers.http_flow_handler import HTTPAuthenticationFlowHandler
55
60
  from nat.front_ends.fastapi.auth_flow_handlers.websocket_flow_handler import FlowState
56
61
  from nat.front_ends.fastapi.auth_flow_handlers.websocket_flow_handler import WebSocketAuthenticationFlowHandler
57
62
  from nat.front_ends.fastapi.fastapi_front_end_config import AsyncGenerateResponse
58
63
  from nat.front_ends.fastapi.fastapi_front_end_config import AsyncGenerationStatusResponse
64
+ from nat.front_ends.fastapi.fastapi_front_end_config import EvaluateItemRequest
65
+ from nat.front_ends.fastapi.fastapi_front_end_config import EvaluateItemResponse
59
66
  from nat.front_ends.fastapi.fastapi_front_end_config import EvaluateRequest
60
67
  from nat.front_ends.fastapi.fastapi_front_end_config import EvaluateResponse
61
68
  from nat.front_ends.fastapi.fastapi_front_end_config import EvaluateStatusResponse
@@ -69,6 +76,7 @@ from nat.front_ends.fastapi.utils import get_config_file_path
69
76
  from nat.object_store.models import ObjectStoreItem
70
77
  from nat.runtime.loader import load_workflow
71
78
  from nat.runtime.session import SessionManager
79
+ from nat.utils.log_utils import setup_logging
72
80
 
73
81
  logger = logging.getLogger(__name__)
74
82
 
@@ -100,6 +108,9 @@ class FastApiFrontEndPluginWorkerBase(ABC):
100
108
  self._scheduler_address = os.environ.get("NAT_DASK_SCHEDULER_ADDRESS")
101
109
  self._db_url = os.environ.get("NAT_JOB_STORE_DB_URL")
102
110
  self._config_file_path = get_config_file_path()
111
+ self._use_dask_threads = os.environ.get("NAT_USE_DASK_THREADS", "0") == "1"
112
+ self._log_level = int(os.environ.get("NAT_FASTAPI_LOG_LEVEL", logging.INFO))
113
+ setup_logging(self._log_level)
103
114
 
104
115
  if self._scheduler_address is not None:
105
116
  if not _DASK_AVAILABLE:
@@ -227,6 +238,78 @@ class FastApiFrontEndPluginWorker(FastApiFrontEndPluginWorkerBase):
227
238
  self._outstanding_flows: dict[str, FlowState] = {}
228
239
  self._outstanding_flows_lock = asyncio.Lock()
229
240
 
241
+ # Track session managers for each route
242
+ self._session_managers: list[SessionManager] = []
243
+
244
+ # Evaluator storage for single-item evaluation
245
+ self._evaluators: dict[str, EvaluatorInfo] = {}
246
+ self._eval_builder: WorkflowEvalBuilder | None = None
247
+
248
+ async def initialize_evaluators(self, config: Config):
249
+ """Initialize and store evaluators from config for single-item evaluation."""
250
+ if not config.eval or not config.eval.evaluators:
251
+ logger.info("No evaluators configured, skipping evaluator initialization")
252
+ return
253
+
254
+ try:
255
+ # Build evaluators using WorkflowEvalBuilder (same pattern as nat eval)
256
+ # Start with registry=None and let populate_builder set everything up
257
+ self._eval_builder = WorkflowEvalBuilder(general_config=config.general,
258
+ eval_general_config=config.eval.general,
259
+ registry=None)
260
+
261
+ # Enter the async context and keep it alive
262
+ await self._eval_builder.__aenter__()
263
+
264
+ # Populate builder with config (this sets up LLMs, functions, etc.)
265
+ # Skip workflow build since we already have it from the main builder
266
+ await self._eval_builder.populate_builder(config, skip_workflow=True)
267
+
268
+ # Now evaluators should be populated by populate_builder
269
+ for name in config.eval.evaluators.keys():
270
+ self._evaluators[name] = self._eval_builder.get_evaluator(name)
271
+ logger.info(f"Initialized evaluator: {name}")
272
+
273
+ logger.info(f"Successfully initialized {len(self._evaluators)} evaluators")
274
+
275
+ except Exception as e:
276
+ logger.error(f"Failed to initialize evaluators: {e}")
277
+ # Don't fail startup, just log the error
278
+ self._evaluators = {}
279
+
280
+ async def _create_session_manager(self,
281
+ builder: WorkflowBuilder,
282
+ entry_function: str | None = None) -> SessionManager:
283
+ """Create and register a SessionManager."""
284
+
285
+ sm = await SessionManager.create(config=self._config, shared_builder=builder, entry_function=entry_function)
286
+ self._session_managers.append(sm)
287
+
288
+ return sm
289
+
290
+ async def cleanup_session_managers(self):
291
+ """Clean up all SessionManager resources on shutdown."""
292
+ for sm in self._session_managers:
293
+ try:
294
+ await sm.shutdown()
295
+ except Exception as e:
296
+ logger.error(f"Error cleaning up SessionManager: {e}")
297
+
298
+ self._session_managers.clear()
299
+ logger.info("All SessionManagers cleaned up")
300
+
301
+ async def cleanup_evaluators(self):
302
+ """Clean up evaluator resources on shutdown."""
303
+ if self._eval_builder:
304
+ try:
305
+ await self._eval_builder.__aexit__(None, None, None)
306
+ logger.info("Evaluator builder context cleaned up")
307
+ except Exception as e:
308
+ logger.error(f"Error cleaning up evaluator builder: {e}")
309
+ finally:
310
+ self._eval_builder = None
311
+ self._evaluators.clear()
312
+
230
313
  def get_step_adaptor(self) -> StepAdaptor:
231
314
 
232
315
  return StepAdaptor(self.front_end_config.step_adaptor)
@@ -236,21 +319,34 @@ class FastApiFrontEndPluginWorker(FastApiFrontEndPluginWorkerBase):
236
319
  # Do things like setting the base URL and global configuration options
237
320
  app.root_path = self.front_end_config.root_path
238
321
 
322
+ # Initialize evaluators for single-item evaluation
323
+ # TODO: we need config control over this as it's not always needed
324
+ await self.initialize_evaluators(self._config)
325
+
326
+ # Ensure session manager resources are cleaned up when the app shuts down
327
+ app.add_event_handler("shutdown", self.cleanup_session_managers)
328
+
329
+ # Ensure evaluator resources are cleaned up when the app shuts down
330
+ app.add_event_handler("shutdown", self.cleanup_evaluators)
331
+
239
332
  await self.add_routes(app, builder)
240
333
 
241
334
  async def add_routes(self, app: FastAPI, builder: WorkflowBuilder):
242
335
 
243
- await self.add_default_route(app, SessionManager(await builder.build()))
244
- await self.add_evaluate_route(app, SessionManager(await builder.build()))
336
+ await self.add_default_route(app, await self._create_session_manager(builder))
337
+ await self.add_evaluate_route(app, await self._create_session_manager(builder))
338
+ await self.add_evaluate_item_route(app, await self._create_session_manager(builder))
339
+
245
340
  await self.add_static_files_route(app, builder)
246
341
  await self.add_authorization_route(app)
247
342
  await self.add_mcp_client_tool_list_route(app, builder)
343
+ await self.add_monitor_route(app)
248
344
 
249
345
  for ep in self.front_end_config.endpoints:
250
346
 
251
- entry_workflow = await builder.build(entry_function=ep.function_name)
252
-
253
- await self.add_route(app, endpoint=ep, session_manager=SessionManager(entry_workflow))
347
+ await self.add_route(app,
348
+ endpoint=ep,
349
+ session_manager=await self._create_session_manager(builder, ep.function_name))
254
350
 
255
351
  async def add_default_route(self, app: FastAPI, session_manager: SessionManager):
256
352
 
@@ -439,6 +535,69 @@ class FastApiFrontEndPluginWorker(FastApiFrontEndPluginWorkerBase):
439
535
  else:
440
536
  logger.warning("Dask is not available, evaluation endpoints will not be added.")
441
537
 
538
+ async def add_evaluate_item_route(self, app: FastAPI, session_manager: SessionManager):
539
+ """Add the single-item evaluation endpoint to the FastAPI app."""
540
+
541
+ async def evaluate_single_item(request: EvaluateItemRequest, http_request: Request) -> EvaluateItemResponse:
542
+ """Handle single-item evaluation requests."""
543
+
544
+ async with session_manager.session(http_connection=http_request):
545
+
546
+ # Check if evaluator exists
547
+ if request.evaluator_name not in self._evaluators:
548
+ raise HTTPException(status_code=404,
549
+ detail=f"Evaluator '{request.evaluator_name}' not found. "
550
+ f"Available evaluators: {list(self._evaluators.keys())}")
551
+
552
+ try:
553
+ # Get the evaluator
554
+ evaluator = self._evaluators[request.evaluator_name]
555
+
556
+ # Run evaluation on single item
557
+ result = await evaluator.evaluate_fn(EvalInput(eval_input_items=[request.item]))
558
+
559
+ # Extract the single output item
560
+ if result.eval_output_items:
561
+ output_item = result.eval_output_items[0]
562
+ return EvaluateItemResponse(success=True, result=output_item, error=None)
563
+ else:
564
+ return EvaluateItemResponse(success=False, result=None, error="Evaluator returned no results")
565
+
566
+ except Exception as e:
567
+ logger.exception(f"Error evaluating item with {request.evaluator_name}")
568
+ return EvaluateItemResponse(success=False, result=None, error=f"Evaluation failed: {str(e)}")
569
+
570
+ # Register the route
571
+ if self.front_end_config.evaluate_item.path:
572
+ app.add_api_route(path=self.front_end_config.evaluate_item.path,
573
+ endpoint=evaluate_single_item,
574
+ methods=[self.front_end_config.evaluate_item.method],
575
+ response_model=EvaluateItemResponse,
576
+ description=self.front_end_config.evaluate_item.description,
577
+ responses={
578
+ 404: {
579
+ "description": "Evaluator not found",
580
+ "content": {
581
+ "application/json": {
582
+ "example": {
583
+ "detail": "Evaluator 'unknown' not found"
584
+ }
585
+ }
586
+ }
587
+ },
588
+ 500: {
589
+ "description": "Internal Server Error",
590
+ "content": {
591
+ "application/json": {
592
+ "example": {
593
+ "detail": "Internal server error occurred"
594
+ }
595
+ }
596
+ }
597
+ }
598
+ })
599
+ logger.info(f"Added evaluate_item route at {self.front_end_config.evaluate_item.path}")
600
+
442
601
  async def add_static_files_route(self, app: FastAPI, builder: WorkflowBuilder):
443
602
 
444
603
  if not self.front_end_config.object_store:
@@ -538,11 +697,15 @@ class FastApiFrontEndPluginWorker(FastApiFrontEndPluginWorkerBase):
538
697
  endpoint: FastApiFrontEndConfig.EndpointBase,
539
698
  session_manager: SessionManager):
540
699
 
541
- workflow = session_manager.workflow
700
+ GenerateBodyType = session_manager.get_workflow_input_schema()
701
+ GenerateStreamResponseType = session_manager.get_workflow_streaming_output_schema()
702
+ GenerateSingleResponseType = session_manager.get_workflow_single_output_schema()
542
703
 
543
- GenerateBodyType = workflow.input_schema
544
- GenerateStreamResponseType = workflow.streaming_output_schema
545
- GenerateSingleResponseType = workflow.single_output_schema
704
+ def add_context_headers_to_response(response: Response) -> None:
705
+ """Add context-based headers to response if available."""
706
+ observability_trace_id = Context.get().observability_trace_id
707
+ if observability_trace_id:
708
+ response.headers["Observability-Trace-Id"] = observability_trace_id
546
709
 
547
710
  # Skip async generation for custom routes (those with function_name)
548
711
  if self._dask_available and not hasattr(endpoint, 'function_name'):
@@ -591,10 +754,13 @@ class FastApiFrontEndPluginWorker(FastApiFrontEndPluginWorkerBase):
591
754
 
592
755
  response.headers["Content-Type"] = "application/json"
593
756
 
594
- async with session_manager.session(http_connection=request,
595
- user_authentication_callback=self._http_flow_handler.authenticate):
757
+ async with session_manager.session(
758
+ http_connection=request,
759
+ user_authentication_callback=self._http_flow_handler.authenticate) as session:
596
760
 
597
- return await generate_single_response(None, session_manager, result_type=result_type)
761
+ result = await generate_single_response(None, session, result_type=result_type)
762
+ add_context_headers_to_response(response)
763
+ return result
598
764
 
599
765
  return get_single
600
766
 
@@ -602,13 +768,14 @@ class FastApiFrontEndPluginWorker(FastApiFrontEndPluginWorkerBase):
602
768
 
603
769
  async def get_stream(request: Request):
604
770
 
605
- async with session_manager.session(http_connection=request,
606
- user_authentication_callback=self._http_flow_handler.authenticate):
771
+ async with session_manager.session(
772
+ http_connection=request,
773
+ user_authentication_callback=self._http_flow_handler.authenticate) as session:
607
774
 
608
775
  return StreamingResponse(headers={"Content-Type": "text/event-stream; charset=utf-8"},
609
776
  content=generate_streaming_response_as_str(
610
777
  None,
611
- session_manager=session_manager,
778
+ session=session,
612
779
  streaming=streaming,
613
780
  step_adaptor=self.get_step_adaptor(),
614
781
  result_type=result_type,
@@ -620,14 +787,14 @@ class FastApiFrontEndPluginWorker(FastApiFrontEndPluginWorkerBase):
620
787
 
621
788
  async def get_stream(filter_steps: str | None = None):
622
789
 
623
- return StreamingResponse(headers={"Content-Type": "text/event-stream; charset=utf-8"},
624
- content=generate_streaming_response_full_as_str(
625
- None,
626
- session_manager=session_manager,
627
- streaming=streaming,
628
- result_type=result_type,
629
- output_type=output_type,
630
- filter_steps=filter_steps))
790
+ async with session_manager.session(http_connection=None) as session:
791
+ return StreamingResponse(headers={"Content-Type": "text/event-stream; charset=utf-8"},
792
+ content=generate_streaming_response_full_as_str(None,
793
+ session=session,
794
+ streaming=streaming,
795
+ result_type=result_type,
796
+ output_type=output_type,
797
+ filter_steps=filter_steps))
631
798
 
632
799
  return get_stream
633
800
 
@@ -637,10 +804,13 @@ class FastApiFrontEndPluginWorker(FastApiFrontEndPluginWorkerBase):
637
804
 
638
805
  response.headers["Content-Type"] = "application/json"
639
806
 
640
- async with session_manager.session(http_connection=request,
641
- user_authentication_callback=self._http_flow_handler.authenticate):
807
+ async with session_manager.session(
808
+ http_connection=request,
809
+ user_authentication_callback=self._http_flow_handler.authenticate) as session:
642
810
 
643
- return await generate_single_response(payload, session_manager, result_type=result_type)
811
+ result = await generate_single_response(payload, session, result_type=result_type)
812
+ add_context_headers_to_response(response)
813
+ return result
644
814
 
645
815
  return post_single
646
816
 
@@ -651,13 +821,14 @@ class FastApiFrontEndPluginWorker(FastApiFrontEndPluginWorkerBase):
651
821
 
652
822
  async def post_stream(request: Request, payload: request_type):
653
823
 
654
- async with session_manager.session(http_connection=request,
655
- user_authentication_callback=self._http_flow_handler.authenticate):
824
+ async with session_manager.session(
825
+ http_connection=request,
826
+ user_authentication_callback=self._http_flow_handler.authenticate) as session:
656
827
 
657
828
  return StreamingResponse(headers={"Content-Type": "text/event-stream; charset=utf-8"},
658
829
  content=generate_streaming_response_as_str(
659
830
  payload,
660
- session_manager=session_manager,
831
+ session=session,
661
832
  streaming=streaming,
662
833
  step_adaptor=self.get_step_adaptor(),
663
834
  result_type=result_type,
@@ -675,14 +846,14 @@ class FastApiFrontEndPluginWorker(FastApiFrontEndPluginWorkerBase):
675
846
 
676
847
  async def post_stream(payload: request_type, filter_steps: str | None = None):
677
848
 
678
- return StreamingResponse(headers={"Content-Type": "text/event-stream; charset=utf-8"},
679
- content=generate_streaming_response_full_as_str(
680
- payload,
681
- session_manager=session_manager,
682
- streaming=streaming,
683
- result_type=result_type,
684
- output_type=output_type,
685
- filter_steps=filter_steps))
849
+ async with session_manager.session(http_connection=None) as session:
850
+ return StreamingResponse(headers={"Content-Type": "text/event-stream; charset=utf-8"},
851
+ content=generate_streaming_response_full_as_str(payload,
852
+ session=session,
853
+ streaming=streaming,
854
+ result_type=result_type,
855
+ output_type=output_type,
856
+ filter_steps=filter_steps))
686
857
 
687
858
  return post_stream
688
859
 
@@ -698,20 +869,22 @@ class FastApiFrontEndPluginWorker(FastApiFrontEndPluginWorkerBase):
698
869
  response.headers["Content-Type"] = "application/json"
699
870
  stream_requested = getattr(payload, 'stream', False)
700
871
 
701
- async with session_manager.session(http_connection=request):
872
+ async with session_manager.session(http_connection=request) as session:
702
873
  if stream_requested:
703
874
 
704
875
  # Return streaming response
705
876
  return StreamingResponse(headers={"Content-Type": "text/event-stream; charset=utf-8"},
706
877
  content=generate_streaming_response_as_str(
707
878
  payload,
708
- session_manager=session_manager,
879
+ session=session,
709
880
  streaming=True,
710
881
  step_adaptor=self.get_step_adaptor(),
711
882
  result_type=ChatResponseChunk,
712
883
  output_type=ChatResponseChunk))
713
884
 
714
- return await generate_single_response(payload, session_manager, result_type=ChatResponse)
885
+ result = await generate_single_response(payload, session, result_type=ChatResponse)
886
+ add_context_headers_to_response(response)
887
+ return result
715
888
 
716
889
  return post_openai_api_compatible
717
890
 
@@ -732,23 +905,6 @@ class FastApiFrontEndPluginWorker(FastApiFrontEndPluginWorkerBase):
732
905
  updated_at=job.updated_at,
733
906
  expires_at=self._job_store.get_expires_at(job))
734
907
 
735
- async def run_generation(scheduler_address: str,
736
- db_url: str,
737
- config_file_path: str,
738
- job_id: str,
739
- payload: typing.Any):
740
- """Background task to run the workflow."""
741
- job_store = JobStore(scheduler_address=scheduler_address, db_url=db_url)
742
- try:
743
- async with load_workflow(config_file_path) as local_session_manager:
744
- result = await generate_single_response(
745
- payload, local_session_manager, result_type=local_session_manager.workflow.single_output_schema)
746
-
747
- await job_store.update_status(job_id, JobStatus.SUCCESS, output=result)
748
- except Exception as e:
749
- logger.exception("Error in async job %s", job_id)
750
- await job_store.update_status(job_id, JobStatus.FAILURE, error=str(e))
751
-
752
908
  def post_async_generation(request_type: type):
753
909
 
754
910
  async def start_async_generation(
@@ -771,6 +927,8 @@ class FastApiFrontEndPluginWorker(FastApiFrontEndPluginWorkerBase):
771
927
  job_fn=run_generation,
772
928
  sync_timeout=request.sync_timeout,
773
929
  job_args=[
930
+ not self._use_dask_threads,
931
+ self._log_level,
774
932
  self._scheduler_address,
775
933
  self._db_url,
776
934
  self._config_file_path,
@@ -1104,7 +1262,7 @@ class FastApiFrontEndPluginWorker(FastApiFrontEndPluginWorkerBase):
1104
1262
  if configured_group.config.type != "mcp_client":
1105
1263
  continue
1106
1264
 
1107
- from nat.plugins.mcp.client_config import MCPClientConfig
1265
+ from nat.plugins.mcp.client.client_config import MCPClientConfig
1108
1266
 
1109
1267
  config = configured_group.config
1110
1268
  assert isinstance(config, MCPClientConfig)
@@ -1253,6 +1411,107 @@ class FastApiFrontEndPluginWorker(FastApiFrontEndPluginWorkerBase):
1253
1411
  }
1254
1412
  })
1255
1413
 
1414
+ async def add_monitor_route(self, app: FastAPI):
1415
+ """Add the per-user monitoring endpoint to the FastAPI app.
1416
+
1417
+ Security Warning:
1418
+ This endpoint exposes per-user identifiers and usage metrics. It should be
1419
+ protected by deploying behind an internal network, a reverse proxy with
1420
+ authentication, or similar access controls to prevent exposure to untrusted callers.
1421
+ """
1422
+ # Check if monitoring is enabled in config
1423
+ if not self._config.general.enable_per_user_monitoring:
1424
+ logger.debug("Per-user monitoring disabled, skipping /monitor/users endpoint")
1425
+ return
1426
+
1427
+ from nat.runtime.metrics import PerUserMetricsCollector
1428
+ from nat.runtime.metrics import PerUserMonitorResponse
1429
+ from nat.runtime.metrics import PerUserResourceUsage
1430
+
1431
+ async def get_per_user_metrics(user_id: str | None = None) -> PerUserMonitorResponse:
1432
+ """
1433
+ Get resource usage metrics for per-user workflows.
1434
+
1435
+ Args:
1436
+ user_id: Optional user ID to filter metrics for a specific user
1437
+
1438
+ Returns:
1439
+ PerUserMonitorResponse with metrics for all or specified users
1440
+ """
1441
+ # Collect metrics from all session managers that have per-user workflows
1442
+ all_users: list[PerUserResourceUsage] = []
1443
+
1444
+ for session_manager in self._session_managers:
1445
+ if not session_manager.is_workflow_per_user:
1446
+ continue
1447
+
1448
+ collector = PerUserMetricsCollector(session_manager)
1449
+
1450
+ if user_id is not None:
1451
+ # Filter for specific user
1452
+ user_metrics = await collector.collect_user_metrics(user_id)
1453
+ if user_metrics:
1454
+ all_users.append(user_metrics)
1455
+ else:
1456
+ # Get all users
1457
+ response = await collector.collect_all_metrics()
1458
+ all_users.extend(response.users)
1459
+
1460
+ from datetime import datetime
1461
+ return PerUserMonitorResponse(
1462
+ timestamp=datetime.now(),
1463
+ total_active_users=len(all_users),
1464
+ users=all_users,
1465
+ )
1466
+
1467
+ # Register the monitoring endpoint
1468
+ app.add_api_route(path="/monitor/users",
1469
+ endpoint=get_per_user_metrics,
1470
+ methods=["GET"],
1471
+ response_model=PerUserMonitorResponse,
1472
+ description="Get resource usage metrics for per-user workflows",
1473
+ tags=["Monitoring"],
1474
+ responses={
1475
+ 200: {
1476
+ "description": "Successfully retrieved per-user metrics",
1477
+ "content": {
1478
+ "application/json": {
1479
+ "example": {
1480
+ "timestamp":
1481
+ "2025-12-16T10:30:00Z",
1482
+ "total_active_users":
1483
+ 2,
1484
+ "users": [{
1485
+ "user_id": "alice",
1486
+ "session": {
1487
+ "created_at": "2025-12-16T09:00:00Z",
1488
+ "last_activity": "2025-12-16T10:29:55Z",
1489
+ "ref_count": 1,
1490
+ "is_active": True
1491
+ },
1492
+ "requests": {
1493
+ "total_requests": 42,
1494
+ "active_requests": 1,
1495
+ "avg_latency_ms": 1250.5,
1496
+ "error_count": 2
1497
+ },
1498
+ "memory": {
1499
+ "per_user_functions_count": 2,
1500
+ "per_user_function_groups_count": 1,
1501
+ "exit_stack_size": 3
1502
+ }
1503
+ }]
1504
+ }
1505
+ }
1506
+ }
1507
+ },
1508
+ 500: {
1509
+ "description": "Internal Server Error"
1510
+ }
1511
+ })
1512
+
1513
+ logger.info("Added per-user monitoring endpoint at /monitor/users")
1514
+
1256
1515
  async def _add_flow(self, state: str, flow_state: FlowState):
1257
1516
  async with self._outstanding_flows_lock:
1258
1517
  self._outstanding_flows[state] = flow_state
@@ -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) 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) 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");
@@ -32,6 +32,7 @@ async def pull_intermediate(_q, adapter):
32
32
  intermediate_done = asyncio.Event()
33
33
  context = Context.get()
34
34
  loop = asyncio.get_running_loop()
35
+ trace_id_emitted = False
35
36
 
36
37
  async def set_intermediate_done():
37
38
  intermediate_done.set()
@@ -43,6 +44,16 @@ async def pull_intermediate(_q, adapter):
43
44
  If adapter is None, convert the raw IntermediateStep into the complete
44
45
  ResponseIntermediateStep and place it into the queue.
45
46
  """
47
+ nonlocal trace_id_emitted
48
+
49
+ # Check if trace ID is now available and emit it once
50
+ if not trace_id_emitted:
51
+ observability_trace_id = context.observability_trace_id
52
+ if observability_trace_id:
53
+ from nat.data_models.api_server import ResponseObservabilityTrace
54
+ loop.create_task(_q.put(ResponseObservabilityTrace(observability_trace_id=observability_trace_id)))
55
+ trace_id_emitted = True
56
+
46
57
  if adapter is None:
47
58
  adapted = ResponseIntermediateStep(id=item.UUID,
48
59
  type=item.event_type,