nvidia-nat 1.3.0.dev2__py3-none-any.whl → 1.3.0rc1__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 (242) hide show
  1. aiq/__init__.py +2 -2
  2. nat/agent/base.py +24 -15
  3. nat/agent/dual_node.py +9 -4
  4. nat/agent/prompt_optimizer/prompt.py +68 -0
  5. nat/agent/prompt_optimizer/register.py +149 -0
  6. nat/agent/react_agent/agent.py +79 -47
  7. nat/agent/react_agent/register.py +41 -21
  8. nat/agent/reasoning_agent/reasoning_agent.py +11 -9
  9. nat/agent/register.py +1 -1
  10. nat/agent/rewoo_agent/agent.py +326 -148
  11. nat/agent/rewoo_agent/prompt.py +19 -22
  12. nat/agent/rewoo_agent/register.py +46 -26
  13. nat/agent/tool_calling_agent/agent.py +84 -28
  14. nat/agent/tool_calling_agent/register.py +51 -28
  15. nat/authentication/api_key/api_key_auth_provider.py +2 -2
  16. nat/authentication/credential_validator/bearer_token_validator.py +557 -0
  17. nat/authentication/http_basic_auth/http_basic_auth_provider.py +1 -1
  18. nat/authentication/interfaces.py +5 -2
  19. nat/authentication/oauth2/oauth2_auth_code_flow_provider.py +40 -20
  20. nat/authentication/oauth2/oauth2_resource_server_config.py +124 -0
  21. nat/authentication/register.py +0 -1
  22. nat/builder/builder.py +56 -24
  23. nat/builder/component_utils.py +9 -5
  24. nat/builder/context.py +46 -11
  25. nat/builder/eval_builder.py +16 -11
  26. nat/builder/framework_enum.py +1 -0
  27. nat/builder/front_end.py +1 -1
  28. nat/builder/function.py +378 -8
  29. nat/builder/function_base.py +3 -3
  30. nat/builder/function_info.py +6 -8
  31. nat/builder/user_interaction_manager.py +2 -2
  32. nat/builder/workflow.py +13 -1
  33. nat/builder/workflow_builder.py +281 -76
  34. nat/cli/cli_utils/config_override.py +2 -2
  35. nat/cli/commands/evaluate.py +1 -1
  36. nat/cli/commands/info/info.py +16 -6
  37. nat/cli/commands/info/list_channels.py +1 -1
  38. nat/cli/commands/info/list_components.py +7 -8
  39. nat/cli/commands/mcp/__init__.py +14 -0
  40. nat/cli/commands/mcp/mcp.py +986 -0
  41. nat/cli/commands/object_store/__init__.py +14 -0
  42. nat/cli/commands/object_store/object_store.py +227 -0
  43. nat/cli/commands/optimize.py +90 -0
  44. nat/cli/commands/registry/publish.py +2 -2
  45. nat/cli/commands/registry/pull.py +2 -2
  46. nat/cli/commands/registry/remove.py +2 -2
  47. nat/cli/commands/registry/search.py +15 -17
  48. nat/cli/commands/start.py +16 -5
  49. nat/cli/commands/uninstall.py +1 -1
  50. nat/cli/commands/workflow/templates/config.yml.j2 +0 -1
  51. nat/cli/commands/workflow/templates/pyproject.toml.j2 +4 -1
  52. nat/cli/commands/workflow/templates/register.py.j2 +0 -1
  53. nat/cli/commands/workflow/workflow_commands.py +9 -13
  54. nat/cli/entrypoint.py +8 -10
  55. nat/cli/register_workflow.py +38 -4
  56. nat/cli/type_registry.py +75 -6
  57. nat/control_flow/__init__.py +0 -0
  58. nat/control_flow/register.py +20 -0
  59. nat/control_flow/router_agent/__init__.py +0 -0
  60. nat/control_flow/router_agent/agent.py +329 -0
  61. nat/control_flow/router_agent/prompt.py +48 -0
  62. nat/control_flow/router_agent/register.py +91 -0
  63. nat/control_flow/sequential_executor.py +166 -0
  64. nat/data_models/agent.py +34 -0
  65. nat/data_models/api_server.py +10 -10
  66. nat/data_models/authentication.py +23 -9
  67. nat/data_models/common.py +1 -1
  68. nat/data_models/component.py +2 -0
  69. nat/data_models/component_ref.py +11 -0
  70. nat/data_models/config.py +41 -17
  71. nat/data_models/dataset_handler.py +1 -1
  72. nat/data_models/discovery_metadata.py +4 -4
  73. nat/data_models/evaluate.py +4 -1
  74. nat/data_models/function.py +34 -0
  75. nat/data_models/function_dependencies.py +14 -6
  76. nat/data_models/gated_field_mixin.py +242 -0
  77. nat/data_models/intermediate_step.py +3 -3
  78. nat/data_models/optimizable.py +119 -0
  79. nat/data_models/optimizer.py +149 -0
  80. nat/data_models/swe_bench_model.py +1 -1
  81. nat/data_models/temperature_mixin.py +44 -0
  82. nat/data_models/thinking_mixin.py +86 -0
  83. nat/data_models/top_p_mixin.py +44 -0
  84. nat/embedder/nim_embedder.py +1 -1
  85. nat/embedder/openai_embedder.py +1 -1
  86. nat/embedder/register.py +0 -1
  87. nat/eval/config.py +3 -1
  88. nat/eval/dataset_handler/dataset_handler.py +71 -7
  89. nat/eval/evaluate.py +86 -31
  90. nat/eval/evaluator/base_evaluator.py +1 -1
  91. nat/eval/evaluator/evaluator_model.py +13 -0
  92. nat/eval/intermediate_step_adapter.py +1 -1
  93. nat/eval/rag_evaluator/evaluate.py +2 -2
  94. nat/eval/rag_evaluator/register.py +3 -3
  95. nat/eval/register.py +4 -1
  96. nat/eval/remote_workflow.py +3 -3
  97. nat/eval/runtime_evaluator/__init__.py +14 -0
  98. nat/eval/runtime_evaluator/evaluate.py +123 -0
  99. nat/eval/runtime_evaluator/register.py +100 -0
  100. nat/eval/swe_bench_evaluator/evaluate.py +6 -6
  101. nat/eval/trajectory_evaluator/evaluate.py +1 -1
  102. nat/eval/trajectory_evaluator/register.py +1 -1
  103. nat/eval/tunable_rag_evaluator/evaluate.py +4 -7
  104. nat/eval/utils/eval_trace_ctx.py +89 -0
  105. nat/eval/utils/weave_eval.py +18 -9
  106. nat/experimental/decorators/experimental_warning_decorator.py +27 -7
  107. nat/experimental/test_time_compute/functions/plan_select_execute_function.py +7 -3
  108. nat/experimental/test_time_compute/functions/ttc_tool_orchestration_function.py +3 -3
  109. nat/experimental/test_time_compute/functions/ttc_tool_wrapper_function.py +1 -1
  110. nat/experimental/test_time_compute/models/strategy_base.py +5 -4
  111. nat/experimental/test_time_compute/register.py +0 -1
  112. nat/experimental/test_time_compute/selection/llm_based_output_merging_selector.py +1 -3
  113. nat/front_ends/console/authentication_flow_handler.py +82 -30
  114. nat/front_ends/console/console_front_end_plugin.py +8 -5
  115. nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py +52 -17
  116. nat/front_ends/fastapi/dask_client_mixin.py +65 -0
  117. nat/front_ends/fastapi/fastapi_front_end_config.py +36 -5
  118. nat/front_ends/fastapi/fastapi_front_end_controller.py +4 -4
  119. nat/front_ends/fastapi/fastapi_front_end_plugin.py +135 -4
  120. nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py +481 -281
  121. nat/front_ends/fastapi/job_store.py +518 -99
  122. nat/front_ends/fastapi/main.py +11 -19
  123. nat/front_ends/fastapi/message_handler.py +13 -14
  124. nat/front_ends/fastapi/message_validator.py +17 -19
  125. nat/front_ends/fastapi/response_helpers.py +4 -4
  126. nat/front_ends/fastapi/step_adaptor.py +2 -2
  127. nat/front_ends/fastapi/utils.py +57 -0
  128. nat/front_ends/mcp/introspection_token_verifier.py +73 -0
  129. nat/front_ends/mcp/mcp_front_end_config.py +10 -1
  130. nat/front_ends/mcp/mcp_front_end_plugin.py +45 -13
  131. nat/front_ends/mcp/mcp_front_end_plugin_worker.py +116 -8
  132. nat/front_ends/mcp/tool_converter.py +44 -14
  133. nat/front_ends/register.py +0 -1
  134. nat/front_ends/simple_base/simple_front_end_plugin_base.py +3 -1
  135. nat/llm/aws_bedrock_llm.py +24 -12
  136. nat/llm/azure_openai_llm.py +13 -6
  137. nat/llm/litellm_llm.py +69 -0
  138. nat/llm/nim_llm.py +20 -8
  139. nat/llm/openai_llm.py +14 -6
  140. nat/llm/register.py +4 -1
  141. nat/llm/utils/env_config_value.py +2 -3
  142. nat/llm/utils/thinking.py +215 -0
  143. nat/meta/pypi.md +9 -9
  144. nat/object_store/register.py +0 -1
  145. nat/observability/exporter/base_exporter.py +3 -3
  146. nat/observability/exporter/file_exporter.py +1 -1
  147. nat/observability/exporter/processing_exporter.py +309 -81
  148. nat/observability/exporter/span_exporter.py +1 -1
  149. nat/observability/exporter_manager.py +7 -7
  150. nat/observability/mixin/file_mixin.py +7 -7
  151. nat/observability/mixin/redaction_config_mixin.py +42 -0
  152. nat/observability/mixin/tagging_config_mixin.py +62 -0
  153. nat/observability/mixin/type_introspection_mixin.py +420 -107
  154. nat/observability/processor/batching_processor.py +5 -7
  155. nat/observability/processor/falsy_batch_filter_processor.py +55 -0
  156. nat/observability/processor/processor.py +3 -0
  157. nat/observability/processor/processor_factory.py +70 -0
  158. nat/observability/processor/redaction/__init__.py +24 -0
  159. nat/observability/processor/redaction/contextual_redaction_processor.py +125 -0
  160. nat/observability/processor/redaction/contextual_span_redaction_processor.py +66 -0
  161. nat/observability/processor/redaction/redaction_processor.py +177 -0
  162. nat/observability/processor/redaction/span_header_redaction_processor.py +92 -0
  163. nat/observability/processor/span_tagging_processor.py +68 -0
  164. nat/observability/register.py +6 -4
  165. nat/profiler/calc/calc_runner.py +3 -4
  166. nat/profiler/callbacks/agno_callback_handler.py +1 -1
  167. nat/profiler/callbacks/langchain_callback_handler.py +6 -6
  168. nat/profiler/callbacks/llama_index_callback_handler.py +3 -3
  169. nat/profiler/callbacks/semantic_kernel_callback_handler.py +3 -3
  170. nat/profiler/data_frame_row.py +1 -1
  171. nat/profiler/decorators/framework_wrapper.py +62 -13
  172. nat/profiler/decorators/function_tracking.py +160 -3
  173. nat/profiler/forecasting/models/forecasting_base_model.py +3 -1
  174. nat/profiler/inference_optimization/bottleneck_analysis/simple_stack_analysis.py +1 -1
  175. nat/profiler/inference_optimization/data_models.py +3 -3
  176. nat/profiler/inference_optimization/experimental/prefix_span_analysis.py +7 -8
  177. nat/profiler/inference_optimization/token_uniqueness.py +1 -1
  178. nat/profiler/parameter_optimization/__init__.py +0 -0
  179. nat/profiler/parameter_optimization/optimizable_utils.py +93 -0
  180. nat/profiler/parameter_optimization/optimizer_runtime.py +67 -0
  181. nat/profiler/parameter_optimization/parameter_optimizer.py +153 -0
  182. nat/profiler/parameter_optimization/parameter_selection.py +107 -0
  183. nat/profiler/parameter_optimization/pareto_visualizer.py +380 -0
  184. nat/profiler/parameter_optimization/prompt_optimizer.py +384 -0
  185. nat/profiler/parameter_optimization/update_helpers.py +66 -0
  186. nat/profiler/profile_runner.py +14 -9
  187. nat/profiler/utils.py +4 -2
  188. nat/registry_handlers/local/local_handler.py +2 -2
  189. nat/registry_handlers/package_utils.py +1 -2
  190. nat/registry_handlers/pypi/pypi_handler.py +23 -26
  191. nat/registry_handlers/register.py +3 -4
  192. nat/registry_handlers/rest/rest_handler.py +12 -13
  193. nat/retriever/milvus/retriever.py +2 -2
  194. nat/retriever/nemo_retriever/retriever.py +1 -1
  195. nat/retriever/register.py +0 -1
  196. nat/runtime/loader.py +2 -2
  197. nat/runtime/runner.py +3 -2
  198. nat/runtime/session.py +43 -8
  199. nat/settings/global_settings.py +16 -5
  200. nat/tool/chat_completion.py +5 -2
  201. nat/tool/code_execution/local_sandbox/local_sandbox_server.py +3 -3
  202. nat/tool/datetime_tools.py +49 -9
  203. nat/tool/document_search.py +2 -2
  204. nat/tool/github_tools.py +450 -0
  205. nat/tool/nvidia_rag.py +1 -1
  206. nat/tool/register.py +2 -9
  207. nat/tool/retriever.py +3 -2
  208. nat/utils/callable_utils.py +70 -0
  209. nat/utils/data_models/schema_validator.py +3 -3
  210. nat/utils/exception_handlers/automatic_retries.py +104 -51
  211. nat/utils/exception_handlers/schemas.py +1 -1
  212. nat/utils/io/yaml_tools.py +2 -2
  213. nat/utils/log_levels.py +25 -0
  214. nat/utils/reactive/base/observable_base.py +2 -2
  215. nat/utils/reactive/base/observer_base.py +1 -1
  216. nat/utils/reactive/observable.py +2 -2
  217. nat/utils/reactive/observer.py +4 -4
  218. nat/utils/reactive/subscription.py +1 -1
  219. nat/utils/settings/global_settings.py +6 -8
  220. nat/utils/type_converter.py +4 -3
  221. nat/utils/type_utils.py +9 -5
  222. {nvidia_nat-1.3.0.dev2.dist-info → nvidia_nat-1.3.0rc1.dist-info}/METADATA +42 -16
  223. {nvidia_nat-1.3.0.dev2.dist-info → nvidia_nat-1.3.0rc1.dist-info}/RECORD +230 -189
  224. {nvidia_nat-1.3.0.dev2.dist-info → nvidia_nat-1.3.0rc1.dist-info}/entry_points.txt +1 -0
  225. nat/cli/commands/info/list_mcp.py +0 -304
  226. nat/tool/github_tools/create_github_commit.py +0 -133
  227. nat/tool/github_tools/create_github_issue.py +0 -87
  228. nat/tool/github_tools/create_github_pr.py +0 -106
  229. nat/tool/github_tools/get_github_file.py +0 -106
  230. nat/tool/github_tools/get_github_issue.py +0 -166
  231. nat/tool/github_tools/get_github_pr.py +0 -256
  232. nat/tool/github_tools/update_github_issue.py +0 -100
  233. nat/tool/mcp/exceptions.py +0 -142
  234. nat/tool/mcp/mcp_client.py +0 -255
  235. nat/tool/mcp/mcp_tool.py +0 -96
  236. nat/utils/exception_handlers/mcp.py +0 -211
  237. /nat/{tool/github_tools → agent/prompt_optimizer}/__init__.py +0 -0
  238. /nat/{tool/mcp → authentication/credential_validator}/__init__.py +0 -0
  239. {nvidia_nat-1.3.0.dev2.dist-info → nvidia_nat-1.3.0rc1.dist-info}/WHEEL +0 -0
  240. {nvidia_nat-1.3.0.dev2.dist-info → nvidia_nat-1.3.0rc1.dist-info}/licenses/LICENSE-3rd-party.txt +0 -0
  241. {nvidia_nat-1.3.0.dev2.dist-info → nvidia_nat-1.3.0rc1.dist-info}/licenses/LICENSE.md +0 -0
  242. {nvidia_nat-1.3.0.dev2.dist-info → nvidia_nat-1.3.0rc1.dist-info}/top_level.txt +0 -0
@@ -26,8 +26,6 @@ from collections.abc import Sequence
26
26
  from typing import Any
27
27
  from typing import TypeVar
28
28
 
29
- # pylint: disable=inconsistent-return-statements
30
-
31
29
  T = TypeVar("T")
32
30
  Exc = tuple[type[BaseException], ...] # exception classes
33
31
  CodePattern = int | str | range # for retry_codes argument
@@ -120,6 +118,7 @@ def _retry_decorator(
120
118
  retry_codes: Sequence[CodePattern] | None = None,
121
119
  retry_on_messages: Sequence[str] | None = None,
122
120
  deepcopy: bool = False,
121
+ instance_context_aware: bool = False,
123
122
  ) -> Callable[[Callable[..., T]], Callable[..., T]]:
124
123
  """
125
124
  Build a decorator that retries with exponential back-off *iff*:
@@ -132,69 +131,122 @@ def _retry_decorator(
132
131
  deepcopy:
133
132
  If True, each retry receives deep‑copied *args and **kwargs* to avoid
134
133
  mutating shared state between attempts.
134
+
135
+ instance_context_aware:
136
+ If True, the decorator will check for a retry context flag on the first
137
+ argument (assumed to be 'self'). If the flag is set, retries are skipped
138
+ to prevent retry storms in nested method calls.
135
139
  """
136
140
 
137
141
  def decorate(fn: Callable[..., T]) -> Callable[..., T]:
138
142
  use_deepcopy = deepcopy
143
+ use_context_aware = instance_context_aware
139
144
 
140
- async def _call_with_retry_async(*args, **kw) -> T:
141
- delay = base_delay
142
- for attempt in range(retries):
143
- call_args = copy.deepcopy(args) if use_deepcopy else args
144
- call_kwargs = copy.deepcopy(kw) if use_deepcopy else kw
145
+ class _RetryContext:
146
+ """Context manager for instance-level retry gating."""
147
+
148
+ __slots__ = ("_obj", "_enabled", "_active")
149
+
150
+ def __init__(self, args: tuple[Any, ...]):
151
+ self._obj = args[0] if (use_context_aware and args) else None
152
+ self._enabled = bool(self._obj)
153
+ self._active = False
154
+
155
+ def __enter__(self):
156
+ if not self._enabled:
157
+ return False
145
158
  try:
146
- return await fn(*call_args, **call_kwargs)
147
- except retry_on as exc:
148
- if (not _want_retry(exc, code_patterns=retry_codes, msg_substrings=retry_on_messages)
149
- or attempt == retries - 1):
150
- raise
151
- await asyncio.sleep(delay)
152
- delay *= backoff
159
+ # If already in retry context, signal caller to skip retries
160
+ if getattr(self._obj, "_in_retry_context", False):
161
+ return True
162
+ object.__setattr__(self._obj, "_in_retry_context", True)
163
+ self._active = True
164
+ return False
165
+ except Exception:
166
+ # If we cannot set the attribute, behave as if context isn't enabled
167
+ self._enabled = False
168
+ return False
169
+
170
+ def __exit__(self, _exc_type, _exc, _tb):
171
+ if self._enabled and self._active:
172
+ try:
173
+ object.__setattr__(self._obj, "_in_retry_context", False)
174
+ except Exception:
175
+ pass
176
+
177
+ async def _call_with_retry_async(*args, **kw) -> T:
178
+ with _RetryContext(args) as already_in_context:
179
+ if already_in_context:
180
+ return await fn(*args, **kw)
181
+ delay = base_delay
182
+ for attempt in range(retries):
183
+ call_args = copy.deepcopy(args) if use_deepcopy else args
184
+ call_kwargs = copy.deepcopy(kw) if use_deepcopy else kw
185
+ try:
186
+ return await fn(*call_args, **call_kwargs)
187
+ except retry_on as exc:
188
+ if (not _want_retry(exc, code_patterns=retry_codes, msg_substrings=retry_on_messages)
189
+ or attempt == retries - 1):
190
+ raise
191
+ await asyncio.sleep(delay)
192
+ delay *= backoff
153
193
 
154
194
  async def _agen_with_retry(*args, **kw):
155
- delay = base_delay
156
- for attempt in range(retries):
157
- call_args = copy.deepcopy(args) if use_deepcopy else args
158
- call_kwargs = copy.deepcopy(kw) if use_deepcopy else kw
159
- try:
160
- async for item in fn(*call_args, **call_kwargs):
195
+ with _RetryContext(args) as already_in_context:
196
+ if already_in_context:
197
+ async for item in fn(*args, **kw):
161
198
  yield item
162
199
  return
163
- except retry_on as exc:
164
- if (not _want_retry(exc, code_patterns=retry_codes, msg_substrings=retry_on_messages)
165
- or attempt == retries - 1):
166
- raise
167
- await asyncio.sleep(delay)
168
- delay *= backoff
200
+ delay = base_delay
201
+ for attempt in range(retries):
202
+ call_args = copy.deepcopy(args) if use_deepcopy else args
203
+ call_kwargs = copy.deepcopy(kw) if use_deepcopy else kw
204
+ try:
205
+ async for item in fn(*call_args, **call_kwargs):
206
+ yield item
207
+ return
208
+ except retry_on as exc:
209
+ if (not _want_retry(exc, code_patterns=retry_codes, msg_substrings=retry_on_messages)
210
+ or attempt == retries - 1):
211
+ raise
212
+ await asyncio.sleep(delay)
213
+ delay *= backoff
169
214
 
170
215
  def _gen_with_retry(*args, **kw) -> Iterable[Any]:
171
- delay = base_delay
172
- for attempt in range(retries):
173
- call_args = copy.deepcopy(args) if use_deepcopy else args
174
- call_kwargs = copy.deepcopy(kw) if use_deepcopy else kw
175
- try:
176
- yield from fn(*call_args, **call_kwargs)
216
+ with _RetryContext(args) as already_in_context:
217
+ if already_in_context:
218
+ yield from fn(*args, **kw)
177
219
  return
178
- except retry_on as exc:
179
- if (not _want_retry(exc, code_patterns=retry_codes, msg_substrings=retry_on_messages)
180
- or attempt == retries - 1):
181
- raise
182
- time.sleep(delay)
183
- delay *= backoff
220
+ delay = base_delay
221
+ for attempt in range(retries):
222
+ call_args = copy.deepcopy(args) if use_deepcopy else args
223
+ call_kwargs = copy.deepcopy(kw) if use_deepcopy else kw
224
+ try:
225
+ yield from fn(*call_args, **call_kwargs)
226
+ return
227
+ except retry_on as exc:
228
+ if (not _want_retry(exc, code_patterns=retry_codes, msg_substrings=retry_on_messages)
229
+ or attempt == retries - 1):
230
+ raise
231
+ time.sleep(delay)
232
+ delay *= backoff
184
233
 
185
234
  def _sync_with_retry(*args, **kw) -> T:
186
- delay = base_delay
187
- for attempt in range(retries):
188
- call_args = copy.deepcopy(args) if use_deepcopy else args
189
- call_kwargs = copy.deepcopy(kw) if use_deepcopy else kw
190
- try:
191
- return fn(*call_args, **call_kwargs)
192
- except retry_on as exc:
193
- if (not _want_retry(exc, code_patterns=retry_codes, msg_substrings=retry_on_messages)
194
- or attempt == retries - 1):
195
- raise
196
- time.sleep(delay)
197
- delay *= backoff
235
+ with _RetryContext(args) as already_in_context:
236
+ if already_in_context:
237
+ return fn(*args, **kw)
238
+ delay = base_delay
239
+ for attempt in range(retries):
240
+ call_args = copy.deepcopy(args) if use_deepcopy else args
241
+ call_kwargs = copy.deepcopy(kw) if use_deepcopy else kw
242
+ try:
243
+ return fn(*call_args, **call_kwargs)
244
+ except retry_on as exc:
245
+ if (not _want_retry(exc, code_patterns=retry_codes, msg_substrings=retry_on_messages)
246
+ or attempt == retries - 1):
247
+ raise
248
+ time.sleep(delay)
249
+ delay *= backoff
198
250
 
199
251
  # Decide which wrapper to return
200
252
  if inspect.iscoroutinefunction(fn):
@@ -247,6 +299,7 @@ def patch_with_retry(
247
299
  retry_codes=retry_codes,
248
300
  retry_on_messages=retry_on_messages,
249
301
  deepcopy=deepcopy,
302
+ instance_context_aware=True, # Prevent retry storms
250
303
  )
251
304
 
252
305
  # Choose attribute source: the *class* to avoid triggering __getattr__
@@ -257,7 +310,7 @@ def patch_with_retry(
257
310
  descriptor = inspect.getattr_static(cls, name)
258
311
 
259
312
  # Skip dunders, privates and all descriptors we must not wrap
260
- if (name.startswith("_") or isinstance(descriptor, (property, staticmethod, classmethod))):
313
+ if (name.startswith("_") or isinstance(descriptor, property | staticmethod | classmethod)):
261
314
  continue
262
315
 
263
316
  original = descriptor.__func__ if isinstance(descriptor, types.MethodType) else descriptor
@@ -21,7 +21,7 @@ from pydantic import ValidationError
21
21
  logger = logging.getLogger(__name__)
22
22
 
23
23
 
24
- def schema_exception_handler(func, **kwargs): # pylint: disable=unused-argument
24
+ def schema_exception_handler(func, **kwargs):
25
25
  """
26
26
  A decorator that handles `ValidationError` exceptions for schema validation functions.
27
27
 
@@ -57,7 +57,7 @@ def yaml_load(config_path: StrPath) -> dict:
57
57
  """
58
58
 
59
59
  # Read YAML file
60
- with open(config_path, "r", encoding="utf-8") as stream:
60
+ with open(config_path, encoding="utf-8") as stream:
61
61
  config_str = stream.read()
62
62
 
63
63
  return yaml_loads(config_str)
@@ -85,7 +85,7 @@ def yaml_loads(config: str) -> dict:
85
85
  try:
86
86
  config_data = yaml.safe_load(stream)
87
87
  except yaml.YAMLError as e:
88
- logger.error("Error loading YAML: %s", interpolated_config_str, exc_info=True)
88
+ logger.error("Error loading YAML: %s", interpolated_config_str)
89
89
  raise ValueError(f"Error loading YAML: {e}") from e
90
90
 
91
91
  assert isinstance(config_data, dict)
@@ -0,0 +1,25 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025, 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
+
18
+ # Define log level choices
19
+ LOG_LEVELS = {
20
+ 'DEBUG': logging.DEBUG,
21
+ 'INFO': logging.INFO,
22
+ 'WARNING': logging.WARNING,
23
+ 'ERROR': logging.ERROR,
24
+ 'CRITICAL': logging.CRITICAL
25
+ }
@@ -25,8 +25,8 @@ from nat.utils.reactive.subscription import Subscription
25
25
 
26
26
  # Covariant type param: An Observable producing type X can also produce
27
27
  # a subtype of X.
28
- _T_out_co = TypeVar("_T_out_co", covariant=True) # pylint: disable=invalid-name
29
- _T = TypeVar("_T") # pylint: disable=invalid-name
28
+ _T_out_co = TypeVar("_T_out_co", covariant=True)
29
+ _T = TypeVar("_T")
30
30
 
31
31
  OnNext = Callable[[_T], None]
32
32
  OnError = Callable[[Exception], None]
@@ -20,7 +20,7 @@ from typing import TypeVar
20
20
 
21
21
  # Contravariant type param: An Observer that can accept type X can also
22
22
  # accept any supertype of X.
23
- _T_in_contra = TypeVar("_T_in_contra", contravariant=True) # pylint: disable=invalid-name
23
+ _T_in_contra = TypeVar("_T_in_contra", contravariant=True)
24
24
 
25
25
 
26
26
  class ObserverBase(Generic[_T_in_contra], ABC):
@@ -24,8 +24,8 @@ from nat.utils.type_utils import override
24
24
 
25
25
  # Covariant type param: An Observable producing type X can also produce
26
26
  # a subtype of X.
27
- _T_out_co = TypeVar("_T_out_co", covariant=True) # pylint: disable=invalid-name
28
- _T = TypeVar("_T") # pylint: disable=invalid-name
27
+ _T_out_co = TypeVar("_T_out_co", covariant=True)
28
+ _T = TypeVar("_T")
29
29
 
30
30
  OnNext = Callable[[_T], None]
31
31
  OnError = Callable[[Exception], None]
@@ -23,8 +23,8 @@ logger = logging.getLogger(__name__)
23
23
 
24
24
  # Contravariant type param: An Observer that can accept type X can also
25
25
  # accept any supertype of X.
26
- _T_in_contra = TypeVar("_T_in_contra", contravariant=True) # pylint: disable=invalid-name
27
- _T = TypeVar("_T") # pylint: disable=invalid-name
26
+ _T_in_contra = TypeVar("_T_in_contra", contravariant=True)
27
+ _T = TypeVar("_T")
28
28
 
29
29
  OnNext = Callable[[_T], None]
30
30
  OnError = Callable[[Exception], None]
@@ -64,7 +64,7 @@ class Observer(ObserverBase[_T_in_contra]):
64
64
  try:
65
65
  self._on_error(exc)
66
66
  except Exception as e:
67
- logger.exception("Error in on_error callback: %s", e, exc_info=True)
67
+ logger.exception("Error in on_error callback: %s", e)
68
68
 
69
69
  def on_complete(self) -> None:
70
70
  if not self._stopped:
@@ -73,4 +73,4 @@ class Observer(ObserverBase[_T_in_contra]):
73
73
  try:
74
74
  self._on_complete()
75
75
  except Exception as e:
76
- logger.exception("Error in on_complete callback: %s", e, exc_info=True)
76
+ logger.exception("Error in on_complete callback: %s", e)
@@ -21,7 +21,7 @@ from typing import TypeVar
21
21
  if typing.TYPE_CHECKING:
22
22
  from nat.utils.reactive.base.subject_base import SubjectBase
23
23
 
24
- _T = TypeVar("_T") # pylint: disable=invalid-name
24
+ _T = TypeVar("_T")
25
25
 
26
26
  OnNext = Callable[[_T], None]
27
27
  OnError = Callable[[Exception], None]
@@ -47,7 +47,7 @@ def configure_registry_channel(config_type: RegistryHandlerBaseConfig, channel_n
47
47
  user_input = input(f"{human_prompt}: ")
48
48
  model_fields = {}
49
49
  model_fields[field] = (info.annotation, ...)
50
- DynamicFieldModel = create_model("DynamicFieldModel", **model_fields) # pylint: disable=C0103
50
+ DynamicFieldModel = create_model("DynamicFieldModel", **model_fields)
51
51
  dynamic_inputs = {field: user_input}
52
52
 
53
53
  try:
@@ -55,7 +55,7 @@ def configure_registry_channel(config_type: RegistryHandlerBaseConfig, channel_n
55
55
  channel_registry_pre[field] = getattr(validated_field_model, field)
56
56
  break
57
57
  except Exception as e:
58
- logger.exception(e, exc_info=True)
58
+ logger.exception(e)
59
59
  logger.warning("Invalid '%s' input, input must be of type %s.", field, info.annotation)
60
60
 
61
61
  validated_model = config_type(**channel_registry_pre)
@@ -76,10 +76,9 @@ def add_channel_interative(channel_type: str) -> None:
76
76
  registry = GlobalTypeRegistry.get()
77
77
 
78
78
  try:
79
- ChannelConfigType = registry.get_registered_channel_info_by_channel_type( # pylint: disable=C0103
80
- channel_type=channel_type).config_type
79
+ ChannelConfigType = registry.get_registered_channel_info_by_channel_type(channel_type=channel_type).config_type
81
80
  except Exception as e:
82
- logger.exception("Invalid channel type: %s", e, exc_info=True)
81
+ logger.exception("Invalid channel type: %s", e)
83
82
  return
84
83
 
85
84
  while (True):
@@ -92,8 +91,7 @@ def add_channel_interative(channel_type: str) -> None:
92
91
  settings.channels[channel_name] = {}
93
92
  break
94
93
 
95
- ChannelConfigType = registry.get_registered_channel_info_by_channel_type( # pylint: disable=C0103
96
- channel_type=channel_type).config_type
94
+ ChannelConfigType = registry.get_registered_channel_info_by_channel_type(channel_type=channel_type).config_type
97
95
 
98
96
  configure_registry_channel(config_type=ChannelConfigType, channel_name=channel_name)
99
97
 
@@ -181,7 +179,7 @@ def match_valid_channel(channel_name: str) -> None:
181
179
 
182
180
  channals_settings = settings.channels
183
181
  channel_settings = channals_settings.get(channel_name)
184
- ChannelConfigType = registry.get_registered_channel_info_by_channel_type( # pylint: disable=C0103
182
+ ChannelConfigType = registry.get_registered_channel_info_by_channel_type(
185
183
  channel_type=channel_settings.static_type()).config_type
186
184
 
187
185
  configure_registry_channel(config_type=ChannelConfigType, channel_name=channel_name)
@@ -90,7 +90,7 @@ class TypeConverter:
90
90
  decomposed = DecomposedType(to_type)
91
91
 
92
92
  # 1) If data is already correct type, return it
93
- if to_type is None or decomposed.is_instance((data, to_type)):
93
+ if to_type is None or decomposed.is_instance(data):
94
94
  return data
95
95
 
96
96
  root = decomposed.root
@@ -198,16 +198,17 @@ class TypeConverter:
198
198
  """
199
199
  visited = set()
200
200
  final = self._try_indirect_conversion(data, to_type, visited)
201
+ src_type = type(data)
201
202
  if final is not None:
202
203
  # Warn once if found a chain
203
- self._maybe_warn_indirect(type(data), to_type)
204
+ self._maybe_warn_indirect(src_type, to_type)
204
205
  return final
205
206
 
206
207
  # If no success, try parent's indirect
207
208
  if self._parent is not None:
208
209
  parent_final = self._parent._try_indirect_convert(data, to_type)
209
210
  if parent_final is not None:
210
- self._maybe_warn_indirect(type(data), to_type)
211
+ self._maybe_warn_indirect(src_type, to_type)
211
212
  return parent_final
212
213
 
213
214
  return None
nat/utils/type_utils.py CHANGED
@@ -50,7 +50,7 @@ def is_valid_json(string):
50
50
  # In Python >= 3.12, it uses the built-in typing.override decorator
51
51
  # In Python < 3.12, it acts as a no-op decorator
52
52
  if sys.version_info >= (3, 12):
53
- from typing import override # pylint: disable=unused-import
53
+ from typing import override
54
54
  else:
55
55
 
56
56
  def override(func):
@@ -181,7 +181,7 @@ class DecomposedType:
181
181
  True if the current type is a union type, False otherwise.
182
182
  """
183
183
 
184
- return self.origin in (typing.Union, types.UnionType) # pylint: disable=consider-alternative-union-syntax
184
+ return self.origin in (typing.Union, types.UnionType)
185
185
 
186
186
  @property
187
187
  @lru_cache
@@ -197,7 +197,7 @@ class DecomposedType:
197
197
  """
198
198
 
199
199
  return self.origin in (
200
- typing.AsyncGenerator, # pylint: disable=consider-alternative-union-syntax,deprecated-typing-alias
200
+ typing.AsyncGenerator,
201
201
  collections.abc.AsyncGenerator,
202
202
  types.AsyncGeneratorType,
203
203
  )
@@ -250,7 +250,7 @@ class DecomposedType:
250
250
  remaining_args = tuple(arg for arg in self.args if arg is not types.NoneType)
251
251
 
252
252
  if (len(remaining_args) > 1):
253
- return DecomposedType(typing.Union[remaining_args]) # pylint: disable=consider-alternative-union-syntax
253
+ return DecomposedType(typing.Union[*remaining_args])
254
254
  if (len(remaining_args) == 1):
255
255
  return DecomposedType(remaining_args[0])
256
256
 
@@ -353,7 +353,7 @@ class DecomposedType:
353
353
  True if the current type is an instance of the specified instance, False otherwise
354
354
  """
355
355
 
356
- return isinstance(instance, self.root)
356
+ return isinstance(instance, self.get_base_type().root)
357
357
 
358
358
  def get_pydantic_schema(self,
359
359
  converters: list[collections.abc.Callable] | None = None) -> type[BaseModel] | type[None]:
@@ -469,6 +469,10 @@ class DecomposedType:
469
469
  # Handle generic types that can't use issubclass
470
470
  pass
471
471
 
472
+ # Check direct equality (works for both regular and generic types)
473
+ if source_type == target_type:
474
+ return True
475
+
472
476
  # Check if source outputs list[T] and target expects T
473
477
  source_decomposed = DecomposedType(source_type)
474
478
  if source_decomposed.origin is list and source_decomposed.args:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nvidia-nat
3
- Version: 1.3.0.dev2
3
+ Version: 1.3.0rc1
4
4
  Summary: NVIDIA NeMo Agent toolkit
5
5
  Author: NVIDIA Corporation
6
6
  Maintainer: NVIDIA Corporation
@@ -207,12 +207,15 @@ License: Apache License
207
207
  limitations under the License.
208
208
  Keywords: ai,rag,agents
209
209
  Classifier: Programming Language :: Python
210
- Requires-Python: <3.13,>=3.11
210
+ Classifier: Programming Language :: Python :: 3.11
211
+ Classifier: Programming Language :: Python :: 3.12
212
+ Classifier: Programming Language :: Python :: 3.13
213
+ Requires-Python: <3.14,>=3.11
211
214
  Description-Content-Type: text/markdown
212
215
  License-File: LICENSE-3rd-party.txt
213
216
  License-File: LICENSE.md
214
217
  Requires-Dist: aioboto3>=11.0.0
215
- Requires-Dist: authlib~=1.3.1
218
+ Requires-Dist: authlib~=1.5
216
219
  Requires-Dist: click~=8.1
217
220
  Requires-Dist: colorama~=0.4.6
218
221
  Requires-Dist: datasets~=4.0
@@ -221,34 +224,44 @@ Requires-Dist: fastapi~=0.115.5
221
224
  Requires-Dist: httpx~=0.27
222
225
  Requires-Dist: jinja2~=3.1
223
226
  Requires-Dist: jsonpath-ng~=1.7
224
- Requires-Dist: mcp~=1.10
227
+ Requires-Dist: mcp~=1.13
228
+ Requires-Dist: nest-asyncio~=1.6
225
229
  Requires-Dist: networkx~=3.4
226
- Requires-Dist: numpy~=1.26
230
+ Requires-Dist: numpy~=1.26; python_version < "3.12"
231
+ Requires-Dist: numpy~=2.3; python_version >= "3.12"
227
232
  Requires-Dist: openinference-semantic-conventions~=0.1.14
228
233
  Requires-Dist: openpyxl~=3.1
234
+ Requires-Dist: optuna~=4.4.0
235
+ Requires-Dist: pip>=24.3.1
229
236
  Requires-Dist: pkce==1.0.3
230
237
  Requires-Dist: pkginfo~=1.12
231
238
  Requires-Dist: platformdirs~=4.3
232
- Requires-Dist: pydantic==2.10.*
239
+ Requires-Dist: pydantic~=2.11
233
240
  Requires-Dist: pymilvus~=2.4
234
241
  Requires-Dist: PyYAML~=6.0
235
242
  Requires-Dist: ragas~=0.2.14
236
243
  Requires-Dist: rich~=13.9
237
244
  Requires-Dist: tabulate~=0.9
238
- Requires-Dist: uvicorn[standard]~=0.32.0
245
+ Requires-Dist: uvicorn[standard]~=0.34
239
246
  Requires-Dist: wikipedia~=1.4
240
247
  Provides-Extra: all
241
248
  Requires-Dist: nvidia-nat-all; extra == "all"
249
+ Provides-Extra: adk
250
+ Requires-Dist: nvidia-nat-adk; extra == "adk"
242
251
  Provides-Extra: agno
243
252
  Requires-Dist: nvidia-nat-agno; extra == "agno"
244
253
  Provides-Extra: crewai
245
254
  Requires-Dist: nvidia-nat-crewai; extra == "crewai"
255
+ Provides-Extra: data-flywheel
256
+ Requires-Dist: nvidia-nat-data-flywheel; extra == "data-flywheel"
246
257
  Provides-Extra: ingestion
247
258
  Requires-Dist: nvidia-nat-ingestion; extra == "ingestion"
248
259
  Provides-Extra: langchain
249
260
  Requires-Dist: nvidia-nat-langchain; extra == "langchain"
250
261
  Provides-Extra: llama-index
251
262
  Requires-Dist: nvidia-nat-llama-index; extra == "llama-index"
263
+ Provides-Extra: mcp
264
+ Requires-Dist: nvidia-nat-mcp; extra == "mcp"
252
265
  Provides-Extra: mem0ai
253
266
  Requires-Dist: nvidia-nat-mem0ai; extra == "mem0ai"
254
267
  Provides-Extra: opentelemetry
@@ -277,6 +290,7 @@ Requires-Dist: nvidia-nat-weave; extra == "weave"
277
290
  Provides-Extra: zep-cloud
278
291
  Requires-Dist: nvidia-nat-zep-cloud; extra == "zep-cloud"
279
292
  Provides-Extra: examples
293
+ Requires-Dist: nat_adk_demo; extra == "examples"
280
294
  Requires-Dist: nat_agno_personal_finance; extra == "examples"
281
295
  Requires-Dist: nat_alert_triage_agent; extra == "examples"
282
296
  Requires-Dist: nat_automated_description_generation; extra == "examples"
@@ -288,8 +302,11 @@ Requires-Dist: nat_por_to_jiratickets; extra == "examples"
288
302
  Requires-Dist: nat_profiler_agent; extra == "examples"
289
303
  Requires-Dist: nat_redact_pii; extra == "examples"
290
304
  Requires-Dist: nat_retail_sales_agent; extra == "examples"
305
+ Requires-Dist: nat_router_agent; extra == "examples"
291
306
  Requires-Dist: nat_semantic_kernel_demo; extra == "examples"
307
+ Requires-Dist: nat_sequential_executor; extra == "examples"
292
308
  Requires-Dist: nat_simple_auth; extra == "examples"
309
+ Requires-Dist: nat_simple_auth_mcp; extra == "examples"
293
310
  Requires-Dist: nat_simple_web_query; extra == "examples"
294
311
  Requires-Dist: nat_simple_web_query_eval; extra == "examples"
295
312
  Requires-Dist: nat_simple_calculator; extra == "examples"
@@ -303,6 +320,15 @@ Requires-Dist: nat_swe_bench; extra == "examples"
303
320
  Requires-Dist: nat_user_report; extra == "examples"
304
321
  Provides-Extra: gunicorn
305
322
  Requires-Dist: gunicorn~=23.0; extra == "gunicorn"
323
+ Provides-Extra: async-endpoints
324
+ Requires-Dist: aiosqlite~=0.21; extra == "async-endpoints"
325
+ Requires-Dist: dask==2023.6; extra == "async-endpoints"
326
+ Requires-Dist: distributed==2023.6; extra == "async-endpoints"
327
+ Requires-Dist: sqlalchemy[asyncio]~=2.0; extra == "async-endpoints"
328
+ Provides-Extra: litellm
329
+ Requires-Dist: litellm==1.74.9; extra == "litellm"
330
+ Provides-Extra: openai
331
+ Requires-Dist: openai~=1.106; extra == "openai"
306
332
  Dynamic: license-file
307
333
 
308
334
  <!--
@@ -330,19 +356,19 @@ NeMo Agent toolkit is a flexible library designed to seamlessly integrate your e
330
356
 
331
357
  ## Key Features
332
358
 
333
- - [**Framework Agnostic:**](https://docs.nvidia.com/nemo/agent-toolkit/1.2/extend/plugins.html) Works with any agentic framework, so you can use your current technology stack without replatforming.
334
- - [**Reusability:**](https://docs.nvidia.com/nemo/agent-toolkit/1.2/extend/sharing-components.html) Every agent, tool, or workflow can be combined and repurposed, allowing developers to leverage existing work in new scenarios.
335
- - [**Rapid Development:**](https://docs.nvidia.com/nemo/agent-toolkit/1.2/tutorials/index.html) Start with a pre-built agent, tool, or workflow, and customize it to your needs.
336
- - [**Profiling:**](https://docs.nvidia.com/nemo/agent-toolkit/1.2/workflows/profiler.html) Profile entire workflows down to the tool and agent level, track input/output tokens and timings, and identify bottlenecks.
337
- - [**Observability:**](https://docs.nvidia.com/nemo/agent-toolkit/1.2/workflows/observe/observe-workflow-with-phoenix.html) Monitor and debug your workflows with any OpenTelemetry-compatible observability tool, with examples using [Phoenix](https://docs.nvidia.com/nemo/agent-toolkit/1.2/workflows/observe/observe-workflow-with-phoenix.html) and [W&B Weave](https://docs.nvidia.com/nemo/agent-toolkit/1.2/workflows/observe/observe-workflow-with-weave.html).
338
- - [**Evaluation System:**](https://docs.nvidia.com/nemo/agent-toolkit/1.2/workflows/evaluate.html) Validate and maintain accuracy of agentic workflows with built-in evaluation tools.
339
- - [**User Interface:**](https://docs.nvidia.com/nemo/agent-toolkit/1.2/quick-start/launching-ui.html) Use the NeMo Agent toolkit UI chat interface to interact with your agents, visualize output, and debug workflows.
340
- - [**MCP Compatibility**](https://docs.nvidia.com/nemo/agent-toolkit/1.2/workflows/mcp/mcp-client.html) Compatible with Model Context Protocol (MCP), allowing tools served by MCP Servers to be used as NeMo Agent toolkit functions.
359
+ - [**Framework Agnostic:**](https://docs.nvidia.com/nemo/agent-toolkit/1.3/extend/plugins.html) Works with any agentic framework, so you can use your current technology stack without replatforming.
360
+ - [**Reusability:**](https://docs.nvidia.com/nemo/agent-toolkit/1.3/extend/sharing-components.html) Every agent, tool, or workflow can be combined and repurposed, allowing developers to leverage existing work in new scenarios.
361
+ - [**Rapid Development:**](https://docs.nvidia.com/nemo/agent-toolkit/1.3/tutorials/index.html) Start with a pre-built agent, tool, or workflow, and customize it to your needs.
362
+ - [**Profiling:**](https://docs.nvidia.com/nemo/agent-toolkit/1.3/workflows/profiler.html) Profile entire workflows down to the tool and agent level, track input/output tokens and timings, and identify bottlenecks.
363
+ - [**Observability:**](https://docs.nvidia.com/nemo/agent-toolkit/1.3/workflows/observe/observe-workflow-with-phoenix.html) Monitor and debug your workflows with any OpenTelemetry-compatible observability tool, with examples using [Phoenix](https://docs.nvidia.com/nemo/agent-toolkit/1.3/workflows/observe/observe-workflow-with-phoenix.html) and [W&B Weave](https://docs.nvidia.com/nemo/agent-toolkit/1.3/workflows/observe/observe-workflow-with-weave.html).
364
+ - [**Evaluation System:**](https://docs.nvidia.com/nemo/agent-toolkit/1.3/workflows/evaluate.html) Validate and maintain accuracy of agentic workflows with built-in evaluation tools.
365
+ - [**User Interface:**](https://docs.nvidia.com/nemo/agent-toolkit/1.3/quick-start/launching-ui.html) Use the NeMo Agent toolkit UI chat interface to interact with your agents, visualize output, and debug workflows.
366
+ - [**MCP Compatibility**](https://docs.nvidia.com/nemo/agent-toolkit/1.3/workflows/mcp/mcp-client.html) Compatible with Model Context Protocol (MCP), allowing tools served by MCP Servers to be used as NeMo Agent toolkit functions.
341
367
 
342
368
  With NeMo Agent toolkit, you can move quickly, experiment freely, and ensure reliability across all your agent-driven projects.
343
369
 
344
370
  ## Links
345
- * [Documentation](https://docs.nvidia.com/nemo/agent-toolkit/1.2/index.html): Explore the full documentation for NeMo Agent toolkit.
371
+ * [Documentation](https://docs.nvidia.com/nemo/agent-toolkit/1.3/index.html): Explore the full documentation for NeMo Agent toolkit.
346
372
 
347
373
  ## First time user?
348
374
  If this is your first time using NeMo Agent toolkit, it is recommended to install the latest version from the [source repository](https://github.com/NVIDIA/NeMo-Agent-Toolkit?tab=readme-ov-file#quick-start) on GitHub. This package is intended for users who are familiar with NeMo Agent toolkit applications and need to add NeMo Agent toolkit as a dependency to their project.