@@ -283,13 +283,55 @@ async def retrieve_async(
283283 else :
284284 return Asset .model_validate (response .json ()["value" ][0 ])
285285
286- def _ensure_robot_context (self ) -> None :
286+ def _resolve_robot_key (
287+ self ,
288+ name : str ,
289+ * ,
290+ folder_key : Optional [str ] = None ,
291+ folder_path : Optional [str ] = None ,
292+ ) -> Optional [str ]:
293+ """Return the robot key, or ``None`` if the asset opts into direct API access.
294+
295+ Raises ``ValueError`` when no robot key is available and ``AllowDirectApiAccess``
296+ is not enabled on the asset.
297+ """
287298 try :
288- is_user = self ._execution_context .robot_key is not None
299+ robot_key = self ._execution_context .robot_key
289300 except ValueError :
290- is_user = False
291- if not is_user :
292- raise ValueError ("This method can only be used for robot assets." )
301+ robot_key = None
302+
303+ if robot_key is None :
304+ asset = self .retrieve (
305+ name = name , folder_key = folder_key , folder_path = folder_path
306+ )
307+ if not asset .allow_direct_api_access :
308+ raise ValueError (
309+ f"No robot key available and 'AllowDirectApiAccess' is disabled for asset '{ name } '."
310+ )
311+ return robot_key
312+
313+ async def _resolve_robot_key_async (
314+ self ,
315+ name : str ,
316+ * ,
317+ folder_key : Optional [str ] = None ,
318+ folder_path : Optional [str ] = None ,
319+ ) -> Optional [str ]:
320+ """Async variant of :meth:`_resolve_robot_key`."""
321+ try :
322+ robot_key = self ._execution_context .robot_key
323+ except ValueError :
324+ robot_key = None
325+
326+ if robot_key is None :
327+ asset = await self .retrieve_async (
328+ name = name , folder_key = folder_key , folder_path = folder_path
329+ )
330+ if not asset .allow_direct_api_access :
331+ raise ValueError (
332+ f"No robot key available and 'AllowDirectApiAccess' is disabled for asset '{ name } '."
333+ )
334+ return robot_key
293335
294336 @resource_override (resource_type = "asset" )
295337 @traced (
@@ -305,6 +347,10 @@ def retrieve_credential(
305347 """Get the decrypted password of a Credential asset.
306348
307349 The robot id is retrieved from the execution context (`UIPATH_ROBOT_KEY` environment variable).
350+ If no robot key is available, the asset's `AllowDirectApiAccess` flag is checked: when
351+ enabled, the credential is fetched without a robot key; otherwise a `ValueError` is raised.
352+
353+ Related Activity: [Get Credential](https://docs.uipath.com/activities/other/latest/workflow/get-robot-credential)
308354
309355 Args:
310356 name (str): The name of the credential asset.
@@ -315,10 +361,18 @@ def retrieve_credential(
315361 Optional[str]: The decrypted credential password.
316362
317363 Raises:
318- ValueError: If called outside a robot context (no `UIPATH_ROBOT_KEY`) .
364+ ValueError: If no robot key is available and the asset does not have `AllowDirectApiAccess` enabled .
319365 """
320- self ._ensure_robot_context ()
321- spec = self ._retrieve_spec (name , folder_key = folder_key , folder_path = folder_path )
366+ robot_key = self ._resolve_robot_key (
367+ name , folder_key = folder_key , folder_path = folder_path
368+ )
369+
370+ spec = self ._retrieve_credential_spec (
371+ name ,
372+ robot_key = robot_key ,
373+ folder_key = folder_key ,
374+ folder_path = folder_path ,
375+ )
322376 response = self .request (
323377 spec .method ,
324378 url = spec .endpoint ,
@@ -343,6 +397,10 @@ async def retrieve_credential_async(
343397 """Asynchronously get the decrypted password of a Credential asset.
344398
345399 The robot id is retrieved from the execution context (`UIPATH_ROBOT_KEY` environment variable).
400+ If no robot key is available, the asset's `AllowDirectApiAccess` flag is checked: when
401+ enabled, the credential is fetched without a robot key; otherwise a `ValueError` is raised.
402+
403+ Related Activity: [Get Credential](https://docs.uipath.com/activities/other/latest/workflow/get-robot-credential)
346404
347405 Args:
348406 name (str): The name of the credential asset.
@@ -353,10 +411,18 @@ async def retrieve_credential_async(
353411 Optional[str]: The decrypted credential password.
354412
355413 Raises:
356- ValueError: If called outside a robot context (no `UIPATH_ROBOT_KEY`) .
414+ ValueError: If no robot key is available and the asset does not have `AllowDirectApiAccess` enabled .
357415 """
358- self ._ensure_robot_context ()
359- spec = self ._retrieve_spec (name , folder_key = folder_key , folder_path = folder_path )
416+ robot_key = await self ._resolve_robot_key_async (
417+ name , folder_key = folder_key , folder_path = folder_path
418+ )
419+
420+ spec = self ._retrieve_credential_spec (
421+ name ,
422+ robot_key = robot_key ,
423+ folder_key = folder_key ,
424+ folder_path = folder_path ,
425+ )
360426 response = await self .request_async (
361427 spec .method ,
362428 url = spec .endpoint ,
@@ -379,6 +445,8 @@ def retrieve_secret(
379445 """Get the decrypted value of a Secret asset.
380446
381447 The robot id is retrieved from the execution context (`UIPATH_ROBOT_KEY` environment variable).
448+ If no robot key is available, the asset's `AllowDirectApiAccess` flag is checked: when
449+ enabled, the secret is fetched without a robot key; otherwise a `ValueError` is raised.
382450
383451 Args:
384452 name (str): The name of the secret asset.
@@ -389,10 +457,18 @@ def retrieve_secret(
389457 Optional[str]: The decrypted secret value.
390458
391459 Raises:
392- ValueError: If called outside a robot context (no `UIPATH_ROBOT_KEY`) .
460+ ValueError: If no robot key is available and the asset does not have `AllowDirectApiAccess` enabled .
393461 """
394- self ._ensure_robot_context ()
395- spec = self ._retrieve_spec (name , folder_key = folder_key , folder_path = folder_path )
462+ robot_key = self ._resolve_robot_key (
463+ name , folder_key = folder_key , folder_path = folder_path
464+ )
465+
466+ spec = self ._retrieve_credential_spec (
467+ name ,
468+ robot_key = robot_key ,
469+ folder_key = folder_key ,
470+ folder_path = folder_path ,
471+ )
396472 response = self .request (
397473 spec .method ,
398474 url = spec .endpoint ,
@@ -415,6 +491,8 @@ async def retrieve_secret_async(
415491 """Asynchronously get the decrypted value of a Secret asset.
416492
417493 The robot id is retrieved from the execution context (`UIPATH_ROBOT_KEY` environment variable).
494+ If no robot key is available, the asset's `AllowDirectApiAccess` flag is checked: when
495+ enabled, the secret is fetched without a robot key; otherwise a `ValueError` is raised.
418496
419497 Args:
420498 name (str): The name of the secret asset.
@@ -425,10 +503,18 @@ async def retrieve_secret_async(
425503 Optional[str]: The decrypted secret value.
426504
427505 Raises:
428- ValueError: If called outside a robot context (no `UIPATH_ROBOT_KEY`) .
506+ ValueError: If no robot key is available and the asset does not have `AllowDirectApiAccess` enabled .
429507 """
430- self ._ensure_robot_context ()
431- spec = self ._retrieve_spec (name , folder_key = folder_key , folder_path = folder_path )
508+ robot_key = await self ._resolve_robot_key_async (
509+ name , folder_key = folder_key , folder_path = folder_path
510+ )
511+
512+ spec = self ._retrieve_credential_spec (
513+ name ,
514+ robot_key = robot_key ,
515+ folder_key = folder_key ,
516+ folder_path = folder_path ,
517+ )
432518 response = await self .request_async (
433519 spec .method ,
434520 url = spec .endpoint ,
@@ -559,6 +645,32 @@ def _retrieve_spec(
559645 },
560646 )
561647
648+ def _retrieve_credential_spec (
649+ self ,
650+ name : str ,
651+ * ,
652+ robot_key : Optional [str ],
653+ folder_key : Optional [str ] = None ,
654+ folder_path : Optional [str ] = None ,
655+ ) -> RequestSpec :
656+ body : Dict [str , Any ] = {
657+ "assetName" : name ,
658+ "supportsCredentialsProxyDisconnected" : True ,
659+ }
660+ if robot_key is not None :
661+ body ["robotKey" ] = robot_key
662+
663+ return RequestSpec (
664+ method = "POST" ,
665+ endpoint = Endpoint (
666+ "/orchestrator_/odata/Assets/UiPath.Server.Configuration.OData.GetRobotAssetByNameForRobotKey"
667+ ),
668+ json = body ,
669+ headers = {
670+ ** header_folder (folder_key , folder_path ),
671+ },
672+ )
673+
562674 def _update_spec (
563675 self ,
564676 robot_asset : UserAsset ,
0 commit comments