diff --git a/DO_OPENAPI_COMMIT_SHA.txt b/DO_OPENAPI_COMMIT_SHA.txt
index 67d44682..5c897da7 100644
--- a/DO_OPENAPI_COMMIT_SHA.txt
+++ b/DO_OPENAPI_COMMIT_SHA.txt
@@ -1 +1 @@
-97dca99
+380d7ee
diff --git a/src/pydo/_client.py b/src/pydo/_client.py
index c59a0d6d..8962bc5e 100644
--- a/src/pydo/_client.py
+++ b/src/pydo/_client.py
@@ -36,7 +36,12 @@
FirewallsOperations,
FunctionsAccessKeyOperations,
FunctionsOperations,
+ GatewayApprovalsOperations,
+ GatewayCodeOperations,
+ GatewaySessionApprovalsOperations,
+ GatewayToolsOperations,
GenaiOperations,
+ HarnessOperations,
ImageActionsOperations,
ImagesOperations,
InferenceOperations,
@@ -45,6 +50,8 @@
KubernetesOperations,
LoadBalancersOperations,
McpServersOperations,
+ MicrovmCheckpointsOperations,
+ MicrovmsOperations,
MonitoringOperations,
NfsOperations,
OneClicksOperations,
@@ -63,6 +70,7 @@
ReservedIPv6Operations,
SecurityOperations,
SessionsOperations,
+ SignalsOperations,
SizesOperations,
SnapshotsOperations,
SpacesKeyOperations,
@@ -108,6 +116,14 @@ class GeneratedClient: # pylint: disable=client-accepts-api-version-keyword,too
:vartype tools: pydo.operations.ToolsOperations
:ivar users: UsersOperations operations
:vartype users: pydo.operations.UsersOperations
+ :ivar gateway_tools: GatewayToolsOperations operations
+ :vartype gateway_tools: pydo.operations.GatewayToolsOperations
+ :ivar gateway_code: GatewayCodeOperations operations
+ :vartype gateway_code: pydo.operations.GatewayCodeOperations
+ :ivar gateway_session_approvals: GatewaySessionApprovalsOperations operations
+ :vartype gateway_session_approvals: pydo.operations.GatewaySessionApprovalsOperations
+ :ivar gateway_approvals: GatewayApprovalsOperations operations
+ :vartype gateway_approvals: pydo.operations.GatewayApprovalsOperations
:ivar one_clicks: OneClicksOperations operations
:vartype one_clicks: pydo.operations.OneClicksOperations
:ivar account: AccountOperations operations
@@ -118,6 +134,8 @@ class GeneratedClient: # pylint: disable=client-accepts-api-version-keyword,too
:vartype actions: pydo.operations.ActionsOperations
:ivar addons: AddonsOperations operations
:vartype addons: pydo.operations.AddonsOperations
+ :ivar harness: HarnessOperations operations
+ :vartype harness: pydo.operations.HarnessOperations
:ivar apps: AppsOperations operations
:vartype apps: pydo.operations.AppsOperations
:ivar cdn: CdnOperations operations
@@ -160,10 +178,16 @@ class GeneratedClient: # pylint: disable=client-accepts-api-version-keyword,too
:vartype image_actions: pydo.operations.ImageActionsOperations
:ivar insights: InsightsOperations operations
:vartype insights: pydo.operations.InsightsOperations
+ :ivar signals: SignalsOperations operations
+ :vartype signals: pydo.operations.SignalsOperations
:ivar kubernetes: KubernetesOperations operations
:vartype kubernetes: pydo.operations.KubernetesOperations
:ivar load_balancers: LoadBalancersOperations operations
:vartype load_balancers: pydo.operations.LoadBalancersOperations
+ :ivar microvms: MicrovmsOperations operations
+ :vartype microvms: pydo.operations.MicrovmsOperations
+ :ivar microvm_checkpoints: MicrovmCheckpointsOperations operations
+ :vartype microvm_checkpoints: pydo.operations.MicrovmCheckpointsOperations
:ivar monitoring: MonitoringOperations operations
:vartype monitoring: pydo.operations.MonitoringOperations
:ivar nfs: NfsOperations operations
@@ -294,6 +318,18 @@ def __init__(
self.users = UsersOperations(
self._client, self._config, self._serialize, self._deserialize
)
+ self.gateway_tools = GatewayToolsOperations(
+ self._client, self._config, self._serialize, self._deserialize
+ )
+ self.gateway_code = GatewayCodeOperations(
+ self._client, self._config, self._serialize, self._deserialize
+ )
+ self.gateway_session_approvals = GatewaySessionApprovalsOperations(
+ self._client, self._config, self._serialize, self._deserialize
+ )
+ self.gateway_approvals = GatewayApprovalsOperations(
+ self._client, self._config, self._serialize, self._deserialize
+ )
self.one_clicks = OneClicksOperations(
self._client, self._config, self._serialize, self._deserialize
)
@@ -309,6 +345,9 @@ def __init__(
self.addons = AddonsOperations(
self._client, self._config, self._serialize, self._deserialize
)
+ self.harness = HarnessOperations(
+ self._client, self._config, self._serialize, self._deserialize
+ )
self.apps = AppsOperations(
self._client, self._config, self._serialize, self._deserialize
)
@@ -372,12 +411,21 @@ def __init__(
self.insights = InsightsOperations(
self._client, self._config, self._serialize, self._deserialize
)
+ self.signals = SignalsOperations(
+ self._client, self._config, self._serialize, self._deserialize
+ )
self.kubernetes = KubernetesOperations(
self._client, self._config, self._serialize, self._deserialize
)
self.load_balancers = LoadBalancersOperations(
self._client, self._config, self._serialize, self._deserialize
)
+ self.microvms = MicrovmsOperations(
+ self._client, self._config, self._serialize, self._deserialize
+ )
+ self.microvm_checkpoints = MicrovmCheckpointsOperations(
+ self._client, self._config, self._serialize, self._deserialize
+ )
self.monitoring = MonitoringOperations(
self._client, self._config, self._serialize, self._deserialize
)
diff --git a/src/pydo/_vendor.py b/src/pydo/_vendor.py
index 422d511d..94e5f091 100644
--- a/src/pydo/_vendor.py
+++ b/src/pydo/_vendor.py
@@ -3,6 +3,10 @@
# Changes may cause incorrect behavior and will be lost if the code is regenerated.
# --------------------------------------------------------------------------
+from typing import Optional
+
+from azure.core import MatchConditions
+
def raise_if_not_implemented(cls, abstract_methods):
not_implemented = [
@@ -15,3 +19,37 @@ def raise_if_not_implemented(cls, abstract_methods):
cls.__name__, "', '".join(not_implemented)
)
)
+
+
+def quote_etag(etag: Optional[str]) -> Optional[str]:
+ if not etag or etag == "*":
+ return etag
+ if etag.startswith("W/"):
+ return etag
+ if etag.startswith('"') and etag.endswith('"'):
+ return etag
+ if etag.startswith("'") and etag.endswith("'"):
+ return etag
+ return '"' + etag + '"'
+
+
+def prep_if_match(
+ etag: Optional[str], match_condition: Optional[MatchConditions]
+) -> Optional[str]:
+ if match_condition == MatchConditions.IfNotModified:
+ if_match = quote_etag(etag) if etag else None
+ return if_match
+ if match_condition == MatchConditions.IfPresent:
+ return "*"
+ return None
+
+
+def prep_if_none_match(
+ etag: Optional[str], match_condition: Optional[MatchConditions]
+) -> Optional[str]:
+ if match_condition == MatchConditions.IfModified:
+ if_none_match = quote_etag(etag) if etag else None
+ return if_none_match
+ if match_condition == MatchConditions.IfMissing:
+ return "*"
+ return None
diff --git a/src/pydo/aio/_client.py b/src/pydo/aio/_client.py
index cb653108..5bceb6d5 100644
--- a/src/pydo/aio/_client.py
+++ b/src/pydo/aio/_client.py
@@ -36,7 +36,12 @@
FirewallsOperations,
FunctionsAccessKeyOperations,
FunctionsOperations,
+ GatewayApprovalsOperations,
+ GatewayCodeOperations,
+ GatewaySessionApprovalsOperations,
+ GatewayToolsOperations,
GenaiOperations,
+ HarnessOperations,
ImageActionsOperations,
ImagesOperations,
InferenceOperations,
@@ -45,6 +50,8 @@
KubernetesOperations,
LoadBalancersOperations,
McpServersOperations,
+ MicrovmCheckpointsOperations,
+ MicrovmsOperations,
MonitoringOperations,
NfsOperations,
OneClicksOperations,
@@ -63,6 +70,7 @@
ReservedIPv6Operations,
SecurityOperations,
SessionsOperations,
+ SignalsOperations,
SizesOperations,
SnapshotsOperations,
SpacesKeyOperations,
@@ -108,6 +116,14 @@ class GeneratedClient: # pylint: disable=client-accepts-api-version-keyword,too
:vartype tools: pydo.aio.operations.ToolsOperations
:ivar users: UsersOperations operations
:vartype users: pydo.aio.operations.UsersOperations
+ :ivar gateway_tools: GatewayToolsOperations operations
+ :vartype gateway_tools: pydo.aio.operations.GatewayToolsOperations
+ :ivar gateway_code: GatewayCodeOperations operations
+ :vartype gateway_code: pydo.aio.operations.GatewayCodeOperations
+ :ivar gateway_session_approvals: GatewaySessionApprovalsOperations operations
+ :vartype gateway_session_approvals: pydo.aio.operations.GatewaySessionApprovalsOperations
+ :ivar gateway_approvals: GatewayApprovalsOperations operations
+ :vartype gateway_approvals: pydo.aio.operations.GatewayApprovalsOperations
:ivar one_clicks: OneClicksOperations operations
:vartype one_clicks: pydo.aio.operations.OneClicksOperations
:ivar account: AccountOperations operations
@@ -118,6 +134,8 @@ class GeneratedClient: # pylint: disable=client-accepts-api-version-keyword,too
:vartype actions: pydo.aio.operations.ActionsOperations
:ivar addons: AddonsOperations operations
:vartype addons: pydo.aio.operations.AddonsOperations
+ :ivar harness: HarnessOperations operations
+ :vartype harness: pydo.aio.operations.HarnessOperations
:ivar apps: AppsOperations operations
:vartype apps: pydo.aio.operations.AppsOperations
:ivar cdn: CdnOperations operations
@@ -160,10 +178,16 @@ class GeneratedClient: # pylint: disable=client-accepts-api-version-keyword,too
:vartype image_actions: pydo.aio.operations.ImageActionsOperations
:ivar insights: InsightsOperations operations
:vartype insights: pydo.aio.operations.InsightsOperations
+ :ivar signals: SignalsOperations operations
+ :vartype signals: pydo.aio.operations.SignalsOperations
:ivar kubernetes: KubernetesOperations operations
:vartype kubernetes: pydo.aio.operations.KubernetesOperations
:ivar load_balancers: LoadBalancersOperations operations
:vartype load_balancers: pydo.aio.operations.LoadBalancersOperations
+ :ivar microvms: MicrovmsOperations operations
+ :vartype microvms: pydo.aio.operations.MicrovmsOperations
+ :ivar microvm_checkpoints: MicrovmCheckpointsOperations operations
+ :vartype microvm_checkpoints: pydo.aio.operations.MicrovmCheckpointsOperations
:ivar monitoring: MonitoringOperations operations
:vartype monitoring: pydo.aio.operations.MonitoringOperations
:ivar nfs: NfsOperations operations
@@ -294,6 +318,18 @@ def __init__(
self.users = UsersOperations(
self._client, self._config, self._serialize, self._deserialize
)
+ self.gateway_tools = GatewayToolsOperations(
+ self._client, self._config, self._serialize, self._deserialize
+ )
+ self.gateway_code = GatewayCodeOperations(
+ self._client, self._config, self._serialize, self._deserialize
+ )
+ self.gateway_session_approvals = GatewaySessionApprovalsOperations(
+ self._client, self._config, self._serialize, self._deserialize
+ )
+ self.gateway_approvals = GatewayApprovalsOperations(
+ self._client, self._config, self._serialize, self._deserialize
+ )
self.one_clicks = OneClicksOperations(
self._client, self._config, self._serialize, self._deserialize
)
@@ -309,6 +345,9 @@ def __init__(
self.addons = AddonsOperations(
self._client, self._config, self._serialize, self._deserialize
)
+ self.harness = HarnessOperations(
+ self._client, self._config, self._serialize, self._deserialize
+ )
self.apps = AppsOperations(
self._client, self._config, self._serialize, self._deserialize
)
@@ -372,12 +411,21 @@ def __init__(
self.insights = InsightsOperations(
self._client, self._config, self._serialize, self._deserialize
)
+ self.signals = SignalsOperations(
+ self._client, self._config, self._serialize, self._deserialize
+ )
self.kubernetes = KubernetesOperations(
self._client, self._config, self._serialize, self._deserialize
)
self.load_balancers = LoadBalancersOperations(
self._client, self._config, self._serialize, self._deserialize
)
+ self.microvms = MicrovmsOperations(
+ self._client, self._config, self._serialize, self._deserialize
+ )
+ self.microvm_checkpoints = MicrovmCheckpointsOperations(
+ self._client, self._config, self._serialize, self._deserialize
+ )
self.monitoring = MonitoringOperations(
self._client, self._config, self._serialize, self._deserialize
)
diff --git a/src/pydo/aio/_vendor.py b/src/pydo/aio/_vendor.py
index 422d511d..94e5f091 100644
--- a/src/pydo/aio/_vendor.py
+++ b/src/pydo/aio/_vendor.py
@@ -3,6 +3,10 @@
# Changes may cause incorrect behavior and will be lost if the code is regenerated.
# --------------------------------------------------------------------------
+from typing import Optional
+
+from azure.core import MatchConditions
+
def raise_if_not_implemented(cls, abstract_methods):
not_implemented = [
@@ -15,3 +19,37 @@ def raise_if_not_implemented(cls, abstract_methods):
cls.__name__, "', '".join(not_implemented)
)
)
+
+
+def quote_etag(etag: Optional[str]) -> Optional[str]:
+ if not etag or etag == "*":
+ return etag
+ if etag.startswith("W/"):
+ return etag
+ if etag.startswith('"') and etag.endswith('"'):
+ return etag
+ if etag.startswith("'") and etag.endswith("'"):
+ return etag
+ return '"' + etag + '"'
+
+
+def prep_if_match(
+ etag: Optional[str], match_condition: Optional[MatchConditions]
+) -> Optional[str]:
+ if match_condition == MatchConditions.IfNotModified:
+ if_match = quote_etag(etag) if etag else None
+ return if_match
+ if match_condition == MatchConditions.IfPresent:
+ return "*"
+ return None
+
+
+def prep_if_none_match(
+ etag: Optional[str], match_condition: Optional[MatchConditions]
+) -> Optional[str]:
+ if match_condition == MatchConditions.IfModified:
+ if_none_match = quote_etag(etag) if etag else None
+ return if_none_match
+ if match_condition == MatchConditions.IfMissing:
+ return "*"
+ return None
diff --git a/src/pydo/aio/operations/__init__.py b/src/pydo/aio/operations/__init__.py
index 163af5e7..95dd025c 100644
--- a/src/pydo/aio/operations/__init__.py
+++ b/src/pydo/aio/operations/__init__.py
@@ -12,11 +12,16 @@
from ._operations import ToolbeltsOperations
from ._operations import ToolsOperations
from ._operations import UsersOperations
+from ._operations import GatewayToolsOperations
+from ._operations import GatewayCodeOperations
+from ._operations import GatewaySessionApprovalsOperations
+from ._operations import GatewayApprovalsOperations
from ._operations import OneClicksOperations
from ._operations import AccountOperations
from ._operations import SshKeysOperations
from ._operations import ActionsOperations
from ._operations import AddonsOperations
+from ._operations import HarnessOperations
from ._operations import AppsOperations
from ._operations import CdnOperations
from ._operations import CertificatesOperations
@@ -38,8 +43,11 @@
from ._operations import ImagesOperations
from ._operations import ImageActionsOperations
from ._operations import InsightsOperations
+from ._operations import SignalsOperations
from ._operations import KubernetesOperations
from ._operations import LoadBalancersOperations
+from ._operations import MicrovmsOperations
+from ._operations import MicrovmCheckpointsOperations
from ._operations import MonitoringOperations
from ._operations import NfsOperations
from ._operations import OrganizationsOperations
@@ -86,11 +94,16 @@
"ToolbeltsOperations",
"ToolsOperations",
"UsersOperations",
+ "GatewayToolsOperations",
+ "GatewayCodeOperations",
+ "GatewaySessionApprovalsOperations",
+ "GatewayApprovalsOperations",
"OneClicksOperations",
"AccountOperations",
"SshKeysOperations",
"ActionsOperations",
"AddonsOperations",
+ "HarnessOperations",
"AppsOperations",
"CdnOperations",
"CertificatesOperations",
@@ -112,8 +125,11 @@
"ImagesOperations",
"ImageActionsOperations",
"InsightsOperations",
+ "SignalsOperations",
"KubernetesOperations",
"LoadBalancersOperations",
+ "MicrovmsOperations",
+ "MicrovmCheckpointsOperations",
"MonitoringOperations",
"NfsOperations",
"OrganizationsOperations",
diff --git a/src/pydo/aio/operations/_operations.py b/src/pydo/aio/operations/_operations.py
index 3273a2ff..6fbc0da9 100644
--- a/src/pydo/aio/operations/_operations.py
+++ b/src/pydo/aio/operations/_operations.py
@@ -22,10 +22,12 @@
overload,
)
+from azure.core import MatchConditions
from azure.core.exceptions import (
ClientAuthenticationError,
HttpResponseError,
ResourceExistsError,
+ ResourceModifiedError,
ResourceNotFoundError,
ResourceNotModifiedError,
map_error,
@@ -261,6 +263,12 @@
build_functions_list_namespaces_request,
build_functions_list_triggers_request,
build_functions_update_trigger_request,
+ build_gateway_approvals_update_request,
+ build_gateway_code_run_request,
+ build_gateway_session_approvals_update_request,
+ build_gateway_tools_list_request,
+ build_gateway_tools_list_search_request,
+ build_gateway_tools_run_request,
build_genai_attach_agent_function_request,
build_genai_attach_agent_guardrails_request,
build_genai_attach_agent_request,
@@ -337,9 +345,9 @@
build_genai_get_scenario_set_download_url_request,
build_genai_get_scenario_set_request,
build_genai_get_scheduled_indexing_request,
- build_genai_get_simulation_journey_request,
- build_genai_get_simulation_journey_trajectory_request,
- build_genai_get_simulation_journey_trajectory_url_request,
+ build_genai_get_simulation_episode_request,
+ build_genai_get_simulation_episode_trajectory_request,
+ build_genai_get_simulation_episode_trajectory_url_request,
build_genai_get_simulation_run_request,
build_genai_get_workspace_request,
build_genai_import_custom_model_request,
@@ -376,7 +384,7 @@
build_genai_list_scenario_library_scenarios_request,
build_genai_list_scenario_sets_request,
build_genai_list_scenarios_request,
- build_genai_list_simulation_journeys_request,
+ build_genai_list_simulation_episodes_request,
build_genai_list_simulation_runs_request,
build_genai_list_workspaces_request,
build_genai_patch_cancel_simulation_run_request,
@@ -403,6 +411,60 @@
build_genai_update_scenario_set_request,
build_genai_update_simulation_run_request,
build_genai_update_workspace_request,
+ build_harness_cancel_session_workspace_transfer_request,
+ build_harness_cancel_trigger_execution_request,
+ build_harness_commit_session_workspace_transfer_request,
+ build_harness_create_config_clone_request,
+ build_harness_create_config_request,
+ build_harness_create_session_checkpoint_request,
+ build_harness_create_session_fork_request,
+ build_harness_create_session_input_request,
+ build_harness_create_session_request,
+ build_harness_create_session_workspace_part_upload_urls_request,
+ build_harness_create_session_workspace_transfer_request,
+ build_harness_create_session_workspace_upload_request,
+ build_harness_create_template_request,
+ build_harness_create_trigger_request,
+ build_harness_delete_config_request,
+ build_harness_delete_session_checkpoint_request,
+ build_harness_delete_session_request,
+ build_harness_delete_template_request,
+ build_harness_delete_trigger_request,
+ build_harness_get_config_request,
+ build_harness_get_session_checkpoint_request,
+ build_harness_get_session_events_request,
+ build_harness_get_session_ingress_request,
+ build_harness_get_session_port_forward_request,
+ build_harness_get_session_request,
+ build_harness_get_session_workspace_download_request,
+ build_harness_get_session_workspace_transfer_request,
+ build_harness_get_template_build_request,
+ build_harness_get_template_request,
+ build_harness_get_trigger_by_session_request,
+ build_harness_get_trigger_execution_request,
+ build_harness_get_trigger_request,
+ build_harness_list_config_sessions_request,
+ build_harness_list_configs_request,
+ build_harness_list_reusable_sessions_request,
+ build_harness_list_session_checkpoints_request,
+ build_harness_list_session_sandbox_sizes_request,
+ build_harness_list_sessions_request,
+ build_harness_list_template_builds_request,
+ build_harness_list_templates_request,
+ build_harness_list_trigger_executions_request,
+ build_harness_list_triggers_request,
+ build_harness_list_webhook_providers_request,
+ build_harness_post_session_hitl_request,
+ build_harness_post_session_pause_request,
+ build_harness_post_session_resume_request,
+ build_harness_post_session_sandbox_exec_request,
+ build_harness_post_trigger_rotate_secret_request,
+ build_harness_post_trigger_webhook_request,
+ build_harness_revert_session_checkpoint_request,
+ build_harness_update_session_request,
+ build_harness_update_template_request,
+ build_harness_update_trigger_request,
+ build_harness_validate_session_policy_request,
build_image_actions_get_request,
build_image_actions_list_request,
build_image_actions_post_request,
@@ -442,10 +504,13 @@
build_insights_get_prom_query_range_request,
build_insights_get_prom_query_request,
build_insights_get_prom_series_request,
+ build_insights_get_trace_request,
build_insights_list_alert_instances_request,
build_insights_list_alert_rules_request,
build_insights_list_notification_channels_request,
build_insights_post_logs_search_request,
+ build_insights_post_spans_search_request,
+ build_insights_post_traces_search_request,
build_insights_update_alert_rule_request,
build_insights_update_notification_channel_request,
build_invoices_get_by_uuid_request,
@@ -499,6 +564,19 @@
build_mcp_servers_patch_request,
build_mcp_servers_run_resync_request,
build_mcp_servers_update_tools_request,
+ build_microvm_checkpoints_create_request,
+ build_microvm_checkpoints_delete_request,
+ build_microvm_checkpoints_get_request,
+ build_microvm_checkpoints_list_request,
+ build_microvms_create_request,
+ build_microvms_delete_request,
+ build_microvms_get_console_request,
+ build_microvms_get_options_request,
+ build_microvms_get_request,
+ build_microvms_list_request,
+ build_microvms_post_pause_request,
+ build_microvms_post_resume_request,
+ build_microvms_run_command_request,
build_monitoring_create_alert_policy_request,
build_monitoring_create_destination_request,
build_monitoring_create_sink_request,
@@ -680,6 +758,20 @@
build_sessions_delete_request,
build_sessions_list_request,
build_sessions_list_search_request,
+ build_signals_create_deletion_request,
+ build_signals_create_export_request,
+ build_signals_get_consent_request,
+ build_signals_get_deletion_request,
+ build_signals_get_export_download_request,
+ build_signals_get_export_options_request,
+ build_signals_get_export_request,
+ build_signals_list_agent_sessions_request,
+ build_signals_list_consents_request,
+ build_signals_list_deletions_request,
+ build_signals_list_exports_request,
+ build_signals_list_session_dialogues_request,
+ build_signals_update_consent_request,
+ build_signals_update_team_consent_request,
build_sizes_list_request,
build_snapshots_delete_request,
build_snapshots_get_request,
@@ -11076,14 +11168,14 @@ async def get(self, user_id: str, **kwargs: Any) -> JSON:
return cast(JSON, deserialized) # type: ignore
-class OneClicksOperations:
+class GatewayToolsOperations:
"""
.. warning::
**DO NOT** instantiate this class directly.
Instead, you should access the following operations through
:class:`~pydo.aio.GeneratedClient`'s
- :attr:`one_clicks` attribute.
+ :attr:`gateway_tools` attribute.
"""
def __init__(self, *args, **kwargs) -> None:
@@ -11096,24 +11188,42 @@ def __init__(self, *args, **kwargs) -> None:
)
@distributed_trace_async
- async def list(self, *, type: Optional[str] = None, **kwargs: Any) -> JSON:
- """List 1-Click Applications.
+ async def list(
+ self,
+ *,
+ x_session_id: str,
+ page_size: int = 20,
+ page_token: Optional[str] = None,
+ etag: Optional[str] = None,
+ match_condition: Optional[MatchConditions] = None,
+ **kwargs: Any
+ ) -> Optional[JSON]:
+ # pylint: disable=line-too-long
+ """List Session Tools.
- To list all available 1-Click applications, send a GET request to ``/v2/1-clicks``. The
- ``type`` may
- be provided as query paramater in order to restrict results to a certain type of 1-Click, for
- example: ``/v2/1-clicks?type=droplet``. Current supported types are ``kubernetes`` and
- ``droplet``.
+ Lists the catalog tools that a session can call, ordered by name. The list applies the
+ session's ``tools`` selection and omits tools that its policy always denies.
- The response will be a JSON object with a key called ``1_clicks``. This will be set to an array
- of
- 1-Click application data, each of which will contain the the slug and type for the 1-Click.
+ Each page includes an ``ETag`` header. Send it in ``If-None-Match`` to receive ``304 Not
+ Modified`` while the page is unchanged.
- :keyword type: Restrict results to a certain type of 1-Click. Known values are: "droplet" and
- "kubernetes". Default value is None.
- :paramtype type: str
- :return: JSON object
- :rtype: JSON
+ :keyword x_session_id: The session to act in: the UUID at the end of the session's
+ ``sessionUrn`` and ``mcpUrl``. The session must belong to the authenticated user and team.
+ Required.
+ :paramtype x_session_id: str
+ :keyword page_size: The number of tools returned per page, from 1 to 100. Defaults to 20 when
+ omitted. Other values are rejected with 400. Default value is 20.
+ :paramtype page_size: int
+ :keyword page_token: The ``next_page_token`` from the previous response. A token is only valid
+ for the session that received it. Default value is None.
+ :paramtype page_token: str
+ :keyword etag: check if resource is changed. Set None to skip checking etag. Default value is
+ None.
+ :paramtype etag: str
+ :keyword match_condition: The match condition to use upon the etag. Default value is None.
+ :paramtype match_condition: ~azure.core.MatchConditions
+ :return: JSON object or None
+ :rtype: JSON or None
:raises ~azure.core.exceptions.HttpResponseError:
Example:
@@ -11121,36 +11231,103 @@ async def list(self, *, type: Optional[str] = None, **kwargs: Any) -> JSON:
# response body for status code(s): 200
response == {
- "1_clicks": [
+ "next_page_token": "str", # Optional. An opaque cursor for the next page of
+ results. Pass it back verbatim as ``page_token``. It is empty on the last page.
+ "tools": [
{
- "slug": "str", # The slug identifier for the 1-Click
- application. Required.
- "type": "str" # The type of the 1-Click application.
- Required.
+ "_meta": {
+ "str": {} # Optional. Additional tool metadata.
+ },
+ "annotations": {
+ "destructiveHint": bool, # Optional. The tool may
+ perform destructive updates.
+ "idempotentHint": bool, # Optional. Repeating a call
+ with the same arguments has no additional effect.
+ "openWorldHint": bool, # Optional. The tool
+ interacts with external systems beyond the provider's own data.
+ "readOnlyHint": bool, # Optional. The tool does not
+ modify anything.
+ "title": "str" # Optional. Human-readable tool
+ title.
+ },
+ "description": "str", # Optional. Tools ordered by name.
+ "inputSchema": {
+ "str": {} # Optional. The JSON Schema for the tool's
+ ``arguments``.
+ },
+ "name": "str", # Optional. The provider-qualified tool name.
+ Pass it as ``tool`` to invoke the tool.
+ "outputSchema": {
+ "str": {} # Optional. The JSON Schema for the tool's
+ output, or for the output view bound to the tool in the session.
+ },
+ "parallelizable": bool, # Optional. Whether the tool can run
+ alongside other calls in one invoke request.
+ "streamingSafe": bool, # Optional. Tools ordered by name.
+ "title": "str", # Optional. Tools ordered by name.
+ "version": "str" # Optional. The immutable tool version.
}
- ]
+ ],
+ "version": "str" # Optional. The catalog version.
+ }
+ # response body for status code(s): 400, 412, 429, 500, 503
+ response == {
+ "call_id": "str", # A unique identifier for this request, when one was
+ assigned. Required.
+ "error": {
+ "class": "str", # Optional. The failure class. Branch on this value
+ rather than on ``message``"" , which may change. Known values are:
+ "invalid_argument", "unauthorized", "forbidden", "rate_limited", "not_found",
+ "timeout", "upstream_error", "output_too_large", "execution_failed",
+ "unavailable", "canceled", "render_required", "unsupported_media_type", and
+ "view_materialization_failed".
+ "message": "str", # Optional. A human-readable explanation that is
+ safe to show to an agent or end user.
+ "recovery_hint": "str", # Optional. The suggested next step. Known
+ values are: "fix_args", "refresh_auth", "retry_later", "narrow_output",
+ "contact_support", and "verify_provider_state".
+ "retriable": bool # Optional. Whether retrying the same request
+ later can succeed.
+ },
+ "status": "str" # Required. "failed"
+ }
+ # response body for status code(s): 401
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
}
"""
error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 401: ClientAuthenticationError,
404: ResourceNotFoundError,
409: ResourceExistsError,
304: ResourceNotModifiedError,
- 401: cast(
- Type[HttpResponseError],
- lambda response: ClientAuthenticationError(response=response),
- ),
- 429: HttpResponseError,
- 500: HttpResponseError,
}
+ if match_condition == MatchConditions.IfNotModified:
+ error_map[412] = ResourceModifiedError
+ elif match_condition == MatchConditions.IfPresent:
+ error_map[412] = ResourceNotFoundError
+ elif match_condition == MatchConditions.IfMissing:
+ error_map[412] = ResourceExistsError
error_map.update(kwargs.pop("error_map", {}) or {})
_headers = kwargs.pop("headers", {}) or {}
_params = kwargs.pop("params", {}) or {}
- cls: ClsType[JSON] = kwargs.pop("cls", None)
+ cls: ClsType[Optional[JSON]] = kwargs.pop("cls", None)
- _request = build_one_clicks_list_request(
- type=type,
+ _request = build_gateway_tools_list_request(
+ x_session_id=x_session_id,
+ page_size=page_size,
+ page_token=page_token,
+ etag=etag,
+ match_condition=match_condition,
headers=_headers,
params=_params,
)
@@ -11165,47 +11342,104 @@ async def list(self, *, type: Optional[str] = None, **kwargs: Any) -> JSON:
response = pipeline_response.http_response
- if response.status_code not in [200]:
+ if response.status_code not in [200, 304, 400, 401, 403, 412, 429, 500, 503]:
if _stream:
await response.read() # Load the body in memory and close the socket
- map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ map_error(
+ status_code=response.status_code, response=response, error_map=error_map
+ )
raise HttpResponseError(response=response)
+ deserialized = None
response_headers = {}
- response_headers["ratelimit-limit"] = self._deserialize(
- "int", response.headers.get("ratelimit-limit")
- )
- response_headers["ratelimit-remaining"] = self._deserialize(
- "int", response.headers.get("ratelimit-remaining")
- )
- response_headers["ratelimit-reset"] = self._deserialize(
- "int", response.headers.get("ratelimit-reset")
- )
+ if response.status_code == 200:
+ response_headers["ETag"] = self._deserialize(
+ "str", response.headers.get("ETag")
+ )
- if response.content:
- deserialized = response.json()
- else:
- deserialized = None
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 400:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 401:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 403:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 412:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 429:
+ response_headers["Retry-After"] = self._deserialize(
+ "int", response.headers.get("Retry-After")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 500:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 503:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
if cls:
- return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+ return cls(pipeline_response, deserialized, response_headers) # type: ignore
- return cast(JSON, deserialized) # type: ignore
+ return deserialized # type: ignore
@overload
- async def install_kubernetes(
- self, body: JSON, *, content_type: str = "application/json", **kwargs: Any
+ async def list_search(
+ self,
+ body: JSON,
+ *,
+ x_session_id: str,
+ content_type: str = "application/json",
+ **kwargs: Any
) -> JSON:
# pylint: disable=line-too-long
- """Install Kubernetes 1-Click Applications.
+ """Search Session Tools.
- To install a Kubernetes 1-Click application on a cluster, send a POST request to
- ``/v2/1-clicks/kubernetes``. The ``addon_slugs`` and ``cluster_uuid`` must be provided as body
- parameter in order to specify which 1-Click application(s) to install. To list all available
- 1-Click Kubernetes applications, send a request to ``/v2/1-clicks?type=kubernetes``.
+ Finds the catalog tools that fit one or more use cases. This is the REST form of the
+ ``action_search`` MCP tool. Each query is searched independently and returns its own result
+ group, so you can see which tools serve which goal. Results include each tool's
+ ``inputSchema``\\ , so you can call a tool with ``POST /tools/invoke`` without another lookup.
+
+ Results include only tools that the session can call. If the session policy requires approval
+ for ``action_search``\\ , the response is a failed result with ``_meta.status`` set to
+ ``requires_approval``.
:param body: Required.
:type body: JSON
+ :keyword x_session_id: The session to act in: the UUID at the end of the session's
+ ``sessionUrn`` and ``mcpUrl``. The session must belong to the authenticated user and team.
+ Required.
+ :paramtype x_session_id: str
:keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
Default value is "application/json".
:paramtype content_type: str
@@ -11218,33 +11452,153 @@ async def install_kubernetes(
# JSON input template you can fill out and use as your body input.
body = {
- "addon_slugs": [
- "str" # An array of 1-Click Application slugs to be installed to the
- Kubernetes cluster. Required.
+ "queries": [
+ {
+ "use_case": "str", # A normalized English description of one
+ complete use case: the action and the intended outcome, including any app
+ the user named. Put personal identifiers in ``known_fields`` instead. Up
+ to 512 bytes and 32 search terms, with at least one letter or digit.
+ Required.
+ "known_fields": "str" # Optional. Known workflow inputs as
+ one string of comma-separated ``key:value`` pairs, such as identifiers or
+ settings. Used as context, not for keyword matching.
+ }
],
- "cluster_uuid": "str" # A unique ID for the Kubernetes cluster to which the
- 1-Click Applications will be installed. Required.
+ "limit": 10, # Optional. Default value is 10. The maximum number of tools
+ returned per query. Values above 50 are capped at 50.
+ "providers": [
+ "str" # Optional. Restricts every query to these providers.
+ ],
+ "tags": [
+ "str" # Optional. Restricts every query to tools with these tags.
+ ]
}
# response body for status code(s): 200
response == {
- "message": "str" # Optional. A message about the result of the request.
+ "call_id": "str", # A unique identifier for this call. Include it when
+ contacting support. Required.
+ "status": "str", # Required. Known values are: "succeeded" and "failed".
+ "_meta": {
+ "str": {} # Optional. Additional result metadata. Keys include: *
+ ``status``"" : ``requires_approval``"" , ``requires_authorization``"" , or
+ ``requires_connection_configuration`` when the call stopped before running.
+ * ``approval_id``"" , ``tool_name``"" , ``expires_at``"" , and
+ ``decide``"" : present with ``requires_approval``. ``decide`` gives the
+ ``method``"" , ``path``"" , and ``body`` of the approval request to send.
+ Approve the call, then repeat it with the same arguments before
+ ``expires_at``. * `retry`: `{"attempt_count": N, "exhausted": bool}` when
+ the gateway retried the call. * ``output_view``"" : the output view
+ applied to the result.
+ },
+ "error": {
+ "class": "str", # Optional. The failure class. Branch on this value
+ rather than on ``message``"" , which may change. Known values are:
+ "invalid_argument", "unauthorized", "forbidden", "rate_limited", "not_found",
+ "timeout", "upstream_error", "output_too_large", "execution_failed",
+ "unavailable", "canceled", "render_required", "unsupported_media_type", and
+ "view_materialization_failed".
+ "message": "str", # Optional. A human-readable explanation that is
+ safe to show to an agent or end user.
+ "recovery_hint": "str", # Optional. The suggested next step. Known
+ values are: "fix_args", "refresh_auth", "retry_later", "narrow_output",
+ "contact_support", and "verify_provider_state".
+ "retriable": bool # Optional. Whether retrying the same request
+ later can succeed.
+ },
+ "output": {
+ "results": [
+ {
+ "guidance": "str", # Optional. A suggested next
+ step. Present only when no tools matched.
+ "index": 0, # Optional. The 1-based position of the
+ query in the request.
+ "results": [
+ {
+ "description": "str", # Optional.
+ One result group per query, in request order.
+ "inputSchema": {
+ "str": {} # Optional. The
+ JSON Schema for the tool's ``arguments``.
+ },
+ "name": "str", # Optional. The
+ provider-qualified tool name. Pass it as ``tool`` to invoke
+ the tool.
+ "score": 0.0, # Optional. The
+ relevance score. Higher is more relevant.
+ "title": "str", # Optional. One
+ result group per query, in request order.
+ "version": "str" # Optional. One
+ result group per query, in request order.
+ }
+ ],
+ "use_case": "str" # Optional. The query's
+ ``use_case``.
+ }
+ ]
+ }
+ }
+ # response body for status code(s): 400, 412, 413, 429, 500, 503
+ response == {
+ "call_id": "str", # A unique identifier for this request, when one was
+ assigned. Required.
+ "error": {
+ "class": "str", # Optional. The failure class. Branch on this value
+ rather than on ``message``"" , which may change. Known values are:
+ "invalid_argument", "unauthorized", "forbidden", "rate_limited", "not_found",
+ "timeout", "upstream_error", "output_too_large", "execution_failed",
+ "unavailable", "canceled", "render_required", "unsupported_media_type", and
+ "view_materialization_failed".
+ "message": "str", # Optional. A human-readable explanation that is
+ safe to show to an agent or end user.
+ "recovery_hint": "str", # Optional. The suggested next step. Known
+ values are: "fix_args", "refresh_auth", "retry_later", "narrow_output",
+ "contact_support", and "verify_provider_state".
+ "retriable": bool # Optional. Whether retrying the same request
+ later can succeed.
+ },
+ "status": "str" # Required. "failed"
+ }
+ # response body for status code(s): 401
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
}
"""
@overload
- async def install_kubernetes(
- self, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any
+ async def list_search(
+ self,
+ body: IO[bytes],
+ *,
+ x_session_id: str,
+ content_type: str = "application/json",
+ **kwargs: Any
) -> JSON:
- """Install Kubernetes 1-Click Applications.
+ # pylint: disable=line-too-long
+ """Search Session Tools.
- To install a Kubernetes 1-Click application on a cluster, send a POST request to
- ``/v2/1-clicks/kubernetes``. The ``addon_slugs`` and ``cluster_uuid`` must be provided as body
- parameter in order to specify which 1-Click application(s) to install. To list all available
- 1-Click Kubernetes applications, send a request to ``/v2/1-clicks?type=kubernetes``.
+ Finds the catalog tools that fit one or more use cases. This is the REST form of the
+ ``action_search`` MCP tool. Each query is searched independently and returns its own result
+ group, so you can see which tools serve which goal. Results include each tool's
+ ``inputSchema``\\ , so you can call a tool with ``POST /tools/invoke`` without another lookup.
+
+ Results include only tools that the session can call. If the session policy requires approval
+ for ``action_search``\\ , the response is a failed result with ``_meta.status`` set to
+ ``requires_approval``.
:param body: Required.
:type body: IO[bytes]
+ :keyword x_session_id: The session to act in: the UUID at the end of the session's
+ ``sessionUrn`` and ``mcpUrl``. The session must belong to the authenticated user and team.
+ Required.
+ :paramtype x_session_id: str
:keyword content_type: Body Parameter content-type. Content type parameter for binary body.
Default value is "application/json".
:paramtype content_type: str
@@ -11257,24 +11611,124 @@ async def install_kubernetes(
# response body for status code(s): 200
response == {
- "message": "str" # Optional. A message about the result of the request.
+ "call_id": "str", # A unique identifier for this call. Include it when
+ contacting support. Required.
+ "status": "str", # Required. Known values are: "succeeded" and "failed".
+ "_meta": {
+ "str": {} # Optional. Additional result metadata. Keys include: *
+ ``status``"" : ``requires_approval``"" , ``requires_authorization``"" , or
+ ``requires_connection_configuration`` when the call stopped before running.
+ * ``approval_id``"" , ``tool_name``"" , ``expires_at``"" , and
+ ``decide``"" : present with ``requires_approval``. ``decide`` gives the
+ ``method``"" , ``path``"" , and ``body`` of the approval request to send.
+ Approve the call, then repeat it with the same arguments before
+ ``expires_at``. * `retry`: `{"attempt_count": N, "exhausted": bool}` when
+ the gateway retried the call. * ``output_view``"" : the output view
+ applied to the result.
+ },
+ "error": {
+ "class": "str", # Optional. The failure class. Branch on this value
+ rather than on ``message``"" , which may change. Known values are:
+ "invalid_argument", "unauthorized", "forbidden", "rate_limited", "not_found",
+ "timeout", "upstream_error", "output_too_large", "execution_failed",
+ "unavailable", "canceled", "render_required", "unsupported_media_type", and
+ "view_materialization_failed".
+ "message": "str", # Optional. A human-readable explanation that is
+ safe to show to an agent or end user.
+ "recovery_hint": "str", # Optional. The suggested next step. Known
+ values are: "fix_args", "refresh_auth", "retry_later", "narrow_output",
+ "contact_support", and "verify_provider_state".
+ "retriable": bool # Optional. Whether retrying the same request
+ later can succeed.
+ },
+ "output": {
+ "results": [
+ {
+ "guidance": "str", # Optional. A suggested next
+ step. Present only when no tools matched.
+ "index": 0, # Optional. The 1-based position of the
+ query in the request.
+ "results": [
+ {
+ "description": "str", # Optional.
+ One result group per query, in request order.
+ "inputSchema": {
+ "str": {} # Optional. The
+ JSON Schema for the tool's ``arguments``.
+ },
+ "name": "str", # Optional. The
+ provider-qualified tool name. Pass it as ``tool`` to invoke
+ the tool.
+ "score": 0.0, # Optional. The
+ relevance score. Higher is more relevant.
+ "title": "str", # Optional. One
+ result group per query, in request order.
+ "version": "str" # Optional. One
+ result group per query, in request order.
+ }
+ ],
+ "use_case": "str" # Optional. The query's
+ ``use_case``.
+ }
+ ]
+ }
+ }
+ # response body for status code(s): 400, 412, 413, 429, 500, 503
+ response == {
+ "call_id": "str", # A unique identifier for this request, when one was
+ assigned. Required.
+ "error": {
+ "class": "str", # Optional. The failure class. Branch on this value
+ rather than on ``message``"" , which may change. Known values are:
+ "invalid_argument", "unauthorized", "forbidden", "rate_limited", "not_found",
+ "timeout", "upstream_error", "output_too_large", "execution_failed",
+ "unavailable", "canceled", "render_required", "unsupported_media_type", and
+ "view_materialization_failed".
+ "message": "str", # Optional. A human-readable explanation that is
+ safe to show to an agent or end user.
+ "recovery_hint": "str", # Optional. The suggested next step. Known
+ values are: "fix_args", "refresh_auth", "retry_later", "narrow_output",
+ "contact_support", and "verify_provider_state".
+ "retriable": bool # Optional. Whether retrying the same request
+ later can succeed.
+ },
+ "status": "str" # Required. "failed"
+ }
+ # response body for status code(s): 401
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
}
"""
@distributed_trace_async
- async def install_kubernetes(
- self, body: Union[JSON, IO[bytes]], **kwargs: Any
+ async def list_search(
+ self, body: Union[JSON, IO[bytes]], *, x_session_id: str, **kwargs: Any
) -> JSON:
# pylint: disable=line-too-long
- """Install Kubernetes 1-Click Applications.
+ """Search Session Tools.
- To install a Kubernetes 1-Click application on a cluster, send a POST request to
- ``/v2/1-clicks/kubernetes``. The ``addon_slugs`` and ``cluster_uuid`` must be provided as body
- parameter in order to specify which 1-Click application(s) to install. To list all available
- 1-Click Kubernetes applications, send a request to ``/v2/1-clicks?type=kubernetes``.
+ Finds the catalog tools that fit one or more use cases. This is the REST form of the
+ ``action_search`` MCP tool. Each query is searched independently and returns its own result
+ group, so you can see which tools serve which goal. Results include each tool's
+ ``inputSchema``\\ , so you can call a tool with ``POST /tools/invoke`` without another lookup.
+
+ Results include only tools that the session can call. If the session policy requires approval
+ for ``action_search``\\ , the response is a failed result with ``_meta.status`` set to
+ ``requires_approval``.
:param body: Is either a JSON type or a IO[bytes] type. Required.
:type body: JSON or IO[bytes]
+ :keyword x_session_id: The session to act in: the UUID at the end of the session's
+ ``sessionUrn`` and ``mcpUrl``. The session must belong to the authenticated user and team.
+ Required.
+ :paramtype x_session_id: str
:return: JSON object
:rtype: JSON
:raises ~azure.core.exceptions.HttpResponseError:
@@ -11284,29 +11738,130 @@ async def install_kubernetes(
# JSON input template you can fill out and use as your body input.
body = {
- "addon_slugs": [
- "str" # An array of 1-Click Application slugs to be installed to the
- Kubernetes cluster. Required.
+ "queries": [
+ {
+ "use_case": "str", # A normalized English description of one
+ complete use case: the action and the intended outcome, including any app
+ the user named. Put personal identifiers in ``known_fields`` instead. Up
+ to 512 bytes and 32 search terms, with at least one letter or digit.
+ Required.
+ "known_fields": "str" # Optional. Known workflow inputs as
+ one string of comma-separated ``key:value`` pairs, such as identifiers or
+ settings. Used as context, not for keyword matching.
+ }
],
- "cluster_uuid": "str" # A unique ID for the Kubernetes cluster to which the
- 1-Click Applications will be installed. Required.
+ "limit": 10, # Optional. Default value is 10. The maximum number of tools
+ returned per query. Values above 50 are capped at 50.
+ "providers": [
+ "str" # Optional. Restricts every query to these providers.
+ ],
+ "tags": [
+ "str" # Optional. Restricts every query to tools with these tags.
+ ]
}
# response body for status code(s): 200
response == {
- "message": "str" # Optional. A message about the result of the request.
+ "call_id": "str", # A unique identifier for this call. Include it when
+ contacting support. Required.
+ "status": "str", # Required. Known values are: "succeeded" and "failed".
+ "_meta": {
+ "str": {} # Optional. Additional result metadata. Keys include: *
+ ``status``"" : ``requires_approval``"" , ``requires_authorization``"" , or
+ ``requires_connection_configuration`` when the call stopped before running.
+ * ``approval_id``"" , ``tool_name``"" , ``expires_at``"" , and
+ ``decide``"" : present with ``requires_approval``. ``decide`` gives the
+ ``method``"" , ``path``"" , and ``body`` of the approval request to send.
+ Approve the call, then repeat it with the same arguments before
+ ``expires_at``. * `retry`: `{"attempt_count": N, "exhausted": bool}` when
+ the gateway retried the call. * ``output_view``"" : the output view
+ applied to the result.
+ },
+ "error": {
+ "class": "str", # Optional. The failure class. Branch on this value
+ rather than on ``message``"" , which may change. Known values are:
+ "invalid_argument", "unauthorized", "forbidden", "rate_limited", "not_found",
+ "timeout", "upstream_error", "output_too_large", "execution_failed",
+ "unavailable", "canceled", "render_required", "unsupported_media_type", and
+ "view_materialization_failed".
+ "message": "str", # Optional. A human-readable explanation that is
+ safe to show to an agent or end user.
+ "recovery_hint": "str", # Optional. The suggested next step. Known
+ values are: "fix_args", "refresh_auth", "retry_later", "narrow_output",
+ "contact_support", and "verify_provider_state".
+ "retriable": bool # Optional. Whether retrying the same request
+ later can succeed.
+ },
+ "output": {
+ "results": [
+ {
+ "guidance": "str", # Optional. A suggested next
+ step. Present only when no tools matched.
+ "index": 0, # Optional. The 1-based position of the
+ query in the request.
+ "results": [
+ {
+ "description": "str", # Optional.
+ One result group per query, in request order.
+ "inputSchema": {
+ "str": {} # Optional. The
+ JSON Schema for the tool's ``arguments``.
+ },
+ "name": "str", # Optional. The
+ provider-qualified tool name. Pass it as ``tool`` to invoke
+ the tool.
+ "score": 0.0, # Optional. The
+ relevance score. Higher is more relevant.
+ "title": "str", # Optional. One
+ result group per query, in request order.
+ "version": "str" # Optional. One
+ result group per query, in request order.
+ }
+ ],
+ "use_case": "str" # Optional. The query's
+ ``use_case``.
+ }
+ ]
+ }
+ }
+ # response body for status code(s): 400, 412, 413, 429, 500, 503
+ response == {
+ "call_id": "str", # A unique identifier for this request, when one was
+ assigned. Required.
+ "error": {
+ "class": "str", # Optional. The failure class. Branch on this value
+ rather than on ``message``"" , which may change. Known values are:
+ "invalid_argument", "unauthorized", "forbidden", "rate_limited", "not_found",
+ "timeout", "upstream_error", "output_too_large", "execution_failed",
+ "unavailable", "canceled", "render_required", "unsupported_media_type", and
+ "view_materialization_failed".
+ "message": "str", # Optional. A human-readable explanation that is
+ safe to show to an agent or end user.
+ "recovery_hint": "str", # Optional. The suggested next step. Known
+ values are: "fix_args", "refresh_auth", "retry_later", "narrow_output",
+ "contact_support", and "verify_provider_state".
+ "retriable": bool # Optional. Whether retrying the same request
+ later can succeed.
+ },
+ "status": "str" # Required. "failed"
+ }
+ # response body for status code(s): 401
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
}
"""
error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 401: ClientAuthenticationError,
404: ResourceNotFoundError,
409: ResourceExistsError,
304: ResourceNotModifiedError,
- 401: cast(
- Type[HttpResponseError],
- lambda response: ClientAuthenticationError(response=response),
- ),
- 429: HttpResponseError,
- 500: HttpResponseError,
}
error_map.update(kwargs.pop("error_map", {}) or {})
@@ -11326,7 +11881,8 @@ async def install_kubernetes(
else:
_json = body
- _request = build_one_clicks_install_kubernetes_request(
+ _request = build_gateway_tools_list_search_request(
+ x_session_id=x_session_id,
content_type=content_type,
json=_json,
content=_content,
@@ -11344,277 +11900,72 @@ async def install_kubernetes(
response = pipeline_response.http_response
- if response.status_code not in [200]:
+ if response.status_code not in [200, 400, 401, 403, 412, 413, 429, 500, 503]:
if _stream:
await response.read() # Load the body in memory and close the socket
- map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
- raise HttpResponseError(response=response)
-
- response_headers = {}
- response_headers["ratelimit-limit"] = self._deserialize(
- "int", response.headers.get("ratelimit-limit")
- )
- response_headers["ratelimit-remaining"] = self._deserialize(
- "int", response.headers.get("ratelimit-remaining")
- )
- response_headers["ratelimit-reset"] = self._deserialize(
- "int", response.headers.get("ratelimit-reset")
- )
-
- if response.content:
- deserialized = response.json()
- else:
- deserialized = None
-
- if cls:
- return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
-
- return cast(JSON, deserialized) # type: ignore
-
-
-class AccountOperations:
- """
- .. warning::
- **DO NOT** instantiate this class directly.
-
- Instead, you should access the following operations through
- :class:`~pydo.aio.GeneratedClient`'s
- :attr:`account` attribute.
- """
-
- def __init__(self, *args, **kwargs) -> None:
- input_args = list(args)
- self._client = input_args.pop(0) if input_args else kwargs.pop("client")
- self._config = input_args.pop(0) if input_args else kwargs.pop("config")
- self._serialize = input_args.pop(0) if input_args else kwargs.pop("serializer")
- self._deserialize = (
- input_args.pop(0) if input_args else kwargs.pop("deserializer")
- )
-
- @distributed_trace_async
- async def get(self, **kwargs: Any) -> JSON:
- # pylint: disable=line-too-long
- """Get User Information.
-
- To show information about the current user account, send a GET request to ``/v2/account``.
-
- :return: JSON object
- :rtype: JSON
- :raises ~azure.core.exceptions.HttpResponseError:
-
- Example:
- .. code-block:: python
-
- # response body for status code(s): 200
- response == {
- "account": {
- "droplet_limit": 0, # The total number of Droplets current user or
- team may have active at one time. :code:` `:code:` `Requires
- ``droplet:read`` scope. Required.
- "email": "str", # The email address used by the current user to
- register for DigitalOcean. Required.
- "email_verified": False, # Default value is False. If true, the user
- has verified their account via email. False otherwise. Required.
- "floating_ip_limit": 0, # The total number of Floating IPs the
- current user or team may have. :code:` `:code:` `Requires
- ``reserved_ip:read`` scope. Required.
- "status": "active", # Default value is "active". This value is one
- of "active", "warning" or "locked". Known values are: "active", "warning",
- and "locked".
- "status_message": "str", # A human-readable message giving more
- details about the status of the account. Required.
- "uuid": "str", # The unique universal identifier for the current
- user. Required.
- "name": "str", # Optional. The display name for the current user.
- "team": {
- "name": "str", # Optional. The name for the current team.
- "uuid": "str" # Optional. The unique universal identifier
- for the current team.
- }
- }
- }
- """
- error_map: MutableMapping[int, Type[HttpResponseError]] = {
- 404: ResourceNotFoundError,
- 409: ResourceExistsError,
- 304: ResourceNotModifiedError,
- 401: cast(
- Type[HttpResponseError],
- lambda response: ClientAuthenticationError(response=response),
- ),
- 429: HttpResponseError,
- 500: HttpResponseError,
- }
- error_map.update(kwargs.pop("error_map", {}) or {})
-
- _headers = kwargs.pop("headers", {}) or {}
- _params = kwargs.pop("params", {}) or {}
-
- cls: ClsType[JSON] = kwargs.pop("cls", None)
-
- _request = build_account_get_request(
- headers=_headers,
- params=_params,
- )
- _request.url = self._client.format_url(_request.url)
-
- _stream = False
- pipeline_response: PipelineResponse = (
- await self._client._pipeline.run( # pylint: disable=protected-access
- _request, stream=_stream, **kwargs
+ map_error(
+ status_code=response.status_code, response=response, error_map=error_map
)
- )
-
- response = pipeline_response.http_response
-
- if response.status_code not in [200]:
- if _stream:
- await response.read() # Load the body in memory and close the socket
- map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
raise HttpResponseError(response=response)
response_headers = {}
- response_headers["ratelimit-limit"] = self._deserialize(
- "int", response.headers.get("ratelimit-limit")
- )
- response_headers["ratelimit-remaining"] = self._deserialize(
- "int", response.headers.get("ratelimit-remaining")
- )
- response_headers["ratelimit-reset"] = self._deserialize(
- "int", response.headers.get("ratelimit-reset")
- )
-
- if response.content:
- deserialized = response.json()
- else:
- deserialized = None
-
- if cls:
- return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
-
- return cast(JSON, deserialized) # type: ignore
-
-
-class SshKeysOperations:
- """
- .. warning::
- **DO NOT** instantiate this class directly.
-
- Instead, you should access the following operations through
- :class:`~pydo.aio.GeneratedClient`'s
- :attr:`ssh_keys` attribute.
- """
-
- def __init__(self, *args, **kwargs) -> None:
- input_args = list(args)
- self._client = input_args.pop(0) if input_args else kwargs.pop("client")
- self._config = input_args.pop(0) if input_args else kwargs.pop("config")
- self._serialize = input_args.pop(0) if input_args else kwargs.pop("serializer")
- self._deserialize = (
- input_args.pop(0) if input_args else kwargs.pop("deserializer")
- )
-
- @distributed_trace_async
- async def list(self, *, per_page: int = 20, page: int = 1, **kwargs: Any) -> JSON:
- # pylint: disable=line-too-long
- """List All SSH Keys.
-
- To list all of the keys in your account, send a GET request to ``/v2/account/keys``. The
- response will be a JSON object with a key set to ``ssh_keys``. The value of this will be an
- array of ssh_key objects, each of which contains the standard ssh_key attributes.
-
- :keyword per_page: Number of items returned per page. Default value is 20.
- :paramtype per_page: int
- :keyword page: Which 'page' of paginated results to return. Default value is 1.
- :paramtype page: int
- :return: JSON object
- :rtype: JSON
- :raises ~azure.core.exceptions.HttpResponseError:
+ if response.status_code == 200:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
- Example:
- .. code-block:: python
+ if response.status_code == 400:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
- # response body for status code(s): 200
- response == {
- "meta": {
- "total": 0 # Optional. Number of objects returned by the request.
- },
- "links": {
- "pages": {}
- },
- "ssh_keys": [
- {
- "name": "str", # A human-readable display name for this key,
- used to easily identify the SSH keys when they are displayed. Required.
- "public_key": "str", # The entire public key string that was
- uploaded. Embedded into the root user's ``authorized_keys`` file if you
- include this key during Droplet creation. Required.
- "fingerprint": "str", # Optional. A unique identifier that
- differentiates this key from other keys using a format that SSH
- recognizes. The fingerprint is created when the key is added to your
- account.
- "id": 0 # Optional. A unique identification number for this
- key. Can be used to embed a specific SSH key into a Droplet.
- }
- ]
- }
- """
- error_map: MutableMapping[int, Type[HttpResponseError]] = {
- 404: ResourceNotFoundError,
- 409: ResourceExistsError,
- 304: ResourceNotModifiedError,
- 401: cast(
- Type[HttpResponseError],
- lambda response: ClientAuthenticationError(response=response),
- ),
- 429: HttpResponseError,
- 500: HttpResponseError,
- }
- error_map.update(kwargs.pop("error_map", {}) or {})
+ if response.status_code == 401:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
- _headers = kwargs.pop("headers", {}) or {}
- _params = kwargs.pop("params", {}) or {}
+ if response.status_code == 403:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
- cls: ClsType[JSON] = kwargs.pop("cls", None)
+ if response.status_code == 412:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
- _request = build_ssh_keys_list_request(
- per_page=per_page,
- page=page,
- headers=_headers,
- params=_params,
- )
- _request.url = self._client.format_url(_request.url)
+ if response.status_code == 413:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
- _stream = False
- pipeline_response: PipelineResponse = (
- await self._client._pipeline.run( # pylint: disable=protected-access
- _request, stream=_stream, **kwargs
+ if response.status_code == 429:
+ response_headers["Retry-After"] = self._deserialize(
+ "int", response.headers.get("Retry-After")
)
- )
-
- response = pipeline_response.http_response
- if response.status_code not in [200]:
- if _stream:
- await response.read() # Load the body in memory and close the socket
- map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
- raise HttpResponseError(response=response)
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
- response_headers = {}
- response_headers["ratelimit-limit"] = self._deserialize(
- "int", response.headers.get("ratelimit-limit")
- )
- response_headers["ratelimit-remaining"] = self._deserialize(
- "int", response.headers.get("ratelimit-remaining")
- )
- response_headers["ratelimit-reset"] = self._deserialize(
- "int", response.headers.get("ratelimit-reset")
- )
+ if response.status_code == 500:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
- if response.content:
- deserialized = response.json()
- else:
- deserialized = None
+ if response.status_code == 503:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
if cls:
return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
@@ -11622,18 +11973,36 @@ async def list(self, *, per_page: int = 20, page: int = 1, **kwargs: Any) -> JSO
return cast(JSON, deserialized) # type: ignore
@overload
- async def create(
- self, body: JSON, *, content_type: str = "application/json", **kwargs: Any
+ async def run(
+ self,
+ body: JSON,
+ *,
+ x_session_id: str,
+ content_type: str = "application/json",
+ **kwargs: Any
) -> JSON:
# pylint: disable=line-too-long
- """Create a New SSH Key.
+ """Invoke Session Tools.
- To add a new SSH public key to your DigitalOcean account, send a POST request to
- ``/v2/account/keys``. Set the ``name`` attribute to the name you wish to use and the
- ``public_key`` attribute to the full public key you are adding.
+ Runs 1 to 10 tool calls in parallel and returns one result per call, in request order. This is
+ the REST form of the ``action_invoke`` MCP tool.
+
+ Each call is checked against the session's tool selection and policy, uses the session actor's
+ connections, and applies any output view bound to the tool in the session. A well-formed
+ request returns ``200`` even when some calls fail. Check each item's ``result.status``\\ , and
+ use ``success_count`` and ``error_count`` to branch without scanning every item.
+
+ A call whose policy requires approval fails with ``_meta.status`` set to ``requires_approval``.
+ Have the session's owner approve it, then repeat the call with the same arguments. A call that
+ needs the end user to connect a provider fails with ``_meta.status`` set to
+ ``requires_authorization`` or ``requires_connection_configuration``.
:param body: Required.
:type body: JSON
+ :keyword x_session_id: The session to act in: the UUID at the end of the session's
+ ``sessionUrn`` and ``mcpUrl``. The session must belong to the authenticated user and team.
+ Required.
+ :paramtype x_session_id: str
:keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
Default value is "application/json".
:paramtype content_type: str
@@ -11646,48 +12015,145 @@ async def create(
# JSON input template you can fill out and use as your body input.
body = {
- "name": "str", # A human-readable display name for this key, used to easily
- identify the SSH keys when they are displayed. Required.
- "public_key": "str", # The entire public key string that was uploaded.
- Embedded into the root user's ``authorized_keys`` file if you include this key
- during Droplet creation. Required.
- "fingerprint": "str", # Optional. A unique identifier that differentiates
- this key from other keys using a format that SSH recognizes. The fingerprint is
- created when the key is added to your account.
- "id": 0 # Optional. A unique identification number for this key. Can be used
- to embed a specific SSH key into a Droplet.
+ "tools": [
+ {
+ "tool": "str", # The tool name, as returned by ``GET
+ /tools`` or ``POST /tools/search``. Names are case-insensitive. Required.
+ "arguments": {
+ "str": {} # Optional. The tool's arguments, matching
+ its ``inputSchema``.
+ },
+ "version": "str" # Optional. An immutable tool version. Omit
+ to use the released version.
+ }
+ ],
+ "rationale": "str" # Optional. One sentence explaining why the tools are
+ being called. Values longer than 512 characters are truncated.
}
- # response body for status code(s): 201
+ # response body for status code(s): 200
response == {
- "ssh_key": {
- "name": "str", # A human-readable display name for this key, used to
- easily identify the SSH keys when they are displayed. Required.
- "public_key": "str", # The entire public key string that was
- uploaded. Embedded into the root user's ``authorized_keys`` file if you
- include this key during Droplet creation. Required.
- "fingerprint": "str", # Optional. A unique identifier that
- differentiates this key from other keys using a format that SSH recognizes.
- The fingerprint is created when the key is added to your account.
- "id": 0 # Optional. A unique identification number for this key. Can
- be used to embed a specific SSH key into a Droplet.
- }
+ "error_count": 0, # Optional.
+ "results": [
+ {
+ "index": 0, # Optional. The 0-based position of the call in
+ the request.
+ "result": {
+ "call_id": "str", # A unique identifier for this
+ call. Include it when contacting support. Required.
+ "status": "str", # Required. Known values are:
+ "succeeded" and "failed".
+ "_meta": {
+ "str": {} # Optional. Additional result
+ metadata. Keys include: * ``status``"" :
+ ``requires_approval``"" , ``requires_authorization``"" , or
+ ``requires_connection_configuration`` when the call stopped
+ before running. * ``approval_id``"" , ``tool_name``"" ,
+ ``expires_at``"" , and ``decide``"" : present with
+ ``requires_approval``. ``decide`` gives the ``method``"" ,
+ ``path``"" , and ``body`` of the approval request to send.
+ Approve the call, then repeat it with the same arguments before
+ ``expires_at``. * `retry`: `{"attempt_count": N, "exhausted":
+ bool}` when the gateway retried the call. *
+ ``output_view``"" : the output view applied to the result.
+ },
+ "error": {
+ "class": "str", # Optional. The failure
+ class. Branch on this value rather than on ``message``"" , which
+ may change. Known values are: "invalid_argument", "unauthorized",
+ "forbidden", "rate_limited", "not_found", "timeout",
+ "upstream_error", "output_too_large", "execution_failed",
+ "unavailable", "canceled", "render_required",
+ "unsupported_media_type", and "view_materialization_failed".
+ "message": "str", # Optional. A
+ human-readable explanation that is safe to show to an agent or
+ end user.
+ "recovery_hint": "str", # Optional. The
+ suggested next step. Known values are: "fix_args",
+ "refresh_auth", "retry_later", "narrow_output",
+ "contact_support", and "verify_provider_state".
+ "retriable": bool # Optional. Whether
+ retrying the same request later can succeed.
+ },
+ "output": {
+ "str": {} # Optional. The tool's JSON
+ output. Present when ``status`` is ``succeeded``. Its shape is
+ the tool's output schema, or the output view bound to the tool in
+ the session.
+ }
+ },
+ "tool": "str", # Optional. The canonical tool name.
+ "version": "str" # Optional. The tool version that ran.
+ }
+ ],
+ "success_count": 0, # Optional.
+ "total_count": 0 # Optional.
+ }
+ # response body for status code(s): 400, 402, 412, 413, 429, 500, 503
+ response == {
+ "call_id": "str", # A unique identifier for this request, when one was
+ assigned. Required.
+ "error": {
+ "class": "str", # Optional. The failure class. Branch on this value
+ rather than on ``message``"" , which may change. Known values are:
+ "invalid_argument", "unauthorized", "forbidden", "rate_limited", "not_found",
+ "timeout", "upstream_error", "output_too_large", "execution_failed",
+ "unavailable", "canceled", "render_required", "unsupported_media_type", and
+ "view_materialization_failed".
+ "message": "str", # Optional. A human-readable explanation that is
+ safe to show to an agent or end user.
+ "recovery_hint": "str", # Optional. The suggested next step. Known
+ values are: "fix_args", "refresh_auth", "retry_later", "narrow_output",
+ "contact_support", and "verify_provider_state".
+ "retriable": bool # Optional. Whether retrying the same request
+ later can succeed.
+ },
+ "status": "str" # Required. "failed"
+ }
+ # response body for status code(s): 401
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
}
"""
@overload
- async def create(
- self, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any
+ async def run(
+ self,
+ body: IO[bytes],
+ *,
+ x_session_id: str,
+ content_type: str = "application/json",
+ **kwargs: Any
) -> JSON:
# pylint: disable=line-too-long
- """Create a New SSH Key.
+ """Invoke Session Tools.
- To add a new SSH public key to your DigitalOcean account, send a POST request to
- ``/v2/account/keys``. Set the ``name`` attribute to the name you wish to use and the
- ``public_key`` attribute to the full public key you are adding.
+ Runs 1 to 10 tool calls in parallel and returns one result per call, in request order. This is
+ the REST form of the ``action_invoke`` MCP tool.
+
+ Each call is checked against the session's tool selection and policy, uses the session actor's
+ connections, and applies any output view bound to the tool in the session. A well-formed
+ request returns ``200`` even when some calls fail. Check each item's ``result.status``\\ , and
+ use ``success_count`` and ``error_count`` to branch without scanning every item.
+
+ A call whose policy requires approval fails with ``_meta.status`` set to ``requires_approval``.
+ Have the session's owner approve it, then repeat the call with the same arguments. A call that
+ needs the end user to connect a provider fails with ``_meta.status`` set to
+ ``requires_authorization`` or ``requires_connection_configuration``.
:param body: Required.
:type body: IO[bytes]
+ :keyword x_session_id: The session to act in: the UUID at the end of the session's
+ ``sessionUrn`` and ``mcpUrl``. The session must belong to the authenticated user and team.
+ Required.
+ :paramtype x_session_id: str
:keyword content_type: Body Parameter content-type. Content type parameter for binary body.
Default value is "application/json".
:paramtype content_type: str
@@ -11698,34 +12164,124 @@ async def create(
Example:
.. code-block:: python
- # response body for status code(s): 201
+ # response body for status code(s): 200
response == {
- "ssh_key": {
- "name": "str", # A human-readable display name for this key, used to
- easily identify the SSH keys when they are displayed. Required.
- "public_key": "str", # The entire public key string that was
- uploaded. Embedded into the root user's ``authorized_keys`` file if you
- include this key during Droplet creation. Required.
- "fingerprint": "str", # Optional. A unique identifier that
- differentiates this key from other keys using a format that SSH recognizes.
- The fingerprint is created when the key is added to your account.
- "id": 0 # Optional. A unique identification number for this key. Can
- be used to embed a specific SSH key into a Droplet.
- }
+ "error_count": 0, # Optional.
+ "results": [
+ {
+ "index": 0, # Optional. The 0-based position of the call in
+ the request.
+ "result": {
+ "call_id": "str", # A unique identifier for this
+ call. Include it when contacting support. Required.
+ "status": "str", # Required. Known values are:
+ "succeeded" and "failed".
+ "_meta": {
+ "str": {} # Optional. Additional result
+ metadata. Keys include: * ``status``"" :
+ ``requires_approval``"" , ``requires_authorization``"" , or
+ ``requires_connection_configuration`` when the call stopped
+ before running. * ``approval_id``"" , ``tool_name``"" ,
+ ``expires_at``"" , and ``decide``"" : present with
+ ``requires_approval``. ``decide`` gives the ``method``"" ,
+ ``path``"" , and ``body`` of the approval request to send.
+ Approve the call, then repeat it with the same arguments before
+ ``expires_at``. * `retry`: `{"attempt_count": N, "exhausted":
+ bool}` when the gateway retried the call. *
+ ``output_view``"" : the output view applied to the result.
+ },
+ "error": {
+ "class": "str", # Optional. The failure
+ class. Branch on this value rather than on ``message``"" , which
+ may change. Known values are: "invalid_argument", "unauthorized",
+ "forbidden", "rate_limited", "not_found", "timeout",
+ "upstream_error", "output_too_large", "execution_failed",
+ "unavailable", "canceled", "render_required",
+ "unsupported_media_type", and "view_materialization_failed".
+ "message": "str", # Optional. A
+ human-readable explanation that is safe to show to an agent or
+ end user.
+ "recovery_hint": "str", # Optional. The
+ suggested next step. Known values are: "fix_args",
+ "refresh_auth", "retry_later", "narrow_output",
+ "contact_support", and "verify_provider_state".
+ "retriable": bool # Optional. Whether
+ retrying the same request later can succeed.
+ },
+ "output": {
+ "str": {} # Optional. The tool's JSON
+ output. Present when ``status`` is ``succeeded``. Its shape is
+ the tool's output schema, or the output view bound to the tool in
+ the session.
+ }
+ },
+ "tool": "str", # Optional. The canonical tool name.
+ "version": "str" # Optional. The tool version that ran.
+ }
+ ],
+ "success_count": 0, # Optional.
+ "total_count": 0 # Optional.
+ }
+ # response body for status code(s): 400, 402, 412, 413, 429, 500, 503
+ response == {
+ "call_id": "str", # A unique identifier for this request, when one was
+ assigned. Required.
+ "error": {
+ "class": "str", # Optional. The failure class. Branch on this value
+ rather than on ``message``"" , which may change. Known values are:
+ "invalid_argument", "unauthorized", "forbidden", "rate_limited", "not_found",
+ "timeout", "upstream_error", "output_too_large", "execution_failed",
+ "unavailable", "canceled", "render_required", "unsupported_media_type", and
+ "view_materialization_failed".
+ "message": "str", # Optional. A human-readable explanation that is
+ safe to show to an agent or end user.
+ "recovery_hint": "str", # Optional. The suggested next step. Known
+ values are: "fix_args", "refresh_auth", "retry_later", "narrow_output",
+ "contact_support", and "verify_provider_state".
+ "retriable": bool # Optional. Whether retrying the same request
+ later can succeed.
+ },
+ "status": "str" # Required. "failed"
+ }
+ # response body for status code(s): 401
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
}
"""
@distributed_trace_async
- async def create(self, body: Union[JSON, IO[bytes]], **kwargs: Any) -> JSON:
+ async def run(
+ self, body: Union[JSON, IO[bytes]], *, x_session_id: str, **kwargs: Any
+ ) -> JSON:
# pylint: disable=line-too-long
- """Create a New SSH Key.
+ """Invoke Session Tools.
- To add a new SSH public key to your DigitalOcean account, send a POST request to
- ``/v2/account/keys``. Set the ``name`` attribute to the name you wish to use and the
- ``public_key`` attribute to the full public key you are adding.
+ Runs 1 to 10 tool calls in parallel and returns one result per call, in request order. This is
+ the REST form of the ``action_invoke`` MCP tool.
+
+ Each call is checked against the session's tool selection and policy, uses the session actor's
+ connections, and applies any output view bound to the tool in the session. A well-formed
+ request returns ``200`` even when some calls fail. Check each item's ``result.status``\\ , and
+ use ``success_count`` and ``error_count`` to branch without scanning every item.
+
+ A call whose policy requires approval fails with ``_meta.status`` set to ``requires_approval``.
+ Have the session's owner approve it, then repeat the call with the same arguments. A call that
+ needs the end user to connect a provider fails with ``_meta.status`` set to
+ ``requires_authorization`` or ``requires_connection_configuration``.
:param body: Is either a JSON type or a IO[bytes] type. Required.
:type body: JSON or IO[bytes]
+ :keyword x_session_id: The session to act in: the UUID at the end of the session's
+ ``sessionUrn`` and ``mcpUrl``. The session must belong to the authenticated user and team.
+ Required.
+ :paramtype x_session_id: str
:return: JSON object
:rtype: JSON
:raises ~azure.core.exceptions.HttpResponseError:
@@ -11735,44 +12291,118 @@ async def create(self, body: Union[JSON, IO[bytes]], **kwargs: Any) -> JSON:
# JSON input template you can fill out and use as your body input.
body = {
- "name": "str", # A human-readable display name for this key, used to easily
- identify the SSH keys when they are displayed. Required.
- "public_key": "str", # The entire public key string that was uploaded.
- Embedded into the root user's ``authorized_keys`` file if you include this key
- during Droplet creation. Required.
- "fingerprint": "str", # Optional. A unique identifier that differentiates
- this key from other keys using a format that SSH recognizes. The fingerprint is
- created when the key is added to your account.
- "id": 0 # Optional. A unique identification number for this key. Can be used
- to embed a specific SSH key into a Droplet.
+ "tools": [
+ {
+ "tool": "str", # The tool name, as returned by ``GET
+ /tools`` or ``POST /tools/search``. Names are case-insensitive. Required.
+ "arguments": {
+ "str": {} # Optional. The tool's arguments, matching
+ its ``inputSchema``.
+ },
+ "version": "str" # Optional. An immutable tool version. Omit
+ to use the released version.
+ }
+ ],
+ "rationale": "str" # Optional. One sentence explaining why the tools are
+ being called. Values longer than 512 characters are truncated.
}
- # response body for status code(s): 201
+ # response body for status code(s): 200
response == {
- "ssh_key": {
- "name": "str", # A human-readable display name for this key, used to
- easily identify the SSH keys when they are displayed. Required.
- "public_key": "str", # The entire public key string that was
- uploaded. Embedded into the root user's ``authorized_keys`` file if you
- include this key during Droplet creation. Required.
- "fingerprint": "str", # Optional. A unique identifier that
- differentiates this key from other keys using a format that SSH recognizes.
- The fingerprint is created when the key is added to your account.
- "id": 0 # Optional. A unique identification number for this key. Can
- be used to embed a specific SSH key into a Droplet.
- }
+ "error_count": 0, # Optional.
+ "results": [
+ {
+ "index": 0, # Optional. The 0-based position of the call in
+ the request.
+ "result": {
+ "call_id": "str", # A unique identifier for this
+ call. Include it when contacting support. Required.
+ "status": "str", # Required. Known values are:
+ "succeeded" and "failed".
+ "_meta": {
+ "str": {} # Optional. Additional result
+ metadata. Keys include: * ``status``"" :
+ ``requires_approval``"" , ``requires_authorization``"" , or
+ ``requires_connection_configuration`` when the call stopped
+ before running. * ``approval_id``"" , ``tool_name``"" ,
+ ``expires_at``"" , and ``decide``"" : present with
+ ``requires_approval``. ``decide`` gives the ``method``"" ,
+ ``path``"" , and ``body`` of the approval request to send.
+ Approve the call, then repeat it with the same arguments before
+ ``expires_at``. * `retry`: `{"attempt_count": N, "exhausted":
+ bool}` when the gateway retried the call. *
+ ``output_view``"" : the output view applied to the result.
+ },
+ "error": {
+ "class": "str", # Optional. The failure
+ class. Branch on this value rather than on ``message``"" , which
+ may change. Known values are: "invalid_argument", "unauthorized",
+ "forbidden", "rate_limited", "not_found", "timeout",
+ "upstream_error", "output_too_large", "execution_failed",
+ "unavailable", "canceled", "render_required",
+ "unsupported_media_type", and "view_materialization_failed".
+ "message": "str", # Optional. A
+ human-readable explanation that is safe to show to an agent or
+ end user.
+ "recovery_hint": "str", # Optional. The
+ suggested next step. Known values are: "fix_args",
+ "refresh_auth", "retry_later", "narrow_output",
+ "contact_support", and "verify_provider_state".
+ "retriable": bool # Optional. Whether
+ retrying the same request later can succeed.
+ },
+ "output": {
+ "str": {} # Optional. The tool's JSON
+ output. Present when ``status`` is ``succeeded``. Its shape is
+ the tool's output schema, or the output view bound to the tool in
+ the session.
+ }
+ },
+ "tool": "str", # Optional. The canonical tool name.
+ "version": "str" # Optional. The tool version that ran.
+ }
+ ],
+ "success_count": 0, # Optional.
+ "total_count": 0 # Optional.
+ }
+ # response body for status code(s): 400, 402, 412, 413, 429, 500, 503
+ response == {
+ "call_id": "str", # A unique identifier for this request, when one was
+ assigned. Required.
+ "error": {
+ "class": "str", # Optional. The failure class. Branch on this value
+ rather than on ``message``"" , which may change. Known values are:
+ "invalid_argument", "unauthorized", "forbidden", "rate_limited", "not_found",
+ "timeout", "upstream_error", "output_too_large", "execution_failed",
+ "unavailable", "canceled", "render_required", "unsupported_media_type", and
+ "view_materialization_failed".
+ "message": "str", # Optional. A human-readable explanation that is
+ safe to show to an agent or end user.
+ "recovery_hint": "str", # Optional. The suggested next step. Known
+ values are: "fix_args", "refresh_auth", "retry_later", "narrow_output",
+ "contact_support", and "verify_provider_state".
+ "retriable": bool # Optional. Whether retrying the same request
+ later can succeed.
+ },
+ "status": "str" # Required. "failed"
+ }
+ # response body for status code(s): 401
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
}
"""
error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 401: ClientAuthenticationError,
404: ResourceNotFoundError,
409: ResourceExistsError,
304: ResourceNotModifiedError,
- 401: cast(
- Type[HttpResponseError],
- lambda response: ClientAuthenticationError(response=response),
- ),
- 429: HttpResponseError,
- 500: HttpResponseError,
}
error_map.update(kwargs.pop("error_map", {}) or {})
@@ -11792,7 +12422,8 @@ async def create(self, body: Union[JSON, IO[bytes]], **kwargs: Any) -> JSON:
else:
_json = body
- _request = build_ssh_keys_create_request(
+ _request = build_gateway_tools_run_request(
+ x_session_id=x_session_id,
content_type=content_type,
json=_json,
content=_content,
@@ -11810,129 +12441,71 @@ async def create(self, body: Union[JSON, IO[bytes]], **kwargs: Any) -> JSON:
response = pipeline_response.http_response
- if response.status_code not in [201]:
+ if response.status_code not in [
+ 200,
+ 400,
+ 401,
+ 402,
+ 403,
+ 412,
+ 413,
+ 429,
+ 500,
+ 503,
+ ]:
if _stream:
await response.read() # Load the body in memory and close the socket
- map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ map_error(
+ status_code=response.status_code, response=response, error_map=error_map
+ )
raise HttpResponseError(response=response)
response_headers = {}
- response_headers["ratelimit-limit"] = self._deserialize(
- "int", response.headers.get("ratelimit-limit")
- )
- response_headers["ratelimit-remaining"] = self._deserialize(
- "int", response.headers.get("ratelimit-remaining")
- )
- response_headers["ratelimit-reset"] = self._deserialize(
- "int", response.headers.get("ratelimit-reset")
- )
-
- if response.content:
- deserialized = response.json()
- else:
- deserialized = None
-
- if cls:
- return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
-
- return cast(JSON, deserialized) # type: ignore
-
- @distributed_trace_async
- async def get(self, ssh_key_identifier: JSON, **kwargs: Any) -> JSON:
- # pylint: disable=line-too-long
- """Retrieve an Existing SSH Key.
-
- To get information about a key, send a GET request to ``/v2/account/keys/$KEY_ID`` or
- ``/v2/account/keys/$KEY_FINGERPRINT``.
- The response will be a JSON object with the key ``ssh_key`` and value an ssh_key object which
- contains the standard ssh_key attributes.
-
- :param ssh_key_identifier: Either the ID or the fingerprint of an existing SSH key. Required.
- :type ssh_key_identifier: JSON
- :return: JSON object
- :rtype: JSON
- :raises ~azure.core.exceptions.HttpResponseError:
-
- Example:
- .. code-block:: python
-
- # response body for status code(s): 200
- response == {
- "ssh_key": {
- "name": "str", # A human-readable display name for this key, used to
- easily identify the SSH keys when they are displayed. Required.
- "public_key": "str", # The entire public key string that was
- uploaded. Embedded into the root user's ``authorized_keys`` file if you
- include this key during Droplet creation. Required.
- "fingerprint": "str", # Optional. A unique identifier that
- differentiates this key from other keys using a format that SSH recognizes.
- The fingerprint is created when the key is added to your account.
- "id": 0 # Optional. A unique identification number for this key. Can
- be used to embed a specific SSH key into a Droplet.
- }
- }
- # response body for status code(s): 404
- response == {
- "id": "str", # A short identifier corresponding to the HTTP status code
- returned. For example, the ID for a response returning a 404 status code would
- be "not_found.". Required.
- "message": "str", # A message providing additional information about the
- error, including details to help resolve it when possible. Required.
- "request_id": "str" # Optional. Optionally, some endpoints may include a
- request ID that should be provided when reporting bugs or opening support
- tickets to help identify the issue.
- }
- """
- error_map: MutableMapping[int, Type[HttpResponseError]] = {
- 404: ResourceNotFoundError,
- 409: ResourceExistsError,
- 304: ResourceNotModifiedError,
- 401: cast(
- Type[HttpResponseError],
- lambda response: ClientAuthenticationError(response=response),
- ),
- 429: HttpResponseError,
- 500: HttpResponseError,
- }
- error_map.update(kwargs.pop("error_map", {}) or {})
+ if response.status_code == 200:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
- _headers = kwargs.pop("headers", {}) or {}
- _params = kwargs.pop("params", {}) or {}
+ if response.status_code == 400:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
- cls: ClsType[JSON] = kwargs.pop("cls", None)
+ if response.status_code == 401:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
- _request = build_ssh_keys_get_request(
- ssh_key_identifier=ssh_key_identifier,
- headers=_headers,
- params=_params,
- )
- _request.url = self._client.format_url(_request.url)
+ if response.status_code == 402:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
- _stream = False
- pipeline_response: PipelineResponse = (
- await self._client._pipeline.run( # pylint: disable=protected-access
- _request, stream=_stream, **kwargs
- )
- )
+ if response.status_code == 403:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
- response = pipeline_response.http_response
+ if response.status_code == 412:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
- if response.status_code not in [200, 404]:
- if _stream:
- await response.read() # Load the body in memory and close the socket
- map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
- raise HttpResponseError(response=response)
+ if response.status_code == 413:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
- response_headers = {}
- if response.status_code == 200:
- response_headers["ratelimit-limit"] = self._deserialize(
- "int", response.headers.get("ratelimit-limit")
- )
- response_headers["ratelimit-remaining"] = self._deserialize(
- "int", response.headers.get("ratelimit-remaining")
- )
- response_headers["ratelimit-reset"] = self._deserialize(
- "int", response.headers.get("ratelimit-reset")
+ if response.status_code == 429:
+ response_headers["Retry-After"] = self._deserialize(
+ "int", response.headers.get("Retry-After")
)
if response.content:
@@ -11940,17 +12513,13 @@ async def get(self, ssh_key_identifier: JSON, **kwargs: Any) -> JSON:
else:
deserialized = None
- if response.status_code == 404:
- response_headers["ratelimit-limit"] = self._deserialize(
- "int", response.headers.get("ratelimit-limit")
- )
- response_headers["ratelimit-remaining"] = self._deserialize(
- "int", response.headers.get("ratelimit-remaining")
- )
- response_headers["ratelimit-reset"] = self._deserialize(
- "int", response.headers.get("ratelimit-reset")
- )
+ if response.status_code == 500:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+ if response.status_code == 503:
if response.content:
deserialized = response.json()
else:
@@ -11961,26 +12530,57 @@ async def get(self, ssh_key_identifier: JSON, **kwargs: Any) -> JSON:
return cast(JSON, deserialized) # type: ignore
+
+class GatewayCodeOperations:
+ """
+ .. warning::
+ **DO NOT** instantiate this class directly.
+
+ Instead, you should access the following operations through
+ :class:`~pydo.aio.GeneratedClient`'s
+ :attr:`gateway_code` attribute.
+ """
+
+ def __init__(self, *args, **kwargs) -> None:
+ input_args = list(args)
+ self._client = input_args.pop(0) if input_args else kwargs.pop("client")
+ self._config = input_args.pop(0) if input_args else kwargs.pop("config")
+ self._serialize = input_args.pop(0) if input_args else kwargs.pop("serializer")
+ self._deserialize = (
+ input_args.pop(0) if input_args else kwargs.pop("deserializer")
+ )
+
@overload
- async def update(
+ async def run(
self,
- ssh_key_identifier: JSON,
body: JSON,
*,
+ x_session_id: str,
content_type: str = "application/json",
**kwargs: Any
) -> JSON:
# pylint: disable=line-too-long
- """Update an SSH Key's Name.
+ """Execute Code.
- To update the name of an SSH key, send a PUT request to either ``/v2/account/keys/$SSH_KEY_ID``
- or ``/v2/account/keys/$SSH_KEY_FINGERPRINT``. Set the ``name`` attribute to the new name you
- want to use.
+ Runs Python code in an ephemeral sandbox and returns its ``stdout``\\ , ``stderr``\\ , and
+ ``exit_code``. This is the REST form of the ``action_code`` MCP tool. Use it for computation,
+ parsing, and data processing, or to chain several catalog tools in one request.
- :param ssh_key_identifier: Either the ID or the fingerprint of an existing SSH key. Required.
- :type ssh_key_identifier: JSON
- :param body: Set the ``name`` attribute to the new name you want to use. Required.
+ The sandbox provides ``invoke_digitalocean_tool(name, arguments)``\\ , which calls a catalog
+ tool and returns a tool result. Those calls follow the session's tool selection and policy.
+ Each request runs in a fresh sandbox, so state is not kept between requests. Execution,
+ including tool calls, is time limited. Code that runs too long fails with a ``timeout`` error.
+
+ A nonzero exit code is still a ``succeeded`` result; check ``output.exit_code``. If the session
+ policy requires approval for ``action_code``\\ , the response is a failed result with
+ ``_meta.status`` set to ``requires_approval``.
+
+ :param body: Required.
:type body: JSON
+ :keyword x_session_id: The session to act in: the UUID at the end of the session's
+ ``sessionUrn`` and ``mcpUrl``. The session must belong to the authenticated user and team.
+ Required.
+ :paramtype x_session_id: str
:keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
Default value is "application/json".
:paramtype content_type: str
@@ -11993,26 +12593,72 @@ async def update(
# JSON input template you can fill out and use as your body input.
body = {
- "name": "str" # Optional. A human-readable display name for this key, used
- to easily identify the SSH keys when they are displayed.
+ "code": "str" # Python source to run. The sandbox provides
+ ``invoke_digitalocean_tool(name: str, arguments: dict) -> dict``"" , which calls
+ a catalog tool under the session's policy and returns a tool result. Required.
}
# response body for status code(s): 200
response == {
- "ssh_key": {
- "name": "str", # A human-readable display name for this key, used to
- easily identify the SSH keys when they are displayed. Required.
- "public_key": "str", # The entire public key string that was
- uploaded. Embedded into the root user's ``authorized_keys`` file if you
- include this key during Droplet creation. Required.
- "fingerprint": "str", # Optional. A unique identifier that
- differentiates this key from other keys using a format that SSH recognizes.
- The fingerprint is created when the key is added to your account.
- "id": 0 # Optional. A unique identification number for this key. Can
- be used to embed a specific SSH key into a Droplet.
+ "call_id": "str", # A unique identifier for this call. Include it when
+ contacting support. Required.
+ "status": "str", # Required. Known values are: "succeeded" and "failed".
+ "_meta": {
+ "str": {} # Optional. Additional result metadata. Keys include: *
+ ``status``"" : ``requires_approval``"" , ``requires_authorization``"" , or
+ ``requires_connection_configuration`` when the call stopped before running.
+ * ``approval_id``"" , ``tool_name``"" , ``expires_at``"" , and
+ ``decide``"" : present with ``requires_approval``. ``decide`` gives the
+ ``method``"" , ``path``"" , and ``body`` of the approval request to send.
+ Approve the call, then repeat it with the same arguments before
+ ``expires_at``. * `retry`: `{"attempt_count": N, "exhausted": bool}` when
+ the gateway retried the call. * ``output_view``"" : the output view
+ applied to the result.
+ },
+ "error": {
+ "class": "str", # Optional. The failure class. Branch on this value
+ rather than on ``message``"" , which may change. Known values are:
+ "invalid_argument", "unauthorized", "forbidden", "rate_limited", "not_found",
+ "timeout", "upstream_error", "output_too_large", "execution_failed",
+ "unavailable", "canceled", "render_required", "unsupported_media_type", and
+ "view_materialization_failed".
+ "message": "str", # Optional. A human-readable explanation that is
+ safe to show to an agent or end user.
+ "recovery_hint": "str", # Optional. The suggested next step. Known
+ values are: "fix_args", "refresh_auth", "retry_later", "narrow_output",
+ "contact_support", and "verify_provider_state".
+ "retriable": bool # Optional. Whether retrying the same request
+ later can succeed.
+ },
+ "output": {
+ "exit_code": 0, # Optional. The process exit code. A nonzero exit
+ code is still a succeeded result.
+ "stderr": "str", # Optional. Omitted when empty.
+ "stdout": "str" # Optional.
}
}
- # response body for status code(s): 404
+ # response body for status code(s): 400, 412, 413, 429, 500, 503, 504
+ response == {
+ "call_id": "str", # A unique identifier for this request, when one was
+ assigned. Required.
+ "error": {
+ "class": "str", # Optional. The failure class. Branch on this value
+ rather than on ``message``"" , which may change. Known values are:
+ "invalid_argument", "unauthorized", "forbidden", "rate_limited", "not_found",
+ "timeout", "upstream_error", "output_too_large", "execution_failed",
+ "unavailable", "canceled", "render_required", "unsupported_media_type", and
+ "view_materialization_failed".
+ "message": "str", # Optional. A human-readable explanation that is
+ safe to show to an agent or end user.
+ "recovery_hint": "str", # Optional. The suggested next step. Known
+ values are: "fix_args", "refresh_auth", "retry_later", "narrow_output",
+ "contact_support", and "verify_provider_state".
+ "retriable": bool # Optional. Whether retrying the same request
+ later can succeed.
+ },
+ "status": "str" # Required. "failed"
+ }
+ # response body for status code(s): 401
response == {
"id": "str", # A short identifier corresponding to the HTTP status code
returned. For example, the ID for a response returning a 404 status code would
@@ -12026,25 +12672,36 @@ async def update(
"""
@overload
- async def update(
+ async def run(
self,
- ssh_key_identifier: JSON,
body: IO[bytes],
*,
+ x_session_id: str,
content_type: str = "application/json",
**kwargs: Any
) -> JSON:
# pylint: disable=line-too-long
- """Update an SSH Key's Name.
+ """Execute Code.
- To update the name of an SSH key, send a PUT request to either ``/v2/account/keys/$SSH_KEY_ID``
- or ``/v2/account/keys/$SSH_KEY_FINGERPRINT``. Set the ``name`` attribute to the new name you
- want to use.
+ Runs Python code in an ephemeral sandbox and returns its ``stdout``\\ , ``stderr``\\ , and
+ ``exit_code``. This is the REST form of the ``action_code`` MCP tool. Use it for computation,
+ parsing, and data processing, or to chain several catalog tools in one request.
- :param ssh_key_identifier: Either the ID or the fingerprint of an existing SSH key. Required.
- :type ssh_key_identifier: JSON
- :param body: Set the ``name`` attribute to the new name you want to use. Required.
+ The sandbox provides ``invoke_digitalocean_tool(name, arguments)``\\ , which calls a catalog
+ tool and returns a tool result. Those calls follow the session's tool selection and policy.
+ Each request runs in a fresh sandbox, so state is not kept between requests. Execution,
+ including tool calls, is time limited. Code that runs too long fails with a ``timeout`` error.
+
+ A nonzero exit code is still a ``succeeded`` result; check ``output.exit_code``. If the session
+ policy requires approval for ``action_code``\\ , the response is a failed result with
+ ``_meta.status`` set to ``requires_approval``.
+
+ :param body: Required.
:type body: IO[bytes]
+ :keyword x_session_id: The session to act in: the UUID at the end of the session's
+ ``sessionUrn`` and ``mcpUrl``. The session must belong to the authenticated user and team.
+ Required.
+ :paramtype x_session_id: str
:keyword content_type: Body Parameter content-type. Content type parameter for binary body.
Default value is "application/json".
:paramtype content_type: str
@@ -12057,20 +12714,65 @@ async def update(
# response body for status code(s): 200
response == {
- "ssh_key": {
- "name": "str", # A human-readable display name for this key, used to
- easily identify the SSH keys when they are displayed. Required.
- "public_key": "str", # The entire public key string that was
- uploaded. Embedded into the root user's ``authorized_keys`` file if you
- include this key during Droplet creation. Required.
- "fingerprint": "str", # Optional. A unique identifier that
- differentiates this key from other keys using a format that SSH recognizes.
- The fingerprint is created when the key is added to your account.
- "id": 0 # Optional. A unique identification number for this key. Can
- be used to embed a specific SSH key into a Droplet.
+ "call_id": "str", # A unique identifier for this call. Include it when
+ contacting support. Required.
+ "status": "str", # Required. Known values are: "succeeded" and "failed".
+ "_meta": {
+ "str": {} # Optional. Additional result metadata. Keys include: *
+ ``status``"" : ``requires_approval``"" , ``requires_authorization``"" , or
+ ``requires_connection_configuration`` when the call stopped before running.
+ * ``approval_id``"" , ``tool_name``"" , ``expires_at``"" , and
+ ``decide``"" : present with ``requires_approval``. ``decide`` gives the
+ ``method``"" , ``path``"" , and ``body`` of the approval request to send.
+ Approve the call, then repeat it with the same arguments before
+ ``expires_at``. * `retry`: `{"attempt_count": N, "exhausted": bool}` when
+ the gateway retried the call. * ``output_view``"" : the output view
+ applied to the result.
+ },
+ "error": {
+ "class": "str", # Optional. The failure class. Branch on this value
+ rather than on ``message``"" , which may change. Known values are:
+ "invalid_argument", "unauthorized", "forbidden", "rate_limited", "not_found",
+ "timeout", "upstream_error", "output_too_large", "execution_failed",
+ "unavailable", "canceled", "render_required", "unsupported_media_type", and
+ "view_materialization_failed".
+ "message": "str", # Optional. A human-readable explanation that is
+ safe to show to an agent or end user.
+ "recovery_hint": "str", # Optional. The suggested next step. Known
+ values are: "fix_args", "refresh_auth", "retry_later", "narrow_output",
+ "contact_support", and "verify_provider_state".
+ "retriable": bool # Optional. Whether retrying the same request
+ later can succeed.
+ },
+ "output": {
+ "exit_code": 0, # Optional. The process exit code. A nonzero exit
+ code is still a succeeded result.
+ "stderr": "str", # Optional. Omitted when empty.
+ "stdout": "str" # Optional.
}
}
- # response body for status code(s): 404
+ # response body for status code(s): 400, 412, 413, 429, 500, 503, 504
+ response == {
+ "call_id": "str", # A unique identifier for this request, when one was
+ assigned. Required.
+ "error": {
+ "class": "str", # Optional. The failure class. Branch on this value
+ rather than on ``message``"" , which may change. Known values are:
+ "invalid_argument", "unauthorized", "forbidden", "rate_limited", "not_found",
+ "timeout", "upstream_error", "output_too_large", "execution_failed",
+ "unavailable", "canceled", "render_required", "unsupported_media_type", and
+ "view_materialization_failed".
+ "message": "str", # Optional. A human-readable explanation that is
+ safe to show to an agent or end user.
+ "recovery_hint": "str", # Optional. The suggested next step. Known
+ values are: "fix_args", "refresh_auth", "retry_later", "narrow_output",
+ "contact_support", and "verify_provider_state".
+ "retriable": bool # Optional. Whether retrying the same request
+ later can succeed.
+ },
+ "status": "str" # Required. "failed"
+ }
+ # response body for status code(s): 401
response == {
"id": "str", # A short identifier corresponding to the HTTP status code
returned. For example, the ID for a response returning a 404 status code would
@@ -12084,21 +12786,31 @@ async def update(
"""
@distributed_trace_async
- async def update(
- self, ssh_key_identifier: JSON, body: Union[JSON, IO[bytes]], **kwargs: Any
+ async def run(
+ self, body: Union[JSON, IO[bytes]], *, x_session_id: str, **kwargs: Any
) -> JSON:
# pylint: disable=line-too-long
- """Update an SSH Key's Name.
+ """Execute Code.
- To update the name of an SSH key, send a PUT request to either ``/v2/account/keys/$SSH_KEY_ID``
- or ``/v2/account/keys/$SSH_KEY_FINGERPRINT``. Set the ``name`` attribute to the new name you
- want to use.
+ Runs Python code in an ephemeral sandbox and returns its ``stdout``\\ , ``stderr``\\ , and
+ ``exit_code``. This is the REST form of the ``action_code`` MCP tool. Use it for computation,
+ parsing, and data processing, or to chain several catalog tools in one request.
- :param ssh_key_identifier: Either the ID or the fingerprint of an existing SSH key. Required.
- :type ssh_key_identifier: JSON
- :param body: Set the ``name`` attribute to the new name you want to use. Is either a JSON type
- or a IO[bytes] type. Required.
+ The sandbox provides ``invoke_digitalocean_tool(name, arguments)``\\ , which calls a catalog
+ tool and returns a tool result. Those calls follow the session's tool selection and policy.
+ Each request runs in a fresh sandbox, so state is not kept between requests. Execution,
+ including tool calls, is time limited. Code that runs too long fails with a ``timeout`` error.
+
+ A nonzero exit code is still a ``succeeded`` result; check ``output.exit_code``. If the session
+ policy requires approval for ``action_code``\\ , the response is a failed result with
+ ``_meta.status`` set to ``requires_approval``.
+
+ :param body: Is either a JSON type or a IO[bytes] type. Required.
:type body: JSON or IO[bytes]
+ :keyword x_session_id: The session to act in: the UUID at the end of the session's
+ ``sessionUrn`` and ``mcpUrl``. The session must belong to the authenticated user and team.
+ Required.
+ :paramtype x_session_id: str
:return: JSON object
:rtype: JSON
:raises ~azure.core.exceptions.HttpResponseError:
@@ -12108,26 +12820,72 @@ async def update(
# JSON input template you can fill out and use as your body input.
body = {
- "name": "str" # Optional. A human-readable display name for this key, used
- to easily identify the SSH keys when they are displayed.
+ "code": "str" # Python source to run. The sandbox provides
+ ``invoke_digitalocean_tool(name: str, arguments: dict) -> dict``"" , which calls
+ a catalog tool under the session's policy and returns a tool result. Required.
}
# response body for status code(s): 200
response == {
- "ssh_key": {
- "name": "str", # A human-readable display name for this key, used to
- easily identify the SSH keys when they are displayed. Required.
- "public_key": "str", # The entire public key string that was
- uploaded. Embedded into the root user's ``authorized_keys`` file if you
- include this key during Droplet creation. Required.
- "fingerprint": "str", # Optional. A unique identifier that
- differentiates this key from other keys using a format that SSH recognizes.
- The fingerprint is created when the key is added to your account.
- "id": 0 # Optional. A unique identification number for this key. Can
- be used to embed a specific SSH key into a Droplet.
+ "call_id": "str", # A unique identifier for this call. Include it when
+ contacting support. Required.
+ "status": "str", # Required. Known values are: "succeeded" and "failed".
+ "_meta": {
+ "str": {} # Optional. Additional result metadata. Keys include: *
+ ``status``"" : ``requires_approval``"" , ``requires_authorization``"" , or
+ ``requires_connection_configuration`` when the call stopped before running.
+ * ``approval_id``"" , ``tool_name``"" , ``expires_at``"" , and
+ ``decide``"" : present with ``requires_approval``. ``decide`` gives the
+ ``method``"" , ``path``"" , and ``body`` of the approval request to send.
+ Approve the call, then repeat it with the same arguments before
+ ``expires_at``. * `retry`: `{"attempt_count": N, "exhausted": bool}` when
+ the gateway retried the call. * ``output_view``"" : the output view
+ applied to the result.
+ },
+ "error": {
+ "class": "str", # Optional. The failure class. Branch on this value
+ rather than on ``message``"" , which may change. Known values are:
+ "invalid_argument", "unauthorized", "forbidden", "rate_limited", "not_found",
+ "timeout", "upstream_error", "output_too_large", "execution_failed",
+ "unavailable", "canceled", "render_required", "unsupported_media_type", and
+ "view_materialization_failed".
+ "message": "str", # Optional. A human-readable explanation that is
+ safe to show to an agent or end user.
+ "recovery_hint": "str", # Optional. The suggested next step. Known
+ values are: "fix_args", "refresh_auth", "retry_later", "narrow_output",
+ "contact_support", and "verify_provider_state".
+ "retriable": bool # Optional. Whether retrying the same request
+ later can succeed.
+ },
+ "output": {
+ "exit_code": 0, # Optional. The process exit code. A nonzero exit
+ code is still a succeeded result.
+ "stderr": "str", # Optional. Omitted when empty.
+ "stdout": "str" # Optional.
}
}
- # response body for status code(s): 404
+ # response body for status code(s): 400, 412, 413, 429, 500, 503, 504
+ response == {
+ "call_id": "str", # A unique identifier for this request, when one was
+ assigned. Required.
+ "error": {
+ "class": "str", # Optional. The failure class. Branch on this value
+ rather than on ``message``"" , which may change. Known values are:
+ "invalid_argument", "unauthorized", "forbidden", "rate_limited", "not_found",
+ "timeout", "upstream_error", "output_too_large", "execution_failed",
+ "unavailable", "canceled", "render_required", "unsupported_media_type", and
+ "view_materialization_failed".
+ "message": "str", # Optional. A human-readable explanation that is
+ safe to show to an agent or end user.
+ "recovery_hint": "str", # Optional. The suggested next step. Known
+ values are: "fix_args", "refresh_auth", "retry_later", "narrow_output",
+ "contact_support", and "verify_provider_state".
+ "retriable": bool # Optional. Whether retrying the same request
+ later can succeed.
+ },
+ "status": "str" # Required. "failed"
+ }
+ # response body for status code(s): 401
response == {
"id": "str", # A short identifier corresponding to the HTTP status code
returned. For example, the ID for a response returning a 404 status code would
@@ -12140,15 +12898,10 @@ async def update(
}
"""
error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 401: ClientAuthenticationError,
404: ResourceNotFoundError,
409: ResourceExistsError,
304: ResourceNotModifiedError,
- 401: cast(
- Type[HttpResponseError],
- lambda response: ClientAuthenticationError(response=response),
- ),
- 429: HttpResponseError,
- 500: HttpResponseError,
}
error_map.update(kwargs.pop("error_map", {}) or {})
@@ -12168,8 +12921,8 @@ async def update(
else:
_json = body
- _request = build_ssh_keys_update_request(
- ssh_key_identifier=ssh_key_identifier,
+ _request = build_gateway_code_run_request(
+ x_session_id=x_session_id,
content_type=content_type,
json=_json,
content=_content,
@@ -12187,164 +12940,104 @@ async def update(
response = pipeline_response.http_response
- if response.status_code not in [200, 404]:
+ if response.status_code not in [
+ 200,
+ 400,
+ 401,
+ 403,
+ 412,
+ 413,
+ 429,
+ 500,
+ 503,
+ 504,
+ ]:
if _stream:
await response.read() # Load the body in memory and close the socket
- map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ map_error(
+ status_code=response.status_code, response=response, error_map=error_map
+ )
raise HttpResponseError(response=response)
response_headers = {}
if response.status_code == 200:
- response_headers["ratelimit-limit"] = self._deserialize(
- "int", response.headers.get("ratelimit-limit")
- )
- response_headers["ratelimit-remaining"] = self._deserialize(
- "int", response.headers.get("ratelimit-remaining")
- )
- response_headers["ratelimit-reset"] = self._deserialize(
- "int", response.headers.get("ratelimit-reset")
- )
-
if response.content:
deserialized = response.json()
else:
deserialized = None
- if response.status_code == 404:
- response_headers["ratelimit-limit"] = self._deserialize(
- "int", response.headers.get("ratelimit-limit")
- )
- response_headers["ratelimit-remaining"] = self._deserialize(
- "int", response.headers.get("ratelimit-remaining")
- )
- response_headers["ratelimit-reset"] = self._deserialize(
- "int", response.headers.get("ratelimit-reset")
- )
-
+ if response.status_code == 400:
if response.content:
deserialized = response.json()
else:
deserialized = None
- if cls:
- return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
-
- return cast(JSON, deserialized) # type: ignore
-
- @distributed_trace_async
- async def delete(self, ssh_key_identifier: JSON, **kwargs: Any) -> Optional[JSON]:
- # pylint: disable=line-too-long
- """Delete an SSH Key.
-
- To destroy a public SSH key that you have in your account, send a DELETE request to
- ``/v2/account/keys/$KEY_ID`` or ``/v2/account/keys/$KEY_FINGERPRINT``.
- A 204 status will be returned, indicating that the action was successful and that the response
- body is empty.
-
- :param ssh_key_identifier: Either the ID or the fingerprint of an existing SSH key. Required.
- :type ssh_key_identifier: JSON
- :return: JSON object or None
- :rtype: JSON or None
- :raises ~azure.core.exceptions.HttpResponseError:
-
- Example:
- .. code-block:: python
-
- # response body for status code(s): 404
- response == {
- "id": "str", # A short identifier corresponding to the HTTP status code
- returned. For example, the ID for a response returning a 404 status code would
- be "not_found.". Required.
- "message": "str", # A message providing additional information about the
- error, including details to help resolve it when possible. Required.
- "request_id": "str" # Optional. Optionally, some endpoints may include a
- request ID that should be provided when reporting bugs or opening support
- tickets to help identify the issue.
- }
- """
- error_map: MutableMapping[int, Type[HttpResponseError]] = {
- 404: ResourceNotFoundError,
- 409: ResourceExistsError,
- 304: ResourceNotModifiedError,
- 401: cast(
- Type[HttpResponseError],
- lambda response: ClientAuthenticationError(response=response),
- ),
- 429: HttpResponseError,
- 500: HttpResponseError,
- }
- error_map.update(kwargs.pop("error_map", {}) or {})
+ if response.status_code == 401:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
- _headers = kwargs.pop("headers", {}) or {}
- _params = kwargs.pop("params", {}) or {}
+ if response.status_code == 403:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
- cls: ClsType[Optional[JSON]] = kwargs.pop("cls", None)
+ if response.status_code == 412:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
- _request = build_ssh_keys_delete_request(
- ssh_key_identifier=ssh_key_identifier,
- headers=_headers,
- params=_params,
- )
- _request.url = self._client.format_url(_request.url)
+ if response.status_code == 413:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
- _stream = False
- pipeline_response: PipelineResponse = (
- await self._client._pipeline.run( # pylint: disable=protected-access
- _request, stream=_stream, **kwargs
+ if response.status_code == 429:
+ response_headers["Retry-After"] = self._deserialize(
+ "int", response.headers.get("Retry-After")
)
- )
-
- response = pipeline_response.http_response
- if response.status_code not in [204, 404]:
- if _stream:
- await response.read() # Load the body in memory and close the socket
- map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
- raise HttpResponseError(response=response)
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
- deserialized = None
- response_headers = {}
- if response.status_code == 204:
- response_headers["ratelimit-limit"] = self._deserialize(
- "int", response.headers.get("ratelimit-limit")
- )
- response_headers["ratelimit-remaining"] = self._deserialize(
- "int", response.headers.get("ratelimit-remaining")
- )
- response_headers["ratelimit-reset"] = self._deserialize(
- "int", response.headers.get("ratelimit-reset")
- )
+ if response.status_code == 500:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
- if response.status_code == 404:
- response_headers["ratelimit-limit"] = self._deserialize(
- "int", response.headers.get("ratelimit-limit")
- )
- response_headers["ratelimit-remaining"] = self._deserialize(
- "int", response.headers.get("ratelimit-remaining")
- )
- response_headers["ratelimit-reset"] = self._deserialize(
- "int", response.headers.get("ratelimit-reset")
- )
+ if response.status_code == 503:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+ if response.status_code == 504:
if response.content:
deserialized = response.json()
else:
deserialized = None
if cls:
- return cls(pipeline_response, deserialized, response_headers) # type: ignore
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
- return deserialized # type: ignore
+ return cast(JSON, deserialized) # type: ignore
-class ActionsOperations:
+class GatewaySessionApprovalsOperations:
"""
.. warning::
**DO NOT** instantiate this class directly.
Instead, you should access the following operations through
:class:`~pydo.aio.GeneratedClient`'s
- :attr:`actions` attribute.
+ :attr:`gateway_session_approvals` attribute.
"""
def __init__(self, *args, **kwargs) -> None:
@@ -12356,19 +13049,40 @@ def __init__(self, *args, **kwargs) -> None:
input_args.pop(0) if input_args else kwargs.pop("deserializer")
)
- @distributed_trace_async
- async def list(self, *, per_page: int = 20, page: int = 1, **kwargs: Any) -> JSON:
+ @overload
+ async def update(
+ self,
+ session_id: str,
+ approval_id: str,
+ body: JSON,
+ *,
+ content_type: str = "application/json",
+ **kwargs: Any
+ ) -> JSON:
# pylint: disable=line-too-long
- """List All Actions.
+ """Decide a Pending Approval.
- This will be the entire list of actions taken on your account, so it will be quite large. As
- with any large collection returned by the API, the results will be paginated with only 20 on
- each page by default.
+ Approves or denies a tool call that is waiting for approval. A tool result returns
+ ``_meta.status`` set to ``requires_approval`` when the session policy sets ``ask`` for the
+ call, and its ``_meta.decide`` gives this request's path.
- :keyword per_page: Number of items returned per page. Default value is 20.
- :paramtype per_page: int
- :keyword page: Which 'page' of paginated results to return. Default value is 1.
- :paramtype page: int
+ Send the decision with the session owner's token. Approval is a separate control request, not a
+ tool, so an agent cannot approve its own calls. After approving, repeat the original call with
+ the same arguments before ``expires_at``. An approval applies only to that session, tool
+ version, and set of arguments, and is used once. To ask again after a denial or expiry, repeat
+ the tool call.
+
+ :param session_id: The session UUID: the value at the end of the session's ``sessionUrn`` and
+ ``mcpUrl``. The session must belong to the authenticated user and team. Required.
+ :type session_id: str
+ :param approval_id: The ``approval_id`` from a tool result whose ``_meta.status`` is
+ ``requires_approval``. Required.
+ :type approval_id: str
+ :param body: Required.
+ :type body: JSON
+ :keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
+ Default value is "application/json".
+ :paramtype content_type: str
:return: JSON object
:rtype: JSON
:raises ~azure.core.exceptions.HttpResponseError:
@@ -12376,132 +13090,164 @@ async def list(self, *, per_page: int = 20, page: int = 1, **kwargs: Any) -> JSO
Example:
.. code-block:: python
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "decision": "str" # Whether to let the pending call run. Required. Known
+ values are: "approve" and "deny".
+ }
+
# response body for status code(s): 200
response == {
- "meta": {
- "total": 0 # Optional. Number of objects returned by the request.
+ "expires_at": "2020-02-20 00:00:00", # Optional. Repeat an approved call
+ with the same arguments before this time.
+ "id": "str", # Optional. The approval ID.
+ "status": "str" # Optional. Known values are: "approved" and "denied".
+ }
+ # response body for status code(s): 400, 404, 409, 412, 429, 500, 503
+ response == {
+ "call_id": "str", # A unique identifier for this request, when one was
+ assigned. Required.
+ "error": {
+ "class": "str", # Optional. The failure class. Branch on this value
+ rather than on ``message``"" , which may change. Known values are:
+ "invalid_argument", "unauthorized", "forbidden", "rate_limited", "not_found",
+ "timeout", "upstream_error", "output_too_large", "execution_failed",
+ "unavailable", "canceled", "render_required", "unsupported_media_type", and
+ "view_materialization_failed".
+ "message": "str", # Optional. A human-readable explanation that is
+ safe to show to an agent or end user.
+ "recovery_hint": "str", # Optional. The suggested next step. Known
+ values are: "fix_args", "refresh_auth", "retry_later", "narrow_output",
+ "contact_support", and "verify_provider_state".
+ "retriable": bool # Optional. Whether retrying the same request
+ later can succeed.
},
- "actions": [
- {
- "completed_at": "2020-02-20 00:00:00", # Optional. A time
- value given in ISO8601 combined date and time format that represents when
- the action was completed.
- "id": 0, # Optional. A unique numeric ID that can be used to
- identify and reference an action.
- "region": {
- "available": bool, # This is a boolean value that
- represents whether new Droplets can be created in this region.
- Required.
- "features": [
- "str" # This attribute is set to an array
- which contains features available in this region. Required.
- ],
- "name": "str", # The display name of the region.
- This will be a full name that is used in the control panel and other
- interfaces. Required.
- "sizes": [
- "str" # This attribute is set to an array
- which contains the identifying slugs for the sizes available in
- this region. sizes:read is required to view. Required.
- ],
- "slug": "str" # A human-readable string that is used
- as a unique identifier for each region. Required.
- },
- "region_slug": "str", # Optional. A human-readable string
- that is used as a unique identifier for each region.
- "resource_id": 0, # Optional. A unique identifier for the
- resource that the action is associated with.
- "resource_type": "str", # Optional. The type of resource
- that the action is associated with.
- "started_at": "2020-02-20 00:00:00", # Optional. A time
- value given in ISO8601 combined date and time format that represents when
- the action was initiated.
- "status": "in-progress", # Optional. Default value is
- "in-progress". The current status of the action. This can be
- "in-progress", "completed", or "errored". Known values are:
- "in-progress", "completed", and "errored".
- "type": "str" # Optional. This is the type of action that
- the object represents. For example, this could be "transfer" to represent
- the state of an image transfer action.
- }
- ],
- "links": {
- "pages": {}
- }
+ "status": "str" # Required. "failed"
+ }
+ # response body for status code(s): 401
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
}
"""
- error_map: MutableMapping[int, Type[HttpResponseError]] = {
- 404: ResourceNotFoundError,
- 409: ResourceExistsError,
- 304: ResourceNotModifiedError,
- 401: cast(
- Type[HttpResponseError],
- lambda response: ClientAuthenticationError(response=response),
- ),
- 429: HttpResponseError,
- 500: HttpResponseError,
- }
- error_map.update(kwargs.pop("error_map", {}) or {})
-
- _headers = kwargs.pop("headers", {}) or {}
- _params = kwargs.pop("params", {}) or {}
-
- cls: ClsType[JSON] = kwargs.pop("cls", None)
-
- _request = build_actions_list_request(
- per_page=per_page,
- page=page,
- headers=_headers,
- params=_params,
- )
- _request.url = self._client.format_url(_request.url)
-
- _stream = False
- pipeline_response: PipelineResponse = (
- await self._client._pipeline.run( # pylint: disable=protected-access
- _request, stream=_stream, **kwargs
- )
- )
- response = pipeline_response.http_response
+ @overload
+ async def update(
+ self,
+ session_id: str,
+ approval_id: str,
+ body: IO[bytes],
+ *,
+ content_type: str = "application/json",
+ **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """Decide a Pending Approval.
- if response.status_code not in [200]:
- if _stream:
- await response.read() # Load the body in memory and close the socket
- map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
- raise HttpResponseError(response=response)
+ Approves or denies a tool call that is waiting for approval. A tool result returns
+ ``_meta.status`` set to ``requires_approval`` when the session policy sets ``ask`` for the
+ call, and its ``_meta.decide`` gives this request's path.
- response_headers = {}
- response_headers["ratelimit-limit"] = self._deserialize(
- "int", response.headers.get("ratelimit-limit")
- )
- response_headers["ratelimit-remaining"] = self._deserialize(
- "int", response.headers.get("ratelimit-remaining")
- )
- response_headers["ratelimit-reset"] = self._deserialize(
- "int", response.headers.get("ratelimit-reset")
- )
+ Send the decision with the session owner's token. Approval is a separate control request, not a
+ tool, so an agent cannot approve its own calls. After approving, repeat the original call with
+ the same arguments before ``expires_at``. An approval applies only to that session, tool
+ version, and set of arguments, and is used once. To ask again after a denial or expiry, repeat
+ the tool call.
- if response.content:
- deserialized = response.json()
- else:
- deserialized = None
+ :param session_id: The session UUID: the value at the end of the session's ``sessionUrn`` and
+ ``mcpUrl``. The session must belong to the authenticated user and team. Required.
+ :type session_id: str
+ :param approval_id: The ``approval_id`` from a tool result whose ``_meta.status`` is
+ ``requires_approval``. Required.
+ :type approval_id: str
+ :param body: Required.
+ :type body: IO[bytes]
+ :keyword content_type: Body Parameter content-type. Content type parameter for binary body.
+ Default value is "application/json".
+ :paramtype content_type: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
- if cls:
- return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+ Example:
+ .. code-block:: python
- return cast(JSON, deserialized) # type: ignore
+ # response body for status code(s): 200
+ response == {
+ "expires_at": "2020-02-20 00:00:00", # Optional. Repeat an approved call
+ with the same arguments before this time.
+ "id": "str", # Optional. The approval ID.
+ "status": "str" # Optional. Known values are: "approved" and "denied".
+ }
+ # response body for status code(s): 400, 404, 409, 412, 429, 500, 503
+ response == {
+ "call_id": "str", # A unique identifier for this request, when one was
+ assigned. Required.
+ "error": {
+ "class": "str", # Optional. The failure class. Branch on this value
+ rather than on ``message``"" , which may change. Known values are:
+ "invalid_argument", "unauthorized", "forbidden", "rate_limited", "not_found",
+ "timeout", "upstream_error", "output_too_large", "execution_failed",
+ "unavailable", "canceled", "render_required", "unsupported_media_type", and
+ "view_materialization_failed".
+ "message": "str", # Optional. A human-readable explanation that is
+ safe to show to an agent or end user.
+ "recovery_hint": "str", # Optional. The suggested next step. Known
+ values are: "fix_args", "refresh_auth", "retry_later", "narrow_output",
+ "contact_support", and "verify_provider_state".
+ "retriable": bool # Optional. Whether retrying the same request
+ later can succeed.
+ },
+ "status": "str" # Required. "failed"
+ }
+ # response body for status code(s): 401
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
@distributed_trace_async
- async def get(self, action_id: int, **kwargs: Any) -> JSON:
+ async def update(
+ self,
+ session_id: str,
+ approval_id: str,
+ body: Union[JSON, IO[bytes]],
+ **kwargs: Any
+ ) -> JSON:
# pylint: disable=line-too-long
- """Retrieve an Existing Action.
+ """Decide a Pending Approval.
- To retrieve a specific action object, send a GET request to ``/v2/actions/$ACTION_ID``.
+ Approves or denies a tool call that is waiting for approval. A tool result returns
+ ``_meta.status`` set to ``requires_approval`` when the session policy sets ``ask`` for the
+ call, and its ``_meta.decide`` gives this request's path.
- :param action_id: A unique numeric ID that can be used to identify and reference an action.
- Required.
- :type action_id: int
+ Send the decision with the session owner's token. Approval is a separate control request, not a
+ tool, so an agent cannot approve its own calls. After approving, repeat the original call with
+ the same arguments before ``expires_at``. An approval applies only to that session, tool
+ version, and set of arguments, and is used once. To ask again after a denial or expiry, repeat
+ the tool call.
+
+ :param session_id: The session UUID: the value at the end of the session's ``sessionUrn`` and
+ ``mcpUrl``. The session must belong to the authenticated user and team. Required.
+ :type session_id: str
+ :param approval_id: The ``approval_id`` from a tool result whose ``_meta.status`` is
+ ``requires_approval``. Required.
+ :type approval_id: str
+ :param body: Is either a JSON type or a IO[bytes] type. Required.
+ :type body: JSON or IO[bytes]
:return: JSON object
:rtype: JSON
:raises ~azure.core.exceptions.HttpResponseError:
@@ -12509,50 +13255,41 @@ async def get(self, action_id: int, **kwargs: Any) -> JSON:
Example:
.. code-block:: python
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "decision": "str" # Whether to let the pending call run. Required. Known
+ values are: "approve" and "deny".
+ }
+
# response body for status code(s): 200
response == {
- "action": {
- "completed_at": "2020-02-20 00:00:00", # Optional. A time value
- given in ISO8601 combined date and time format that represents when the
- action was completed.
- "id": 0, # Optional. A unique numeric ID that can be used to
- identify and reference an action.
- "region": {
- "available": bool, # This is a boolean value that represents
- whether new Droplets can be created in this region. Required.
- "features": [
- "str" # This attribute is set to an array which
- contains features available in this region. Required.
- ],
- "name": "str", # The display name of the region. This will
- be a full name that is used in the control panel and other interfaces.
- Required.
- "sizes": [
- "str" # This attribute is set to an array which
- contains the identifying slugs for the sizes available in this
- region. sizes:read is required to view. Required.
- ],
- "slug": "str" # A human-readable string that is used as a
- unique identifier for each region. Required.
- },
- "region_slug": "str", # Optional. A human-readable string that is
- used as a unique identifier for each region.
- "resource_id": 0, # Optional. A unique identifier for the resource
- that the action is associated with.
- "resource_type": "str", # Optional. The type of resource that the
- action is associated with.
- "started_at": "2020-02-20 00:00:00", # Optional. A time value given
- in ISO8601 combined date and time format that represents when the action was
- initiated.
- "status": "in-progress", # Optional. Default value is "in-progress".
- The current status of the action. This can be "in-progress", "completed", or
- "errored". Known values are: "in-progress", "completed", and "errored".
- "type": "str" # Optional. This is the type of action that the object
- represents. For example, this could be "transfer" to represent the state of
- an image transfer action.
- }
+ "expires_at": "2020-02-20 00:00:00", # Optional. Repeat an approved call
+ with the same arguments before this time.
+ "id": "str", # Optional. The approval ID.
+ "status": "str" # Optional. Known values are: "approved" and "denied".
}
- # response body for status code(s): 404
+ # response body for status code(s): 400, 404, 409, 412, 429, 500, 503
+ response == {
+ "call_id": "str", # A unique identifier for this request, when one was
+ assigned. Required.
+ "error": {
+ "class": "str", # Optional. The failure class. Branch on this value
+ rather than on ``message``"" , which may change. Known values are:
+ "invalid_argument", "unauthorized", "forbidden", "rate_limited", "not_found",
+ "timeout", "upstream_error", "output_too_large", "execution_failed",
+ "unavailable", "canceled", "render_required", "unsupported_media_type", and
+ "view_materialization_failed".
+ "message": "str", # Optional. A human-readable explanation that is
+ safe to show to an agent or end user.
+ "recovery_hint": "str", # Optional. The suggested next step. Known
+ values are: "fix_args", "refresh_auth", "retry_later", "narrow_output",
+ "contact_support", and "verify_provider_state".
+ "retriable": bool # Optional. Whether retrying the same request
+ later can succeed.
+ },
+ "status": "str" # Required. "failed"
+ }
+ # response body for status code(s): 401
response == {
"id": "str", # A short identifier corresponding to the HTTP status code
returned. For example, the ID for a response returning a 404 status code would
@@ -12565,25 +13302,35 @@ async def get(self, action_id: int, **kwargs: Any) -> JSON:
}
"""
error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 401: ClientAuthenticationError,
404: ResourceNotFoundError,
409: ResourceExistsError,
304: ResourceNotModifiedError,
- 401: cast(
- Type[HttpResponseError],
- lambda response: ClientAuthenticationError(response=response),
- ),
- 429: HttpResponseError,
- 500: HttpResponseError,
}
error_map.update(kwargs.pop("error_map", {}) or {})
- _headers = kwargs.pop("headers", {}) or {}
+ _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
_params = kwargs.pop("params", {}) or {}
+ content_type: Optional[str] = kwargs.pop(
+ "content_type", _headers.pop("Content-Type", None)
+ )
cls: ClsType[JSON] = kwargs.pop("cls", None)
- _request = build_actions_get_request(
- action_id=action_id,
+ content_type = content_type or "application/json"
+ _json = None
+ _content = None
+ if isinstance(body, (IOBase, bytes)):
+ _content = body
+ else:
+ _json = body
+
+ _request = build_gateway_session_approvals_update_request(
+ session_id=session_id,
+ approval_id=approval_id,
+ content_type=content_type,
+ json=_json,
+ content=_content,
headers=_headers,
params=_params,
)
@@ -12598,38 +13345,71 @@ async def get(self, action_id: int, **kwargs: Any) -> JSON:
response = pipeline_response.http_response
- if response.status_code not in [200, 404]:
+ if response.status_code not in [
+ 200,
+ 400,
+ 401,
+ 403,
+ 404,
+ 409,
+ 412,
+ 429,
+ 500,
+ 503,
+ ]:
if _stream:
await response.read() # Load the body in memory and close the socket
- map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ map_error(
+ status_code=response.status_code, response=response, error_map=error_map
+ )
raise HttpResponseError(response=response)
response_headers = {}
if response.status_code == 200:
- response_headers["ratelimit-limit"] = self._deserialize(
- "int", response.headers.get("ratelimit-limit")
- )
- response_headers["ratelimit-remaining"] = self._deserialize(
- "int", response.headers.get("ratelimit-remaining")
- )
- response_headers["ratelimit-reset"] = self._deserialize(
- "int", response.headers.get("ratelimit-reset")
- )
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 400:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 401:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+ if response.status_code == 403:
if response.content:
deserialized = response.json()
else:
deserialized = None
if response.status_code == 404:
- response_headers["ratelimit-limit"] = self._deserialize(
- "int", response.headers.get("ratelimit-limit")
- )
- response_headers["ratelimit-remaining"] = self._deserialize(
- "int", response.headers.get("ratelimit-remaining")
- )
- response_headers["ratelimit-reset"] = self._deserialize(
- "int", response.headers.get("ratelimit-reset")
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 409:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 412:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 429:
+ response_headers["Retry-After"] = self._deserialize(
+ "int", response.headers.get("Retry-After")
)
if response.content:
@@ -12637,20 +13417,32 @@ async def get(self, action_id: int, **kwargs: Any) -> JSON:
else:
deserialized = None
+ if response.status_code == 500:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 503:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
if cls:
return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
return cast(JSON, deserialized) # type: ignore
-class AddonsOperations:
+class GatewayApprovalsOperations:
"""
.. warning::
**DO NOT** instantiate this class directly.
Instead, you should access the following operations through
:class:`~pydo.aio.GeneratedClient`'s
- :attr:`addons` attribute.
+ :attr:`gateway_approvals` attribute.
"""
def __init__(self, *args, **kwargs) -> None:
@@ -12662,14 +13454,36 @@ def __init__(self, *args, **kwargs) -> None:
input_args.pop(0) if input_args else kwargs.pop("deserializer")
)
- @distributed_trace_async
- async def get_app(self, **kwargs: Any) -> JSON:
+ @overload
+ async def update(
+ self,
+ approval_id: str,
+ body: JSON,
+ *,
+ x_session_id: str,
+ content_type: str = "application/json",
+ **kwargs: Any
+ ) -> JSON:
# pylint: disable=line-too-long
- """List Available Add-On Applications.
+ """Decide a Pending Approval by Session Header.
- To fetch details of all available Add-On Applications, send a GET request to
- ``/v2/add-ons/apps``.
+ Approves or denies a tool call that is waiting for approval, identifying the session with the
+ ``X-Session-Id`` header. It behaves the same as ``POST
+ /approvals/session/{session_id}/{approval_id}``\\ , which is the path returned in a result's
+ ``_meta.decide``.
+ :param approval_id: The ``approval_id`` from a tool result whose ``_meta.status`` is
+ ``requires_approval``. Required.
+ :type approval_id: str
+ :param body: Required.
+ :type body: JSON
+ :keyword x_session_id: The session to act in: the UUID at the end of the session's
+ ``sessionUrn`` and ``mcpUrl``. The session must belong to the authenticated user and team.
+ Required.
+ :paramtype x_session_id: str
+ :keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
+ Default value is "application/json".
+ :paramtype content_type: str
:return: JSON object
:rtype: JSON
:raises ~azure.core.exceptions.HttpResponseError:
@@ -12677,176 +13491,157 @@ async def get_app(self, **kwargs: Any) -> JSON:
Example:
.. code-block:: python
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "decision": "str" # Whether to let the pending call run. Required. Known
+ values are: "approve" and "deny".
+ }
+
# response body for status code(s): 200
response == {
- "apps": [
- {
- "app_slug": "str", # The slug identifier for the application
- associated with the resource. Required.
- "eula": "str", # The End User License Agreement URL for the
- resource. Required.
- "plans": [
- {
- "active": bool, # Indicates if the plan is
- currently active. Required.
- "app_id": 0, # ID of the app associated with
- this plan. Required.
- "available": bool, # Indicates if the plan
- is available for selection. Required.
- "by_default": bool, # Indicates if this plan
- is the default option for the app. Required.
- "created_at": "2020-02-20 00:00:00", #
- Timestamp when the plan was created. Required.
- "display_name": "str", # Display name for a
- given plan. Required.
- "id": 0, # ID of a given plan. Required.
- "price_per_month": 0, # Price of a month's
- usage of the plan in US dollars. Required.
- "slug": "str", # Slug identifier for the
- plan. Required.
- "state": "str", # Current state of the plan.
- Required. Known values are: "unknown", "draft", "in_review",
- "approved", "suspended", and "archived".
- "updated_at": "2020-02-20 00:00:00", #
- Timestamp when the plan was last updated. Required.
- "uuid": "str", # Unique identifier for the
- plan. Required.
- "description": "str", # Optional.
- Description of an app plan.
- "dimensions": [
- {
- "display_name": "str", #
- Display name for the dimension. Required.
- "feature_name": "str", #
- Name of the feature associated with the dimension.
- Required.
- "id": 0, # Unique identifier
- for the dimension. Required.
- "sku": "str", # Unique
- string identifier for the dimension, tied to a price.
- Required.
- "slug": "str", # Slug
- identifier for the dimension. Required.
- "volumes": [
- {
- "id": 0, #
- Unique identifier for the addon. Required.
- "low_volume":
- 0, # The minimum volume for the volume pricing
- tier. Required.
- "max_volume":
- 0, # The maximum volume for the volume pricing
- tier. Required.
- "price_per_unit": "str" # The price per unit for
- the volume tier in US dollars. Required.
- }
- ]
- }
- ],
- "features": [
- {
- "created_at": "2020-02-20
- 00:00:00", # Timestamp when the feature was created.
- Required.
- "id": 0, # Unique identifier
- for the app feature. Required.
- "name": "str", # Name of the
- feature. Required.
- "type": "str", # Feature
- type, indicating the kind of data it holds. Required.
- Known values are: "unknown", "string", "boolean", and
- "allowance".
- "updated_at": "2020-02-20
- 00:00:00", # Timestamp when the feature was last
- updated. Required.
- "value": {},
- "unit": "str" # Optional.
- Unit of measurement for the feature, if applicable. Units
- apply to allowance features. Known values are:
- "unit_unknown", "GB", "GIB", "count", "byte", and
- "byte_second".
- }
- ]
- }
- ],
- "tos": "str" # The Terms of Service URL for the resource.
- Required.
- }
- ]
+ "expires_at": "2020-02-20 00:00:00", # Optional. Repeat an approved call
+ with the same arguments before this time.
+ "id": "str", # Optional. The approval ID.
+ "status": "str" # Optional. Known values are: "approved" and "denied".
+ }
+ # response body for status code(s): 400, 404, 409, 412, 429, 500, 503
+ response == {
+ "call_id": "str", # A unique identifier for this request, when one was
+ assigned. Required.
+ "error": {
+ "class": "str", # Optional. The failure class. Branch on this value
+ rather than on ``message``"" , which may change. Known values are:
+ "invalid_argument", "unauthorized", "forbidden", "rate_limited", "not_found",
+ "timeout", "upstream_error", "output_too_large", "execution_failed",
+ "unavailable", "canceled", "render_required", "unsupported_media_type", and
+ "view_materialization_failed".
+ "message": "str", # Optional. A human-readable explanation that is
+ safe to show to an agent or end user.
+ "recovery_hint": "str", # Optional. The suggested next step. Known
+ values are: "fix_args", "refresh_auth", "retry_later", "narrow_output",
+ "contact_support", and "verify_provider_state".
+ "retriable": bool # Optional. Whether retrying the same request
+ later can succeed.
+ },
+ "status": "str" # Required. "failed"
+ }
+ # response body for status code(s): 401
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
}
"""
- error_map: MutableMapping[int, Type[HttpResponseError]] = {
- 404: ResourceNotFoundError,
- 409: ResourceExistsError,
- 304: ResourceNotModifiedError,
- 401: cast(
- Type[HttpResponseError],
- lambda response: ClientAuthenticationError(response=response),
- ),
- 429: HttpResponseError,
- 500: HttpResponseError,
- }
- error_map.update(kwargs.pop("error_map", {}) or {})
-
- _headers = kwargs.pop("headers", {}) or {}
- _params = kwargs.pop("params", {}) or {}
-
- cls: ClsType[JSON] = kwargs.pop("cls", None)
-
- _request = build_addons_get_app_request(
- headers=_headers,
- params=_params,
- )
- _request.url = self._client.format_url(_request.url)
-
- _stream = False
- pipeline_response: PipelineResponse = (
- await self._client._pipeline.run( # pylint: disable=protected-access
- _request, stream=_stream, **kwargs
- )
- )
- response = pipeline_response.http_response
-
- if response.status_code not in [200]:
- if _stream:
- await response.read() # Load the body in memory and close the socket
- map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
- raise HttpResponseError(response=response)
+ @overload
+ async def update(
+ self,
+ approval_id: str,
+ body: IO[bytes],
+ *,
+ x_session_id: str,
+ content_type: str = "application/json",
+ **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """Decide a Pending Approval by Session Header.
- response_headers = {}
- response_headers["ratelimit-limit"] = self._deserialize(
- "int", response.headers.get("ratelimit-limit")
- )
- response_headers["ratelimit-remaining"] = self._deserialize(
- "int", response.headers.get("ratelimit-remaining")
- )
- response_headers["ratelimit-reset"] = self._deserialize(
- "int", response.headers.get("ratelimit-reset")
- )
+ Approves or denies a tool call that is waiting for approval, identifying the session with the
+ ``X-Session-Id`` header. It behaves the same as ``POST
+ /approvals/session/{session_id}/{approval_id}``\\ , which is the path returned in a result's
+ ``_meta.decide``.
- if response.content:
- deserialized = response.json()
- else:
- deserialized = None
+ :param approval_id: The ``approval_id`` from a tool result whose ``_meta.status`` is
+ ``requires_approval``. Required.
+ :type approval_id: str
+ :param body: Required.
+ :type body: IO[bytes]
+ :keyword x_session_id: The session to act in: the UUID at the end of the session's
+ ``sessionUrn`` and ``mcpUrl``. The session must belong to the authenticated user and team.
+ Required.
+ :paramtype x_session_id: str
+ :keyword content_type: Body Parameter content-type. Content type parameter for binary body.
+ Default value is "application/json".
+ :paramtype content_type: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
- if cls:
- return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+ Example:
+ .. code-block:: python
- return cast(JSON, deserialized) # type: ignore
+ # response body for status code(s): 200
+ response == {
+ "expires_at": "2020-02-20 00:00:00", # Optional. Repeat an approved call
+ with the same arguments before this time.
+ "id": "str", # Optional. The approval ID.
+ "status": "str" # Optional. Known values are: "approved" and "denied".
+ }
+ # response body for status code(s): 400, 404, 409, 412, 429, 500, 503
+ response == {
+ "call_id": "str", # A unique identifier for this request, when one was
+ assigned. Required.
+ "error": {
+ "class": "str", # Optional. The failure class. Branch on this value
+ rather than on ``message``"" , which may change. Known values are:
+ "invalid_argument", "unauthorized", "forbidden", "rate_limited", "not_found",
+ "timeout", "upstream_error", "output_too_large", "execution_failed",
+ "unavailable", "canceled", "render_required", "unsupported_media_type", and
+ "view_materialization_failed".
+ "message": "str", # Optional. A human-readable explanation that is
+ safe to show to an agent or end user.
+ "recovery_hint": "str", # Optional. The suggested next step. Known
+ values are: "fix_args", "refresh_auth", "retry_later", "narrow_output",
+ "contact_support", and "verify_provider_state".
+ "retriable": bool # Optional. Whether retrying the same request
+ later can succeed.
+ },
+ "status": "str" # Required. "failed"
+ }
+ # response body for status code(s): 401
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
@distributed_trace_async
- async def get_app_metadata(self, app_slug: str, **kwargs: Any) -> JSON:
+ async def update(
+ self,
+ approval_id: str,
+ body: Union[JSON, IO[bytes]],
+ *,
+ x_session_id: str,
+ **kwargs: Any
+ ) -> JSON:
# pylint: disable=line-too-long
- """Get Metadata for an Add-On Application.
+ """Decide a Pending Approval by Session Header.
- To find out what metadata is required for a specific add-on, send a GET request to
- ``/v2/add-ons/apps/{app_slug}/metadata``.
- Metadata varies by application.
+ Approves or denies a tool call that is waiting for approval, identifying the session with the
+ ``X-Session-Id`` header. It behaves the same as ``POST
+ /approvals/session/{session_id}/{approval_id}``\\ , which is the path returned in a result's
+ ``_meta.decide``.
- :param app_slug: The slug identifier for the application whose metadata is being requested.
+ :param approval_id: The ``approval_id`` from a tool result whose ``_meta.status`` is
+ ``requires_approval``. Required.
+ :type approval_id: str
+ :param body: Is either a JSON type or a IO[bytes] type. Required.
+ :type body: JSON or IO[bytes]
+ :keyword x_session_id: The session to act in: the UUID at the end of the session's
+ ``sessionUrn`` and ``mcpUrl``. The session must belong to the authenticated user and team.
Required.
- :type app_slug: str
+ :paramtype x_session_id: str
:return: JSON object
:rtype: JSON
:raises ~azure.core.exceptions.HttpResponseError:
@@ -12854,26 +13649,41 @@ async def get_app_metadata(self, app_slug: str, **kwargs: Any) -> JSON:
Example:
.. code-block:: python
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "decision": "str" # Whether to let the pending call run. Required. Known
+ values are: "approve" and "deny".
+ }
+
# response body for status code(s): 200
response == {
- "metadata": [
- {
- "description": "str", # A brief description of the metadata
- item. Required.
- "display_name": "str", # The display name of the metadata
- item. Required.
- "id": 0, # Unique identifier for the addon metadata item.
- Required.
- "name": "str", # The name of the metadata item. Required.
- "type": "str", # The data type of the metadata value.
- Required. Known values are: "string" and "boolean".
- "options": [
- "str" # Optional. options.
- ]
- }
- ]
+ "expires_at": "2020-02-20 00:00:00", # Optional. Repeat an approved call
+ with the same arguments before this time.
+ "id": "str", # Optional. The approval ID.
+ "status": "str" # Optional. Known values are: "approved" and "denied".
}
- # response body for status code(s): 404
+ # response body for status code(s): 400, 404, 409, 412, 429, 500, 503
+ response == {
+ "call_id": "str", # A unique identifier for this request, when one was
+ assigned. Required.
+ "error": {
+ "class": "str", # Optional. The failure class. Branch on this value
+ rather than on ``message``"" , which may change. Known values are:
+ "invalid_argument", "unauthorized", "forbidden", "rate_limited", "not_found",
+ "timeout", "upstream_error", "output_too_large", "execution_failed",
+ "unavailable", "canceled", "render_required", "unsupported_media_type", and
+ "view_materialization_failed".
+ "message": "str", # Optional. A human-readable explanation that is
+ safe to show to an agent or end user.
+ "recovery_hint": "str", # Optional. The suggested next step. Known
+ values are: "fix_args", "refresh_auth", "retry_later", "narrow_output",
+ "contact_support", and "verify_provider_state".
+ "retriable": bool # Optional. Whether retrying the same request
+ later can succeed.
+ },
+ "status": "str" # Required. "failed"
+ }
+ # response body for status code(s): 401
response == {
"id": "str", # A short identifier corresponding to the HTTP status code
returned. For example, the ID for a response returning a 404 status code would
@@ -12886,25 +13696,35 @@ async def get_app_metadata(self, app_slug: str, **kwargs: Any) -> JSON:
}
"""
error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 401: ClientAuthenticationError,
404: ResourceNotFoundError,
409: ResourceExistsError,
304: ResourceNotModifiedError,
- 401: cast(
- Type[HttpResponseError],
- lambda response: ClientAuthenticationError(response=response),
- ),
- 429: HttpResponseError,
- 500: HttpResponseError,
}
error_map.update(kwargs.pop("error_map", {}) or {})
- _headers = kwargs.pop("headers", {}) or {}
+ _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
_params = kwargs.pop("params", {}) or {}
+ content_type: Optional[str] = kwargs.pop(
+ "content_type", _headers.pop("Content-Type", None)
+ )
cls: ClsType[JSON] = kwargs.pop("cls", None)
- _request = build_addons_get_app_metadata_request(
- app_slug=app_slug,
+ content_type = content_type or "application/json"
+ _json = None
+ _content = None
+ if isinstance(body, (IOBase, bytes)):
+ _content = body
+ else:
+ _json = body
+
+ _request = build_gateway_approvals_update_request(
+ approval_id=approval_id,
+ x_session_id=x_session_id,
+ content_type=content_type,
+ json=_json,
+ content=_content,
headers=_headers,
params=_params,
)
@@ -12919,38 +13739,71 @@ async def get_app_metadata(self, app_slug: str, **kwargs: Any) -> JSON:
response = pipeline_response.http_response
- if response.status_code not in [200, 404]:
+ if response.status_code not in [
+ 200,
+ 400,
+ 401,
+ 403,
+ 404,
+ 409,
+ 412,
+ 429,
+ 500,
+ 503,
+ ]:
if _stream:
await response.read() # Load the body in memory and close the socket
- map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ map_error(
+ status_code=response.status_code, response=response, error_map=error_map
+ )
raise HttpResponseError(response=response)
response_headers = {}
if response.status_code == 200:
- response_headers["ratelimit-limit"] = self._deserialize(
- "int", response.headers.get("ratelimit-limit")
- )
- response_headers["ratelimit-remaining"] = self._deserialize(
- "int", response.headers.get("ratelimit-remaining")
- )
- response_headers["ratelimit-reset"] = self._deserialize(
- "int", response.headers.get("ratelimit-reset")
- )
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 400:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 401:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+ if response.status_code == 403:
if response.content:
deserialized = response.json()
else:
deserialized = None
if response.status_code == 404:
- response_headers["ratelimit-limit"] = self._deserialize(
- "int", response.headers.get("ratelimit-limit")
- )
- response_headers["ratelimit-remaining"] = self._deserialize(
- "int", response.headers.get("ratelimit-remaining")
- )
- response_headers["ratelimit-reset"] = self._deserialize(
- "int", response.headers.get("ratelimit-reset")
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 409:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 412:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 429:
+ response_headers["Retry-After"] = self._deserialize(
+ "int", response.headers.get("Retry-After")
)
if response.content:
@@ -12958,18 +13811,60 @@ async def get_app_metadata(self, app_slug: str, **kwargs: Any) -> JSON:
else:
deserialized = None
+ if response.status_code == 500:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 503:
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
if cls:
return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
return cast(JSON, deserialized) # type: ignore
+
+class OneClicksOperations:
+ """
+ .. warning::
+ **DO NOT** instantiate this class directly.
+
+ Instead, you should access the following operations through
+ :class:`~pydo.aio.GeneratedClient`'s
+ :attr:`one_clicks` attribute.
+ """
+
+ def __init__(self, *args, **kwargs) -> None:
+ input_args = list(args)
+ self._client = input_args.pop(0) if input_args else kwargs.pop("client")
+ self._config = input_args.pop(0) if input_args else kwargs.pop("config")
+ self._serialize = input_args.pop(0) if input_args else kwargs.pop("serializer")
+ self._deserialize = (
+ input_args.pop(0) if input_args else kwargs.pop("deserializer")
+ )
+
@distributed_trace_async
- async def list(self, **kwargs: Any) -> JSON:
- # pylint: disable=line-too-long
- """List all Add-On Resources.
+ async def list(self, *, type: Optional[str] = None, **kwargs: Any) -> JSON:
+ """List 1-Click Applications.
- To fetch all Add-On Resources under your team, send a GET request to ``/v2/add-ons/saas``.
+ To list all available 1-Click applications, send a GET request to ``/v2/1-clicks``. The
+ ``type`` may
+ be provided as query paramater in order to restrict results to a certain type of 1-Click, for
+ example: ``/v2/1-clicks?type=droplet``. Current supported types are ``kubernetes`` and
+ ``droplet``.
+
+ The response will be a JSON object with a key called ``1_clicks``. This will be set to an array
+ of
+ 1-Click application data, each of which will contain the the slug and type for the 1-Click.
+ :keyword type: Restrict results to a certain type of 1-Click. Known values are: "droplet" and
+ "kubernetes". Default value is None.
+ :paramtype type: str
:return: JSON object
:rtype: JSON
:raises ~azure.core.exceptions.HttpResponseError:
@@ -12979,38 +13874,12 @@ async def list(self, **kwargs: Any) -> JSON:
# response body for status code(s): 200
response == {
- "resources": [
+ "1_clicks": [
{
- "app_slug": "str", # The slug identifier for the application
- associated with the resource. Required.
- "has_config": bool, # Indicates if the resource has
- configuration values set by the vendor. Required.
- "name": "str", # The name of the addon resource. Required.
- "plan_slug": "str", # The slug identifier for the plan
- associated with the resource. Required.
- "state": "str", # The state the resource is currently in.
- Required. Known values are: "pending", "provisioning", "provisioned",
- "deprovisioning", "deprovisioned", "provisioning-failed",
- "deprovisioning-failed", and "suspended".
- "uuid": "str", # The unique identifier for the addon
- resource. Required.
- "app_name": "str", # Optional. The name of the application
- associated with the resource.
- "message": "str", # Optional. A message related to the
- resource, if applicable.
- "metadata": [
- {
- "name": "str", # The name of the metadata
- item to be set. Required.
- "value": {}
- }
- ],
- "plan_name": "str", # Optional. The name of the plan
- associated with the resource.
- "plan_price_per_month": 0, # Optional. The price of the plan
- per month in US dollars.
- "sso_url": "str" # Optional. The Single Sign-On URL for the
- resource, if applicable.
+ "slug": "str", # The slug identifier for the 1-Click
+ application. Required.
+ "type": "str" # The type of the 1-Click application.
+ Required.
}
]
}
@@ -13033,7 +13902,8 @@ async def list(self, **kwargs: Any) -> JSON:
cls: ClsType[JSON] = kwargs.pop("cls", None)
- _request = build_addons_list_request(
+ _request = build_one_clicks_list_request(
+ type=type,
headers=_headers,
params=_params,
)
@@ -13076,17 +13946,16 @@ async def list(self, **kwargs: Any) -> JSON:
return cast(JSON, deserialized) # type: ignore
@overload
- async def create(
+ async def install_kubernetes(
self, body: JSON, *, content_type: str = "application/json", **kwargs: Any
) -> JSON:
# pylint: disable=line-too-long
- """Create/Provision a New Add-on Resource.
+ """Install Kubernetes 1-Click Applications.
- To create an add-on resource, send a POST request to ``/v2/add-ons/saas`` with required
- parameters.
- Some add-ons require additional metadata to be provided in the request body. To find out
- what metadata is required for a specific add-on, send a GET request to
- ``/v2/add-ons/apps/{app_slug}/metadata``.
+ To install a Kubernetes 1-Click application on a cluster, send a POST request to
+ ``/v2/1-clicks/kubernetes``. The ``addon_slugs`` and ``cluster_uuid`` must be provided as body
+ parameter in order to specify which 1-Click application(s) to install. To list all available
+ 1-Click Kubernetes applications, send a request to ``/v2/1-clicks?type=kubernetes``.
:param body: Required.
:type body: JSON
@@ -13102,73 +13971,30 @@ async def create(
# JSON input template you can fill out and use as your body input.
body = {
- "app_slug": "str", # The slug identifier for the application associated with
- the resource. Required.
- "metadata": [
- {
- "name": "str", # The name of the metadata item to be set.
- Required.
- "value": {}
- }
+ "addon_slugs": [
+ "str" # An array of 1-Click Application slugs to be installed to the
+ Kubernetes cluster. Required.
],
- "name": "str", # The name of the addon resource. Required.
- "plan_slug": "str", # The slug identifier for the plan associated with the
- resource. Required.
- "fleet_uuid": "str", # Optional. UUID of the fleet/project to which this
- resource will belong.
- "linked_droplet_id": 0 # Optional. ID of the droplet to be linked to this
- resource, if applicable.
+ "cluster_uuid": "str" # A unique ID for the Kubernetes cluster to which the
+ 1-Click Applications will be installed. Required.
}
# response body for status code(s): 200
response == {
- "resource": {
- "app_slug": "str", # The slug identifier for the application
- associated with the resource. Required.
- "has_config": bool, # Indicates if the resource has configuration
- values set by the vendor. Required.
- "name": "str", # The name of the addon resource. Required.
- "plan_slug": "str", # The slug identifier for the plan associated
- with the resource. Required.
- "state": "str", # The state the resource is currently in. Required.
- Known values are: "pending", "provisioning", "provisioned", "deprovisioning",
- "deprovisioned", "provisioning-failed", "deprovisioning-failed", and
- "suspended".
- "uuid": "str", # The unique identifier for the addon resource.
- Required.
- "app_name": "str", # Optional. The name of the application
- associated with the resource.
- "message": "str", # Optional. A message related to the resource, if
- applicable.
- "metadata": [
- {
- "name": "str", # The name of the metadata item to be
- set. Required.
- "value": {}
- }
- ],
- "plan_name": "str", # Optional. The name of the plan associated with
- the resource.
- "plan_price_per_month": 0, # Optional. The price of the plan per
- month in US dollars.
- "sso_url": "str" # Optional. The Single Sign-On URL for the
- resource, if applicable.
- }
+ "message": "str" # Optional. A message about the result of the request.
}
"""
@overload
- async def create(
+ async def install_kubernetes(
self, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any
) -> JSON:
- # pylint: disable=line-too-long
- """Create/Provision a New Add-on Resource.
+ """Install Kubernetes 1-Click Applications.
- To create an add-on resource, send a POST request to ``/v2/add-ons/saas`` with required
- parameters.
- Some add-ons require additional metadata to be provided in the request body. To find out
- what metadata is required for a specific add-on, send a GET request to
- ``/v2/add-ons/apps/{app_slug}/metadata``.
+ To install a Kubernetes 1-Click application on a cluster, send a POST request to
+ ``/v2/1-clicks/kubernetes``. The ``addon_slugs`` and ``cluster_uuid`` must be provided as body
+ parameter in order to specify which 1-Click application(s) to install. To list all available
+ 1-Click Kubernetes applications, send a request to ``/v2/1-clicks?type=kubernetes``.
:param body: Required.
:type body: IO[bytes]
@@ -13184,51 +14010,21 @@ async def create(
# response body for status code(s): 200
response == {
- "resource": {
- "app_slug": "str", # The slug identifier for the application
- associated with the resource. Required.
- "has_config": bool, # Indicates if the resource has configuration
- values set by the vendor. Required.
- "name": "str", # The name of the addon resource. Required.
- "plan_slug": "str", # The slug identifier for the plan associated
- with the resource. Required.
- "state": "str", # The state the resource is currently in. Required.
- Known values are: "pending", "provisioning", "provisioned", "deprovisioning",
- "deprovisioned", "provisioning-failed", "deprovisioning-failed", and
- "suspended".
- "uuid": "str", # The unique identifier for the addon resource.
- Required.
- "app_name": "str", # Optional. The name of the application
- associated with the resource.
- "message": "str", # Optional. A message related to the resource, if
- applicable.
- "metadata": [
- {
- "name": "str", # The name of the metadata item to be
- set. Required.
- "value": {}
- }
- ],
- "plan_name": "str", # Optional. The name of the plan associated with
- the resource.
- "plan_price_per_month": 0, # Optional. The price of the plan per
- month in US dollars.
- "sso_url": "str" # Optional. The Single Sign-On URL for the
- resource, if applicable.
- }
+ "message": "str" # Optional. A message about the result of the request.
}
"""
@distributed_trace_async
- async def create(self, body: Union[JSON, IO[bytes]], **kwargs: Any) -> JSON:
+ async def install_kubernetes(
+ self, body: Union[JSON, IO[bytes]], **kwargs: Any
+ ) -> JSON:
# pylint: disable=line-too-long
- """Create/Provision a New Add-on Resource.
+ """Install Kubernetes 1-Click Applications.
- To create an add-on resource, send a POST request to ``/v2/add-ons/saas`` with required
- parameters.
- Some add-ons require additional metadata to be provided in the request body. To find out
- what metadata is required for a specific add-on, send a GET request to
- ``/v2/add-ons/apps/{app_slug}/metadata``.
+ To install a Kubernetes 1-Click application on a cluster, send a POST request to
+ ``/v2/1-clicks/kubernetes``. The ``addon_slugs`` and ``cluster_uuid`` must be provided as body
+ parameter in order to specify which 1-Click application(s) to install. To list all available
+ 1-Click Kubernetes applications, send a request to ``/v2/1-clicks?type=kubernetes``.
:param body: Is either a JSON type or a IO[bytes] type. Required.
:type body: JSON or IO[bytes]
@@ -13241,58 +14037,17 @@ async def create(self, body: Union[JSON, IO[bytes]], **kwargs: Any) -> JSON:
# JSON input template you can fill out and use as your body input.
body = {
- "app_slug": "str", # The slug identifier for the application associated with
- the resource. Required.
- "metadata": [
- {
- "name": "str", # The name of the metadata item to be set.
- Required.
- "value": {}
- }
+ "addon_slugs": [
+ "str" # An array of 1-Click Application slugs to be installed to the
+ Kubernetes cluster. Required.
],
- "name": "str", # The name of the addon resource. Required.
- "plan_slug": "str", # The slug identifier for the plan associated with the
- resource. Required.
- "fleet_uuid": "str", # Optional. UUID of the fleet/project to which this
- resource will belong.
- "linked_droplet_id": 0 # Optional. ID of the droplet to be linked to this
- resource, if applicable.
+ "cluster_uuid": "str" # A unique ID for the Kubernetes cluster to which the
+ 1-Click Applications will be installed. Required.
}
# response body for status code(s): 200
response == {
- "resource": {
- "app_slug": "str", # The slug identifier for the application
- associated with the resource. Required.
- "has_config": bool, # Indicates if the resource has configuration
- values set by the vendor. Required.
- "name": "str", # The name of the addon resource. Required.
- "plan_slug": "str", # The slug identifier for the plan associated
- with the resource. Required.
- "state": "str", # The state the resource is currently in. Required.
- Known values are: "pending", "provisioning", "provisioned", "deprovisioning",
- "deprovisioned", "provisioning-failed", "deprovisioning-failed", and
- "suspended".
- "uuid": "str", # The unique identifier for the addon resource.
- Required.
- "app_name": "str", # Optional. The name of the application
- associated with the resource.
- "message": "str", # Optional. A message related to the resource, if
- applicable.
- "metadata": [
- {
- "name": "str", # The name of the metadata item to be
- set. Required.
- "value": {}
- }
- ],
- "plan_name": "str", # Optional. The name of the plan associated with
- the resource.
- "plan_price_per_month": 0, # Optional. The price of the plan per
- month in US dollars.
- "sso_url": "str" # Optional. The Single Sign-On URL for the
- resource, if applicable.
- }
+ "message": "str" # Optional. A message about the result of the request.
}
"""
error_map: MutableMapping[int, Type[HttpResponseError]] = {
@@ -13324,7 +14079,7 @@ async def create(self, body: Union[JSON, IO[bytes]], **kwargs: Any) -> JSON:
else:
_json = body
- _request = build_addons_create_request(
+ _request = build_one_clicks_install_kubernetes_request(
content_type=content_type,
json=_json,
content=_content,
@@ -13369,17 +14124,33 @@ async def create(self, body: Union[JSON, IO[bytes]], **kwargs: Any) -> JSON:
return cast(JSON, deserialized) # type: ignore
+
+class AccountOperations:
+ """
+ .. warning::
+ **DO NOT** instantiate this class directly.
+
+ Instead, you should access the following operations through
+ :class:`~pydo.aio.GeneratedClient`'s
+ :attr:`account` attribute.
+ """
+
+ def __init__(self, *args, **kwargs) -> None:
+ input_args = list(args)
+ self._client = input_args.pop(0) if input_args else kwargs.pop("client")
+ self._config = input_args.pop(0) if input_args else kwargs.pop("config")
+ self._serialize = input_args.pop(0) if input_args else kwargs.pop("serializer")
+ self._deserialize = (
+ input_args.pop(0) if input_args else kwargs.pop("deserializer")
+ )
+
@distributed_trace_async
- async def get(self, resource_uuid: str, **kwargs: Any) -> JSON:
+ async def get(self, **kwargs: Any) -> JSON:
# pylint: disable=line-too-long
- """Get details on an Add-On Resource.
+ """Get User Information.
- To fetch details of a specific Add-On Resource, send a GET request to
- ``/v2/add-ons/saas/{resource_uuid}``.
- Replace ``{resource_uuid}`` with the UUID of the resource you want to retrieve.
+ To show information about the current user account, send a GET request to ``/v2/account``.
- :param resource_uuid: The UUID of the add-on resource to retrieve. Required.
- :type resource_uuid: str
:return: JSON object
:rtype: JSON
:raises ~azure.core.exceptions.HttpResponseError:
@@ -13389,50 +14160,32 @@ async def get(self, resource_uuid: str, **kwargs: Any) -> JSON:
# response body for status code(s): 200
response == {
- "resource": {
- "app_slug": "str", # The slug identifier for the application
- associated with the resource. Required.
- "has_config": bool, # Indicates if the resource has configuration
- values set by the vendor. Required.
- "name": "str", # The name of the addon resource. Required.
- "plan_slug": "str", # The slug identifier for the plan associated
- with the resource. Required.
- "state": "str", # The state the resource is currently in. Required.
- Known values are: "pending", "provisioning", "provisioned", "deprovisioning",
- "deprovisioned", "provisioning-failed", "deprovisioning-failed", and
- "suspended".
- "uuid": "str", # The unique identifier for the addon resource.
- Required.
- "app_name": "str", # Optional. The name of the application
- associated with the resource.
- "message": "str", # Optional. A message related to the resource, if
- applicable.
- "metadata": [
- {
- "name": "str", # The name of the metadata item to be
- set. Required.
- "value": {}
- }
- ],
- "plan_name": "str", # Optional. The name of the plan associated with
- the resource.
- "plan_price_per_month": 0, # Optional. The price of the plan per
- month in US dollars.
- "sso_url": "str" # Optional. The Single Sign-On URL for the
- resource, if applicable.
+ "account": {
+ "droplet_limit": 0, # The total number of Droplets current user or
+ team may have active at one time. :code:` `:code:` `Requires
+ ``droplet:read`` scope. Required.
+ "email": "str", # The email address used by the current user to
+ register for DigitalOcean. Required.
+ "email_verified": False, # Default value is False. If true, the user
+ has verified their account via email. False otherwise. Required.
+ "floating_ip_limit": 0, # The total number of Floating IPs the
+ current user or team may have. :code:` `:code:` `Requires
+ ``reserved_ip:read`` scope. Required.
+ "status": "active", # Default value is "active". This value is one
+ of "active", "warning" or "locked". Known values are: "active", "warning",
+ and "locked".
+ "status_message": "str", # A human-readable message giving more
+ details about the status of the account. Required.
+ "uuid": "str", # The unique universal identifier for the current
+ user. Required.
+ "name": "str", # Optional. The display name for the current user.
+ "team": {
+ "name": "str", # Optional. The name for the current team.
+ "uuid": "str" # Optional. The unique universal identifier
+ for the current team.
+ }
}
}
- # response body for status code(s): 404
- response == {
- "id": "str", # A short identifier corresponding to the HTTP status code
- returned. For example, the ID for a response returning a 404 status code would
- be "not_found.". Required.
- "message": "str", # A message providing additional information about the
- error, including details to help resolve it when possible. Required.
- "request_id": "str" # Optional. Optionally, some endpoints may include a
- request ID that should be provided when reporting bugs or opening support
- tickets to help identify the issue.
- }
"""
error_map: MutableMapping[int, Type[HttpResponseError]] = {
404: ResourceNotFoundError,
@@ -13452,8 +14205,7 @@ async def get(self, resource_uuid: str, **kwargs: Any) -> JSON:
cls: ClsType[JSON] = kwargs.pop("cls", None)
- _request = build_addons_get_request(
- resource_uuid=resource_uuid,
+ _request = build_account_get_request(
headers=_headers,
params=_params,
)
@@ -13468,80 +14220,96 @@ async def get(self, resource_uuid: str, **kwargs: Any) -> JSON:
response = pipeline_response.http_response
- if response.status_code not in [200, 404]:
+ if response.status_code not in [200]:
if _stream:
await response.read() # Load the body in memory and close the socket
map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
raise HttpResponseError(response=response)
response_headers = {}
- if response.status_code == 200:
- response_headers["ratelimit-limit"] = self._deserialize(
- "int", response.headers.get("ratelimit-limit")
- )
- response_headers["ratelimit-remaining"] = self._deserialize(
- "int", response.headers.get("ratelimit-remaining")
- )
- response_headers["ratelimit-reset"] = self._deserialize(
- "int", response.headers.get("ratelimit-reset")
- )
-
- if response.content:
- deserialized = response.json()
- else:
- deserialized = None
-
- if response.status_code == 404:
- response_headers["ratelimit-limit"] = self._deserialize(
- "int", response.headers.get("ratelimit-limit")
- )
- response_headers["ratelimit-remaining"] = self._deserialize(
- "int", response.headers.get("ratelimit-remaining")
- )
- response_headers["ratelimit-reset"] = self._deserialize(
- "int", response.headers.get("ratelimit-reset")
- )
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
- if response.content:
- deserialized = response.json()
- else:
- deserialized = None
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
if cls:
return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
return cast(JSON, deserialized) # type: ignore
+
+class SshKeysOperations:
+ """
+ .. warning::
+ **DO NOT** instantiate this class directly.
+
+ Instead, you should access the following operations through
+ :class:`~pydo.aio.GeneratedClient`'s
+ :attr:`ssh_keys` attribute.
+ """
+
+ def __init__(self, *args, **kwargs) -> None:
+ input_args = list(args)
+ self._client = input_args.pop(0) if input_args else kwargs.pop("client")
+ self._config = input_args.pop(0) if input_args else kwargs.pop("config")
+ self._serialize = input_args.pop(0) if input_args else kwargs.pop("serializer")
+ self._deserialize = (
+ input_args.pop(0) if input_args else kwargs.pop("deserializer")
+ )
+
@distributed_trace_async
- async def delete(self, resource_uuid: str, **kwargs: Any) -> Optional[JSON]:
+ async def list(self, *, per_page: int = 20, page: int = 1, **kwargs: Any) -> JSON:
# pylint: disable=line-too-long
- """Delete/Deprovision an Add-on Resource.
+ """List All SSH Keys.
- To delete an add-on resource, send a DELETE request to ``/v2/add-ons/saas/{resource_uuid}``
- with the UUID of the resource to delete.
- You cannot retrieve the resource after it has been deleted. The response indicates a request
- was sent to the 3rd party add-on provider to delete the resource.
- You will no longer be billed for this resource.
+ To list all of the keys in your account, send a GET request to ``/v2/account/keys``. The
+ response will be a JSON object with a key set to ``ssh_keys``. The value of this will be an
+ array of ssh_key objects, each of which contains the standard ssh_key attributes.
- :param resource_uuid: A unique identifier for the add-on resource. Required.
- :type resource_uuid: str
- :return: JSON object or None
- :rtype: JSON or None
+ :keyword per_page: Number of items returned per page. Default value is 20.
+ :paramtype per_page: int
+ :keyword page: Which 'page' of paginated results to return. Default value is 1.
+ :paramtype page: int
+ :return: JSON object
+ :rtype: JSON
:raises ~azure.core.exceptions.HttpResponseError:
Example:
.. code-block:: python
- # response body for status code(s): 404
+ # response body for status code(s): 200
response == {
- "id": "str", # A short identifier corresponding to the HTTP status code
- returned. For example, the ID for a response returning a 404 status code would
- be "not_found.". Required.
- "message": "str", # A message providing additional information about the
- error, including details to help resolve it when possible. Required.
- "request_id": "str" # Optional. Optionally, some endpoints may include a
- request ID that should be provided when reporting bugs or opening support
- tickets to help identify the issue.
+ "meta": {
+ "total": 0 # Optional. Number of objects returned by the request.
+ },
+ "links": {
+ "pages": {}
+ },
+ "ssh_keys": [
+ {
+ "name": "str", # A human-readable display name for this key,
+ used to easily identify the SSH keys when they are displayed. Required.
+ "public_key": "str", # The entire public key string that was
+ uploaded. Embedded into the root user's ``authorized_keys`` file if you
+ include this key during Droplet creation. Required.
+ "fingerprint": "str", # Optional. A unique identifier that
+ differentiates this key from other keys using a format that SSH
+ recognizes. The fingerprint is created when the key is added to your
+ account.
+ "id": 0 # Optional. A unique identification number for this
+ key. Can be used to embed a specific SSH key into a Droplet.
+ }
+ ]
}
"""
error_map: MutableMapping[int, Type[HttpResponseError]] = {
@@ -13560,10 +14328,11 @@ async def delete(self, resource_uuid: str, **kwargs: Any) -> Optional[JSON]:
_headers = kwargs.pop("headers", {}) or {}
_params = kwargs.pop("params", {}) or {}
- cls: ClsType[Optional[JSON]] = kwargs.pop("cls", None)
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
- _request = build_addons_delete_request(
- resource_uuid=resource_uuid,
+ _request = build_ssh_keys_list_request(
+ per_page=per_page,
+ page=page,
headers=_headers,
params=_params,
)
@@ -13578,65 +14347,44 @@ async def delete(self, resource_uuid: str, **kwargs: Any) -> Optional[JSON]:
response = pipeline_response.http_response
- if response.status_code not in [200, 404]:
+ if response.status_code not in [200]:
if _stream:
await response.read() # Load the body in memory and close the socket
map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
raise HttpResponseError(response=response)
- deserialized = None
response_headers = {}
- if response.status_code == 200:
- response_headers["ratelimit-limit"] = self._deserialize(
- "int", response.headers.get("ratelimit-limit")
- )
- response_headers["ratelimit-remaining"] = self._deserialize(
- "int", response.headers.get("ratelimit-remaining")
- )
- response_headers["ratelimit-reset"] = self._deserialize(
- "int", response.headers.get("ratelimit-reset")
- )
-
- if response.status_code == 404:
- response_headers["ratelimit-limit"] = self._deserialize(
- "int", response.headers.get("ratelimit-limit")
- )
- response_headers["ratelimit-remaining"] = self._deserialize(
- "int", response.headers.get("ratelimit-remaining")
- )
- response_headers["ratelimit-reset"] = self._deserialize(
- "int", response.headers.get("ratelimit-reset")
- )
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
- if response.content:
- deserialized = response.json()
- else:
- deserialized = None
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
if cls:
- return cls(pipeline_response, deserialized, response_headers) # type: ignore
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
- return deserialized # type: ignore
+ return cast(JSON, deserialized) # type: ignore
@overload
- async def patch(
- self,
- resource_uuid: str,
- body: JSON,
- *,
- content_type: str = "application/json",
- **kwargs: Any
+ async def create(
+ self, body: JSON, *, content_type: str = "application/json", **kwargs: Any
) -> JSON:
# pylint: disable=line-too-long
- """Update the name for an Add-On Resource.
+ """Create a New SSH Key.
- To change the name of an Add-On Resource, send a PATCH request to
- ``/v2/add-ons/saas/{resource_uuid}``.
- Replace ``{resource_uuid}`` with the UUID of the resource for which you want to change the
- name.
+ To add a new SSH public key to your DigitalOcean account, send a POST request to
+ ``/v2/account/keys``. Set the ``name`` attribute to the name you wish to use and the
+ ``public_key`` attribute to the full public key you are adding.
- :param resource_uuid: The UUID of the add-on resource to rename. Required.
- :type resource_uuid: str
:param body: Required.
:type body: JSON
:keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
@@ -13651,76 +14399,46 @@ async def patch(
# JSON input template you can fill out and use as your body input.
body = {
- "name": "str" # The new name for the add-on resource. Required.
+ "name": "str", # A human-readable display name for this key, used to easily
+ identify the SSH keys when they are displayed. Required.
+ "public_key": "str", # The entire public key string that was uploaded.
+ Embedded into the root user's ``authorized_keys`` file if you include this key
+ during Droplet creation. Required.
+ "fingerprint": "str", # Optional. A unique identifier that differentiates
+ this key from other keys using a format that SSH recognizes. The fingerprint is
+ created when the key is added to your account.
+ "id": 0 # Optional. A unique identification number for this key. Can be used
+ to embed a specific SSH key into a Droplet.
}
- # response body for status code(s): 200
+ # response body for status code(s): 201
response == {
- "resource": {
- "app_slug": "str", # The slug identifier for the application
- associated with the resource. Required.
- "has_config": bool, # Indicates if the resource has configuration
- values set by the vendor. Required.
- "name": "str", # The name of the addon resource. Required.
- "plan_slug": "str", # The slug identifier for the plan associated
- with the resource. Required.
- "state": "str", # The state the resource is currently in. Required.
- Known values are: "pending", "provisioning", "provisioned", "deprovisioning",
- "deprovisioned", "provisioning-failed", "deprovisioning-failed", and
- "suspended".
- "uuid": "str", # The unique identifier for the addon resource.
- Required.
- "app_name": "str", # Optional. The name of the application
- associated with the resource.
- "message": "str", # Optional. A message related to the resource, if
- applicable.
- "metadata": [
- {
- "name": "str", # The name of the metadata item to be
- set. Required.
- "value": {}
- }
- ],
- "plan_name": "str", # Optional. The name of the plan associated with
- the resource.
- "plan_price_per_month": 0, # Optional. The price of the plan per
- month in US dollars.
- "sso_url": "str" # Optional. The Single Sign-On URL for the
- resource, if applicable.
+ "ssh_key": {
+ "name": "str", # A human-readable display name for this key, used to
+ easily identify the SSH keys when they are displayed. Required.
+ "public_key": "str", # The entire public key string that was
+ uploaded. Embedded into the root user's ``authorized_keys`` file if you
+ include this key during Droplet creation. Required.
+ "fingerprint": "str", # Optional. A unique identifier that
+ differentiates this key from other keys using a format that SSH recognizes.
+ The fingerprint is created when the key is added to your account.
+ "id": 0 # Optional. A unique identification number for this key. Can
+ be used to embed a specific SSH key into a Droplet.
}
}
- # response body for status code(s): 404
- response == {
- "id": "str", # A short identifier corresponding to the HTTP status code
- returned. For example, the ID for a response returning a 404 status code would
- be "not_found.". Required.
- "message": "str", # A message providing additional information about the
- error, including details to help resolve it when possible. Required.
- "request_id": "str" # Optional. Optionally, some endpoints may include a
- request ID that should be provided when reporting bugs or opening support
- tickets to help identify the issue.
- }
"""
@overload
- async def patch(
- self,
- resource_uuid: str,
- body: IO[bytes],
- *,
- content_type: str = "application/json",
- **kwargs: Any
+ async def create(
+ self, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any
) -> JSON:
# pylint: disable=line-too-long
- """Update the name for an Add-On Resource.
+ """Create a New SSH Key.
- To change the name of an Add-On Resource, send a PATCH request to
- ``/v2/add-ons/saas/{resource_uuid}``.
- Replace ``{resource_uuid}`` with the UUID of the resource for which you want to change the
- name.
+ To add a new SSH public key to your DigitalOcean account, send a POST request to
+ ``/v2/account/keys``. Set the ``name`` attribute to the name you wish to use and the
+ ``public_key`` attribute to the full public key you are adding.
- :param resource_uuid: The UUID of the add-on resource to rename. Required.
- :type resource_uuid: str
:param body: Required.
:type body: IO[bytes]
:keyword content_type: Body Parameter content-type. Content type parameter for binary body.
@@ -13733,68 +14451,32 @@ async def patch(
Example:
.. code-block:: python
- # response body for status code(s): 200
+ # response body for status code(s): 201
response == {
- "resource": {
- "app_slug": "str", # The slug identifier for the application
- associated with the resource. Required.
- "has_config": bool, # Indicates if the resource has configuration
- values set by the vendor. Required.
- "name": "str", # The name of the addon resource. Required.
- "plan_slug": "str", # The slug identifier for the plan associated
- with the resource. Required.
- "state": "str", # The state the resource is currently in. Required.
- Known values are: "pending", "provisioning", "provisioned", "deprovisioning",
- "deprovisioned", "provisioning-failed", "deprovisioning-failed", and
- "suspended".
- "uuid": "str", # The unique identifier for the addon resource.
- Required.
- "app_name": "str", # Optional. The name of the application
- associated with the resource.
- "message": "str", # Optional. A message related to the resource, if
- applicable.
- "metadata": [
- {
- "name": "str", # The name of the metadata item to be
- set. Required.
- "value": {}
- }
- ],
- "plan_name": "str", # Optional. The name of the plan associated with
- the resource.
- "plan_price_per_month": 0, # Optional. The price of the plan per
- month in US dollars.
- "sso_url": "str" # Optional. The Single Sign-On URL for the
- resource, if applicable.
+ "ssh_key": {
+ "name": "str", # A human-readable display name for this key, used to
+ easily identify the SSH keys when they are displayed. Required.
+ "public_key": "str", # The entire public key string that was
+ uploaded. Embedded into the root user's ``authorized_keys`` file if you
+ include this key during Droplet creation. Required.
+ "fingerprint": "str", # Optional. A unique identifier that
+ differentiates this key from other keys using a format that SSH recognizes.
+ The fingerprint is created when the key is added to your account.
+ "id": 0 # Optional. A unique identification number for this key. Can
+ be used to embed a specific SSH key into a Droplet.
}
}
- # response body for status code(s): 404
- response == {
- "id": "str", # A short identifier corresponding to the HTTP status code
- returned. For example, the ID for a response returning a 404 status code would
- be "not_found.". Required.
- "message": "str", # A message providing additional information about the
- error, including details to help resolve it when possible. Required.
- "request_id": "str" # Optional. Optionally, some endpoints may include a
- request ID that should be provided when reporting bugs or opening support
- tickets to help identify the issue.
- }
"""
@distributed_trace_async
- async def patch(
- self, resource_uuid: str, body: Union[JSON, IO[bytes]], **kwargs: Any
- ) -> JSON:
+ async def create(self, body: Union[JSON, IO[bytes]], **kwargs: Any) -> JSON:
# pylint: disable=line-too-long
- """Update the name for an Add-On Resource.
+ """Create a New SSH Key.
- To change the name of an Add-On Resource, send a PATCH request to
- ``/v2/add-ons/saas/{resource_uuid}``.
- Replace ``{resource_uuid}`` with the UUID of the resource for which you want to change the
- name.
+ To add a new SSH public key to your DigitalOcean account, send a POST request to
+ ``/v2/account/keys``. Set the ``name`` attribute to the name you wish to use and the
+ ``public_key`` attribute to the full public key you are adding.
- :param resource_uuid: The UUID of the add-on resource to rename. Required.
- :type resource_uuid: str
:param body: Is either a JSON type or a IO[bytes] type. Required.
:type body: JSON or IO[bytes]
:return: JSON object
@@ -13806,55 +14488,33 @@ async def patch(
# JSON input template you can fill out and use as your body input.
body = {
- "name": "str" # The new name for the add-on resource. Required.
+ "name": "str", # A human-readable display name for this key, used to easily
+ identify the SSH keys when they are displayed. Required.
+ "public_key": "str", # The entire public key string that was uploaded.
+ Embedded into the root user's ``authorized_keys`` file if you include this key
+ during Droplet creation. Required.
+ "fingerprint": "str", # Optional. A unique identifier that differentiates
+ this key from other keys using a format that SSH recognizes. The fingerprint is
+ created when the key is added to your account.
+ "id": 0 # Optional. A unique identification number for this key. Can be used
+ to embed a specific SSH key into a Droplet.
}
- # response body for status code(s): 200
+ # response body for status code(s): 201
response == {
- "resource": {
- "app_slug": "str", # The slug identifier for the application
- associated with the resource. Required.
- "has_config": bool, # Indicates if the resource has configuration
- values set by the vendor. Required.
- "name": "str", # The name of the addon resource. Required.
- "plan_slug": "str", # The slug identifier for the plan associated
- with the resource. Required.
- "state": "str", # The state the resource is currently in. Required.
- Known values are: "pending", "provisioning", "provisioned", "deprovisioning",
- "deprovisioned", "provisioning-failed", "deprovisioning-failed", and
- "suspended".
- "uuid": "str", # The unique identifier for the addon resource.
- Required.
- "app_name": "str", # Optional. The name of the application
- associated with the resource.
- "message": "str", # Optional. A message related to the resource, if
- applicable.
- "metadata": [
- {
- "name": "str", # The name of the metadata item to be
- set. Required.
- "value": {}
- }
- ],
- "plan_name": "str", # Optional. The name of the plan associated with
- the resource.
- "plan_price_per_month": 0, # Optional. The price of the plan per
- month in US dollars.
- "sso_url": "str" # Optional. The Single Sign-On URL for the
- resource, if applicable.
+ "ssh_key": {
+ "name": "str", # A human-readable display name for this key, used to
+ easily identify the SSH keys when they are displayed. Required.
+ "public_key": "str", # The entire public key string that was
+ uploaded. Embedded into the root user's ``authorized_keys`` file if you
+ include this key during Droplet creation. Required.
+ "fingerprint": "str", # Optional. A unique identifier that
+ differentiates this key from other keys using a format that SSH recognizes.
+ The fingerprint is created when the key is added to your account.
+ "id": 0 # Optional. A unique identification number for this key. Can
+ be used to embed a specific SSH key into a Droplet.
}
}
- # response body for status code(s): 404
- response == {
- "id": "str", # A short identifier corresponding to the HTTP status code
- returned. For example, the ID for a response returning a 404 status code would
- be "not_found.". Required.
- "message": "str", # A message providing additional information about the
- error, including details to help resolve it when possible. Required.
- "request_id": "str" # Optional. Optionally, some endpoints may include a
- request ID that should be provided when reporting bugs or opening support
- tickets to help identify the issue.
- }
"""
error_map: MutableMapping[int, Type[HttpResponseError]] = {
404: ResourceNotFoundError,
@@ -13885,8 +14545,7 @@ async def patch(
else:
_json = body
- _request = build_addons_patch_request(
- resource_uuid=resource_uuid,
+ _request = build_ssh_keys_create_request(
content_type=content_type,
json=_json,
content=_content,
@@ -13904,6 +14563,113 @@ async def patch(
response = pipeline_response.http_response
+ if response.status_code not in [201]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+ @distributed_trace_async
+ async def get(self, ssh_key_identifier: JSON, **kwargs: Any) -> JSON:
+ # pylint: disable=line-too-long
+ """Retrieve an Existing SSH Key.
+
+ To get information about a key, send a GET request to ``/v2/account/keys/$KEY_ID`` or
+ ``/v2/account/keys/$KEY_FINGERPRINT``.
+ The response will be a JSON object with the key ``ssh_key`` and value an ssh_key object which
+ contains the standard ssh_key attributes.
+
+ :param ssh_key_identifier: Either the ID or the fingerprint of an existing SSH key. Required.
+ :type ssh_key_identifier: JSON
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 200
+ response == {
+ "ssh_key": {
+ "name": "str", # A human-readable display name for this key, used to
+ easily identify the SSH keys when they are displayed. Required.
+ "public_key": "str", # The entire public key string that was
+ uploaded. Embedded into the root user's ``authorized_keys`` file if you
+ include this key during Droplet creation. Required.
+ "fingerprint": "str", # Optional. A unique identifier that
+ differentiates this key from other keys using a format that SSH recognizes.
+ The fingerprint is created when the key is added to your account.
+ "id": 0 # Optional. A unique identification number for this key. Can
+ be used to embed a specific SSH key into a Droplet.
+ }
+ }
+ # response body for status code(s): 404
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = kwargs.pop("headers", {}) or {}
+ _params = kwargs.pop("params", {}) or {}
+
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ _request = build_ssh_keys_get_request(
+ ssh_key_identifier=ssh_key_identifier,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
if response.status_code not in [200, 404]:
if _stream:
await response.read() # Load the body in memory and close the socket
@@ -13949,25 +14715,24 @@ async def patch(
return cast(JSON, deserialized) # type: ignore
@overload
- async def patch_plan(
+ async def update(
self,
- resource_uuid: str,
+ ssh_key_identifier: JSON,
body: JSON,
*,
content_type: str = "application/json",
**kwargs: Any
) -> JSON:
# pylint: disable=line-too-long
- """Update the plan for an Add-On Resource.
+ """Update an SSH Key's Name.
- To change the plan associated with an Add-On Resource, send a PATCH request to
- ``/v2/add-ons/saas/{resource_uuid}/plan``.
- Replace ``{resource_uuid}`` with the UUID of the resource for which you want to change the
- plan.
+ To update the name of an SSH key, send a PUT request to either ``/v2/account/keys/$SSH_KEY_ID``
+ or ``/v2/account/keys/$SSH_KEY_FINGERPRINT``. Set the ``name`` attribute to the new name you
+ want to use.
- :param resource_uuid: The UUID of the add-on resource to update. Required.
- :type resource_uuid: str
- :param body: Required.
+ :param ssh_key_identifier: Either the ID or the fingerprint of an existing SSH key. Required.
+ :type ssh_key_identifier: JSON
+ :param body: Set the ``name`` attribute to the new name you want to use. Required.
:type body: JSON
:keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
Default value is "application/json".
@@ -13981,43 +14746,23 @@ async def patch_plan(
# JSON input template you can fill out and use as your body input.
body = {
- "plan_slug": "str" # The slug identifier for the new plan to apply to the
- add-on resource. Required.
+ "name": "str" # Optional. A human-readable display name for this key, used
+ to easily identify the SSH keys when they are displayed.
}
# response body for status code(s): 200
response == {
- "resource": {
- "app_slug": "str", # The slug identifier for the application
- associated with the resource. Required.
- "has_config": bool, # Indicates if the resource has configuration
- values set by the vendor. Required.
- "name": "str", # The name of the addon resource. Required.
- "plan_slug": "str", # The slug identifier for the plan associated
- with the resource. Required.
- "state": "str", # The state the resource is currently in. Required.
- Known values are: "pending", "provisioning", "provisioned", "deprovisioning",
- "deprovisioned", "provisioning-failed", "deprovisioning-failed", and
- "suspended".
- "uuid": "str", # The unique identifier for the addon resource.
- Required.
- "app_name": "str", # Optional. The name of the application
- associated with the resource.
- "message": "str", # Optional. A message related to the resource, if
- applicable.
- "metadata": [
- {
- "name": "str", # The name of the metadata item to be
- set. Required.
- "value": {}
- }
- ],
- "plan_name": "str", # Optional. The name of the plan associated with
- the resource.
- "plan_price_per_month": 0, # Optional. The price of the plan per
- month in US dollars.
- "sso_url": "str" # Optional. The Single Sign-On URL for the
- resource, if applicable.
+ "ssh_key": {
+ "name": "str", # A human-readable display name for this key, used to
+ easily identify the SSH keys when they are displayed. Required.
+ "public_key": "str", # The entire public key string that was
+ uploaded. Embedded into the root user's ``authorized_keys`` file if you
+ include this key during Droplet creation. Required.
+ "fingerprint": "str", # Optional. A unique identifier that
+ differentiates this key from other keys using a format that SSH recognizes.
+ The fingerprint is created when the key is added to your account.
+ "id": 0 # Optional. A unique identification number for this key. Can
+ be used to embed a specific SSH key into a Droplet.
}
}
# response body for status code(s): 404
@@ -14034,25 +14779,24 @@ async def patch_plan(
"""
@overload
- async def patch_plan(
+ async def update(
self,
- resource_uuid: str,
+ ssh_key_identifier: JSON,
body: IO[bytes],
*,
content_type: str = "application/json",
**kwargs: Any
) -> JSON:
# pylint: disable=line-too-long
- """Update the plan for an Add-On Resource.
+ """Update an SSH Key's Name.
- To change the plan associated with an Add-On Resource, send a PATCH request to
- ``/v2/add-ons/saas/{resource_uuid}/plan``.
- Replace ``{resource_uuid}`` with the UUID of the resource for which you want to change the
- plan.
+ To update the name of an SSH key, send a PUT request to either ``/v2/account/keys/$SSH_KEY_ID``
+ or ``/v2/account/keys/$SSH_KEY_FINGERPRINT``. Set the ``name`` attribute to the new name you
+ want to use.
- :param resource_uuid: The UUID of the add-on resource to update. Required.
- :type resource_uuid: str
- :param body: Required.
+ :param ssh_key_identifier: Either the ID or the fingerprint of an existing SSH key. Required.
+ :type ssh_key_identifier: JSON
+ :param body: Set the ``name`` attribute to the new name you want to use. Required.
:type body: IO[bytes]
:keyword content_type: Body Parameter content-type. Content type parameter for binary body.
Default value is "application/json".
@@ -14066,37 +14810,17 @@ async def patch_plan(
# response body for status code(s): 200
response == {
- "resource": {
- "app_slug": "str", # The slug identifier for the application
- associated with the resource. Required.
- "has_config": bool, # Indicates if the resource has configuration
- values set by the vendor. Required.
- "name": "str", # The name of the addon resource. Required.
- "plan_slug": "str", # The slug identifier for the plan associated
- with the resource. Required.
- "state": "str", # The state the resource is currently in. Required.
- Known values are: "pending", "provisioning", "provisioned", "deprovisioning",
- "deprovisioned", "provisioning-failed", "deprovisioning-failed", and
- "suspended".
- "uuid": "str", # The unique identifier for the addon resource.
- Required.
- "app_name": "str", # Optional. The name of the application
- associated with the resource.
- "message": "str", # Optional. A message related to the resource, if
- applicable.
- "metadata": [
- {
- "name": "str", # The name of the metadata item to be
- set. Required.
- "value": {}
- }
- ],
- "plan_name": "str", # Optional. The name of the plan associated with
- the resource.
- "plan_price_per_month": 0, # Optional. The price of the plan per
- month in US dollars.
- "sso_url": "str" # Optional. The Single Sign-On URL for the
- resource, if applicable.
+ "ssh_key": {
+ "name": "str", # A human-readable display name for this key, used to
+ easily identify the SSH keys when they are displayed. Required.
+ "public_key": "str", # The entire public key string that was
+ uploaded. Embedded into the root user's ``authorized_keys`` file if you
+ include this key during Droplet creation. Required.
+ "fingerprint": "str", # Optional. A unique identifier that
+ differentiates this key from other keys using a format that SSH recognizes.
+ The fingerprint is created when the key is added to your account.
+ "id": 0 # Optional. A unique identification number for this key. Can
+ be used to embed a specific SSH key into a Droplet.
}
}
# response body for status code(s): 404
@@ -14113,20 +14837,20 @@ async def patch_plan(
"""
@distributed_trace_async
- async def patch_plan(
- self, resource_uuid: str, body: Union[JSON, IO[bytes]], **kwargs: Any
+ async def update(
+ self, ssh_key_identifier: JSON, body: Union[JSON, IO[bytes]], **kwargs: Any
) -> JSON:
# pylint: disable=line-too-long
- """Update the plan for an Add-On Resource.
+ """Update an SSH Key's Name.
- To change the plan associated with an Add-On Resource, send a PATCH request to
- ``/v2/add-ons/saas/{resource_uuid}/plan``.
- Replace ``{resource_uuid}`` with the UUID of the resource for which you want to change the
- plan.
+ To update the name of an SSH key, send a PUT request to either ``/v2/account/keys/$SSH_KEY_ID``
+ or ``/v2/account/keys/$SSH_KEY_FINGERPRINT``. Set the ``name`` attribute to the new name you
+ want to use.
- :param resource_uuid: The UUID of the add-on resource to update. Required.
- :type resource_uuid: str
- :param body: Is either a JSON type or a IO[bytes] type. Required.
+ :param ssh_key_identifier: Either the ID or the fingerprint of an existing SSH key. Required.
+ :type ssh_key_identifier: JSON
+ :param body: Set the ``name`` attribute to the new name you want to use. Is either a JSON type
+ or a IO[bytes] type. Required.
:type body: JSON or IO[bytes]
:return: JSON object
:rtype: JSON
@@ -14137,43 +14861,23 @@ async def patch_plan(
# JSON input template you can fill out and use as your body input.
body = {
- "plan_slug": "str" # The slug identifier for the new plan to apply to the
- add-on resource. Required.
+ "name": "str" # Optional. A human-readable display name for this key, used
+ to easily identify the SSH keys when they are displayed.
}
# response body for status code(s): 200
response == {
- "resource": {
- "app_slug": "str", # The slug identifier for the application
- associated with the resource. Required.
- "has_config": bool, # Indicates if the resource has configuration
- values set by the vendor. Required.
- "name": "str", # The name of the addon resource. Required.
- "plan_slug": "str", # The slug identifier for the plan associated
- with the resource. Required.
- "state": "str", # The state the resource is currently in. Required.
- Known values are: "pending", "provisioning", "provisioned", "deprovisioning",
- "deprovisioned", "provisioning-failed", "deprovisioning-failed", and
- "suspended".
- "uuid": "str", # The unique identifier for the addon resource.
- Required.
- "app_name": "str", # Optional. The name of the application
- associated with the resource.
- "message": "str", # Optional. A message related to the resource, if
- applicable.
- "metadata": [
- {
- "name": "str", # The name of the metadata item to be
- set. Required.
- "value": {}
- }
- ],
- "plan_name": "str", # Optional. The name of the plan associated with
- the resource.
- "plan_price_per_month": 0, # Optional. The price of the plan per
- month in US dollars.
- "sso_url": "str" # Optional. The Single Sign-On URL for the
- resource, if applicable.
+ "ssh_key": {
+ "name": "str", # A human-readable display name for this key, used to
+ easily identify the SSH keys when they are displayed. Required.
+ "public_key": "str", # The entire public key string that was
+ uploaded. Embedded into the root user's ``authorized_keys`` file if you
+ include this key during Droplet creation. Required.
+ "fingerprint": "str", # Optional. A unique identifier that
+ differentiates this key from other keys using a format that SSH recognizes.
+ The fingerprint is created when the key is added to your account.
+ "id": 0 # Optional. A unique identification number for this key. Can
+ be used to embed a specific SSH key into a Droplet.
}
}
# response body for status code(s): 404
@@ -14217,8 +14921,8 @@ async def patch_plan(
else:
_json = body
- _request = build_addons_patch_plan_request(
- resource_uuid=resource_uuid,
+ _request = build_ssh_keys_update_request(
+ ssh_key_identifier=ssh_key_identifier,
content_type=content_type,
json=_json,
content=_content,
@@ -14280,604 +14984,19379 @@ async def patch_plan(
return cast(JSON, deserialized) # type: ignore
-
-class AppsOperations: # pylint: disable=too-many-public-methods
- """
- .. warning::
- **DO NOT** instantiate this class directly.
-
- Instead, you should access the following operations through
- :class:`~pydo.aio.GeneratedClient`'s
- :attr:`apps` attribute.
- """
-
- def __init__(self, *args, **kwargs) -> None:
- input_args = list(args)
- self._client = input_args.pop(0) if input_args else kwargs.pop("client")
- self._config = input_args.pop(0) if input_args else kwargs.pop("config")
- self._serialize = input_args.pop(0) if input_args else kwargs.pop("serializer")
- self._deserialize = (
- input_args.pop(0) if input_args else kwargs.pop("deserializer")
- )
-
@distributed_trace_async
- async def list(
- self,
- *,
- page: int = 1,
- per_page: int = 20,
- with_projects: Optional[bool] = None,
- **kwargs: Any
- ) -> JSON:
+ async def delete(self, ssh_key_identifier: JSON, **kwargs: Any) -> Optional[JSON]:
# pylint: disable=line-too-long
- """List All Apps.
+ """Delete an SSH Key.
- List all apps on your account. Information about the current active deployment as well as any
- in progress ones will also be included for each app.
+ To destroy a public SSH key that you have in your account, send a DELETE request to
+ ``/v2/account/keys/$KEY_ID`` or ``/v2/account/keys/$KEY_FINGERPRINT``.
+ A 204 status will be returned, indicating that the action was successful and that the response
+ body is empty.
- :keyword page: Which 'page' of paginated results to return. Default value is 1.
- :paramtype page: int
- :keyword per_page: Number of items returned per page. Default value is 20.
- :paramtype per_page: int
- :keyword with_projects: Whether the project_id of listed apps should be fetched and included.
- Default value is None.
- :paramtype with_projects: bool
- :return: JSON object
- :rtype: JSON
+ :param ssh_key_identifier: Either the ID or the fingerprint of an existing SSH key. Required.
+ :type ssh_key_identifier: JSON
+ :return: JSON object or None
+ :rtype: JSON or None
:raises ~azure.core.exceptions.HttpResponseError:
Example:
.. code-block:: python
- # response body for status code(s): 200
+ # response body for status code(s): 404
response == {
- "meta": {
- "total": 0 # Optional. Number of objects returned by the request.
- },
- "apps": [
- {
- "spec": {
- "name": "str", # The name of the app. Must be unique
- across all apps in the same account. Required.
- "databases": [
- {
- "name": "str", # The database's
- name. The name must be unique across all components within
- the same app and cannot use capital letters. Required.
- "cluster_name": "str", # Optional.
- The name of the underlying DigitalOcean DBaaS cluster. This
- is required for production databases. For dev databases, if
- cluster_name is not set, a new cluster will be provisioned.
- "db_name": "str", # Optional. The
- name of the MySQL or PostgreSQL database to configure.
- "db_user": "str", # Optional. The
- name of the MySQL or PostgreSQL user to configure.
- "engine": "UNSET", # Optional.
- Default value is "UNSET". * MYSQL: MySQL * PG: PostgreSQL *
- REDIS: Caching * MONGODB: MongoDB * KAFKA: Kafka *
- OPENSEARCH: OpenSearch * VALKEY: ValKey. Known values are:
- "UNSET", "MYSQL", "PG", "REDIS", "MONGODB", "KAFKA",
- "OPENSEARCH", and "VALKEY".
- "production": bool, # Optional.
- Whether this is a production or dev database.
- "version": "str" # Optional. The
- version of the database engine.
- }
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = kwargs.pop("headers", {}) or {}
+ _params = kwargs.pop("params", {}) or {}
+
+ cls: ClsType[Optional[JSON]] = kwargs.pop("cls", None)
+
+ _request = build_ssh_keys_delete_request(
+ ssh_key_identifier=ssh_key_identifier,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [204, 404]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ deserialized = None
+ response_headers = {}
+ if response.status_code == 204:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, deserialized, response_headers) # type: ignore
+
+ return deserialized # type: ignore
+
+
+class ActionsOperations:
+ """
+ .. warning::
+ **DO NOT** instantiate this class directly.
+
+ Instead, you should access the following operations through
+ :class:`~pydo.aio.GeneratedClient`'s
+ :attr:`actions` attribute.
+ """
+
+ def __init__(self, *args, **kwargs) -> None:
+ input_args = list(args)
+ self._client = input_args.pop(0) if input_args else kwargs.pop("client")
+ self._config = input_args.pop(0) if input_args else kwargs.pop("config")
+ self._serialize = input_args.pop(0) if input_args else kwargs.pop("serializer")
+ self._deserialize = (
+ input_args.pop(0) if input_args else kwargs.pop("deserializer")
+ )
+
+ @distributed_trace_async
+ async def list(self, *, per_page: int = 20, page: int = 1, **kwargs: Any) -> JSON:
+ # pylint: disable=line-too-long
+ """List All Actions.
+
+ This will be the entire list of actions taken on your account, so it will be quite large. As
+ with any large collection returned by the API, the results will be paginated with only 20 on
+ each page by default.
+
+ :keyword per_page: Number of items returned per page. Default value is 20.
+ :paramtype per_page: int
+ :keyword page: Which 'page' of paginated results to return. Default value is 1.
+ :paramtype page: int
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 200
+ response == {
+ "meta": {
+ "total": 0 # Optional. Number of objects returned by the request.
+ },
+ "actions": [
+ {
+ "completed_at": "2020-02-20 00:00:00", # Optional. A time
+ value given in ISO8601 combined date and time format that represents when
+ the action was completed.
+ "id": 0, # Optional. A unique numeric ID that can be used to
+ identify and reference an action.
+ "region": {
+ "available": bool, # This is a boolean value that
+ represents whether new Droplets can be created in this region.
+ Required.
+ "features": [
+ "str" # This attribute is set to an array
+ which contains features available in this region. Required.
],
- "disable_edge_cache": False, # Optional. Default
- value is False. .. role:: raw-html-m2r(raw) :format: html If set
- to ``true``"" , the app will **not** be cached at the edge (CDN).
- Enable this option if you want to manage CDN configuration
- yourself"u2014whether by using an external CDN provider or by
- handling static content and caching within your app. This setting is
- also recommended for apps that require real-time data or serve
- dynamic content, such as those using Server-Sent Events (SSE) over
- GET, or hosting an MCP (Model Context Protocol) Server that utilizes
- SSE."" :raw-html-m2r:` ` **Note:** This feature is not available
- for static site components."" :raw-html-m2r:` ` For more
- information, see `Disable CDN Cache
- `_.
- "disable_email_obfuscation": False, # Optional.
- Default value is False. If set to ``true``"" , email addresses in the
- app will not be obfuscated. This is useful for apps that require
- email addresses to be visible (in the HTML markup).
- "domains": [
- {
- "domain": "str", # The hostname for
- the domain. Required.
- "minimum_tls_version": "str", #
- Optional. The minimum version of TLS a client application can
- use to access resources for the domain. Must be one of the
- following values wrapped within quotations: ``"1.2"`` or
- ``"1.3"``. Known values are: "1.2" and "1.3".
- "type": "UNSPECIFIED", # Optional.
- Default value is "UNSPECIFIED". * DEFAULT: The default
- ``.ondigitalocean.app`` domain assigned to this app *
- PRIMARY: The primary domain for this app that is displayed as
- the default in the control panel, used in bindable
- environment variables, and any other places that reference an
- app's live URL. Only one domain may be set as primary. *
- ALIAS: A non-primary domain. Known values are: "UNSPECIFIED",
- "DEFAULT", "PRIMARY", and "ALIAS".
- "wildcard": bool, # Optional.
- Indicates whether the domain includes all sub-domains, in
- addition to the given domain.
- "zone": "str" # Optional. Optional.
- If the domain uses DigitalOcean DNS and you would like App
- Platform to automatically manage it for you, set this to the
- name of the domain on your account. For example, If the
- domain you are adding is ``app.domain.com``"" , the zone
- could be ``domain.com``.
- }
+ "name": "str", # The display name of the region.
+ This will be a full name that is used in the control panel and other
+ interfaces. Required.
+ "sizes": [
+ "str" # This attribute is set to an array
+ which contains the identifying slugs for the sizes available in
+ this region. sizes:read is required to view. Required.
],
- "egress": {
- "type": "AUTOASSIGN" # Optional. Default
- value is "AUTOASSIGN". The app egress type. Known values are:
- "AUTOASSIGN" and "DEDICATED_IP".
- },
- "enhanced_threat_control_enabled": False, #
- Optional. Default value is False. If set to ``true``"" , suspicious
- requests will go through additional security checks to help mitigate
- layer 7 DDoS attacks.
- "functions": [
- {
- "name": "str", # The name. Must be
- unique across all components within the same app. Required.
- "alerts": [
- {
- "disabled": bool, #
- Optional. Is the alert disabled?.
- "operator":
- "UNSPECIFIED_OPERATOR", # Optional. Default value is
- "UNSPECIFIED_OPERATOR". Known values are:
- "UNSPECIFIED_OPERATOR", "GREATER_THAN", and
- "LESS_THAN".
- "rule":
- "UNSPECIFIED_RULE", # Optional. Default value is
- "UNSPECIFIED_RULE". Known values are:
- "UNSPECIFIED_RULE", "CPU_UTILIZATION",
- "MEM_UTILIZATION", "RESTART_COUNT",
- "DEPLOYMENT_FAILED", "DEPLOYMENT_LIVE",
- "DOMAIN_FAILED", "DOMAIN_LIVE", "AUTOSCALE_FAILED",
- "AUTOSCALE_SUCCEEDED", "FUNCTIONS_ACTIVATION_COUNT",
- "FUNCTIONS_AVERAGE_DURATION_MS",
- "FUNCTIONS_ERROR_RATE_PER_MINUTE",
- "FUNCTIONS_AVERAGE_WAIT_TIME_MS",
- "FUNCTIONS_ERROR_COUNT",
- "FUNCTIONS_GB_RATE_PER_SECOND",
- "REQUESTS_PER_SECOND", and "REQUEST_DURATION_P95_MS".
- "value": 0.0, #
- Optional. Threshold value for alert.
- "window":
- "UNSPECIFIED_WINDOW" # Optional. Default value is
- "UNSPECIFIED_WINDOW". Known values are:
- "UNSPECIFIED_WINDOW", "FIVE_MINUTES", "TEN_MINUTES",
- "THIRTY_MINUTES", and "ONE_HOUR".
- }
- ],
- "bitbucket": {
- "branch": "str", # Optional.
- The name of the branch to use.
- "deploy_on_push": bool, #
- Optional. Whether to automatically deploy new commits
- made to the repo.
- "repo": "str" # Optional.
- The name of the repo in the format owner/repo. Example:
- ``digitalocean/sample-golang``.
- },
- "cors": {
- "allow_credentials": bool, #
- Optional. Whether browsers should expose the response to
- the client-side JavaScript code when the request"u2019s
- credentials mode is include. This configures the
- ``Access-Control-Allow-Credentials`` header.
- "allow_headers": [
- "str" # Optional.
- The set of allowed HTTP request headers. This
- configures the ``Access-Control-Allow-Headers``
- header.
- ],
- "allow_methods": [
- "str" # Optional.
- The set of allowed HTTP methods. This configures the
- ``Access-Control-Allow-Methods`` header.
- ],
- "allow_origins": [
+ "slug": "str" # A human-readable string that is used
+ as a unique identifier for each region. Required.
+ },
+ "region_slug": "str", # Optional. A human-readable string
+ that is used as a unique identifier for each region.
+ "resource_id": 0, # Optional. A unique identifier for the
+ resource that the action is associated with.
+ "resource_type": "str", # Optional. The type of resource
+ that the action is associated with.
+ "started_at": "2020-02-20 00:00:00", # Optional. A time
+ value given in ISO8601 combined date and time format that represents when
+ the action was initiated.
+ "status": "in-progress", # Optional. Default value is
+ "in-progress". The current status of the action. This can be
+ "in-progress", "completed", or "errored". Known values are:
+ "in-progress", "completed", and "errored".
+ "type": "str" # Optional. This is the type of action that
+ the object represents. For example, this could be "transfer" to represent
+ the state of an image transfer action.
+ }
+ ],
+ "links": {
+ "pages": {}
+ }
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = kwargs.pop("headers", {}) or {}
+ _params = kwargs.pop("params", {}) or {}
+
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ _request = build_actions_list_request(
+ per_page=per_page,
+ page=page,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+ @distributed_trace_async
+ async def get(self, action_id: int, **kwargs: Any) -> JSON:
+ # pylint: disable=line-too-long
+ """Retrieve an Existing Action.
+
+ To retrieve a specific action object, send a GET request to ``/v2/actions/$ACTION_ID``.
+
+ :param action_id: A unique numeric ID that can be used to identify and reference an action.
+ Required.
+ :type action_id: int
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 200
+ response == {
+ "action": {
+ "completed_at": "2020-02-20 00:00:00", # Optional. A time value
+ given in ISO8601 combined date and time format that represents when the
+ action was completed.
+ "id": 0, # Optional. A unique numeric ID that can be used to
+ identify and reference an action.
+ "region": {
+ "available": bool, # This is a boolean value that represents
+ whether new Droplets can be created in this region. Required.
+ "features": [
+ "str" # This attribute is set to an array which
+ contains features available in this region. Required.
+ ],
+ "name": "str", # The display name of the region. This will
+ be a full name that is used in the control panel and other interfaces.
+ Required.
+ "sizes": [
+ "str" # This attribute is set to an array which
+ contains the identifying slugs for the sizes available in this
+ region. sizes:read is required to view. Required.
+ ],
+ "slug": "str" # A human-readable string that is used as a
+ unique identifier for each region. Required.
+ },
+ "region_slug": "str", # Optional. A human-readable string that is
+ used as a unique identifier for each region.
+ "resource_id": 0, # Optional. A unique identifier for the resource
+ that the action is associated with.
+ "resource_type": "str", # Optional. The type of resource that the
+ action is associated with.
+ "started_at": "2020-02-20 00:00:00", # Optional. A time value given
+ in ISO8601 combined date and time format that represents when the action was
+ initiated.
+ "status": "in-progress", # Optional. Default value is "in-progress".
+ The current status of the action. This can be "in-progress", "completed", or
+ "errored". Known values are: "in-progress", "completed", and "errored".
+ "type": "str" # Optional. This is the type of action that the object
+ represents. For example, this could be "transfer" to represent the state of
+ an image transfer action.
+ }
+ }
+ # response body for status code(s): 404
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = kwargs.pop("headers", {}) or {}
+ _params = kwargs.pop("params", {}) or {}
+
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ _request = build_actions_get_request(
+ action_id=action_id,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 404]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ if response.status_code == 200:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+
+class AddonsOperations:
+ """
+ .. warning::
+ **DO NOT** instantiate this class directly.
+
+ Instead, you should access the following operations through
+ :class:`~pydo.aio.GeneratedClient`'s
+ :attr:`addons` attribute.
+ """
+
+ def __init__(self, *args, **kwargs) -> None:
+ input_args = list(args)
+ self._client = input_args.pop(0) if input_args else kwargs.pop("client")
+ self._config = input_args.pop(0) if input_args else kwargs.pop("config")
+ self._serialize = input_args.pop(0) if input_args else kwargs.pop("serializer")
+ self._deserialize = (
+ input_args.pop(0) if input_args else kwargs.pop("deserializer")
+ )
+
+ @distributed_trace_async
+ async def get_app(self, **kwargs: Any) -> JSON:
+ # pylint: disable=line-too-long
+ """List Available Add-On Applications.
+
+ To fetch details of all available Add-On Applications, send a GET request to
+ ``/v2/add-ons/apps``.
+
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 200
+ response == {
+ "apps": [
+ {
+ "app_slug": "str", # The slug identifier for the application
+ associated with the resource. Required.
+ "eula": "str", # The End User License Agreement URL for the
+ resource. Required.
+ "plans": [
+ {
+ "active": bool, # Indicates if the plan is
+ currently active. Required.
+ "app_id": 0, # ID of the app associated with
+ this plan. Required.
+ "available": bool, # Indicates if the plan
+ is available for selection. Required.
+ "by_default": bool, # Indicates if this plan
+ is the default option for the app. Required.
+ "created_at": "2020-02-20 00:00:00", #
+ Timestamp when the plan was created. Required.
+ "display_name": "str", # Display name for a
+ given plan. Required.
+ "id": 0, # ID of a given plan. Required.
+ "price_per_month": 0, # Price of a month's
+ usage of the plan in US dollars. Required.
+ "slug": "str", # Slug identifier for the
+ plan. Required.
+ "state": "str", # Current state of the plan.
+ Required. Known values are: "unknown", "draft", "in_review",
+ "approved", "suspended", and "archived".
+ "updated_at": "2020-02-20 00:00:00", #
+ Timestamp when the plan was last updated. Required.
+ "uuid": "str", # Unique identifier for the
+ plan. Required.
+ "description": "str", # Optional.
+ Description of an app plan.
+ "dimensions": [
+ {
+ "display_name": "str", #
+ Display name for the dimension. Required.
+ "feature_name": "str", #
+ Name of the feature associated with the dimension.
+ Required.
+ "id": 0, # Unique identifier
+ for the dimension. Required.
+ "sku": "str", # Unique
+ string identifier for the dimension, tied to a price.
+ Required.
+ "slug": "str", # Slug
+ identifier for the dimension. Required.
+ "volumes": [
{
- "exact":
- "str", # Optional. Exact string match. Only 1 of
- ``exact``"" , ``prefix``"" , or ``regex`` must be
- set. An empty string is a valid value and will be
- serialized explicitly rather than being omitted
- from the payload.
- "prefix":
- "str", # Optional. Prefix-based match. Only 1 of
- ``exact``"" , ``prefix``"" , or ``regex`` must be
- set.
- "regex":
- "str" # Optional. RE2 style regex-based match.
- Only 1 of ``exact``"" , ``prefix``"" , or
- ``regex`` must be set. For more information about
- RE2 syntax, see:
- https://github.com/google/re2/wiki/Syntax.
- }
- ],
- "expose_headers": [
- "str" # Optional.
- The set of HTTP response headers that browsers are
- allowed to access. This configures the
- ``Access-Control-Expose-Headers`` header.
- ],
- "max_age": "str" # Optional.
- An optional duration specifying how long browsers can
- cache the results of a preflight request. This configures
- the ``Access-Control-Max-Age`` header.
- },
- "envs": [
- {
- "key": "str", # The
- variable name. Required.
- "scope":
- "RUN_AND_BUILD_TIME", # Optional. Default value is
- "RUN_AND_BUILD_TIME". * RUN_TIME: Made available only
- at run-time * BUILD_TIME: Made available only at
- build-time * RUN_AND_BUILD_TIME: Made available at
- both build and run-time. Known values are: "UNSET",
- "RUN_TIME", "BUILD_TIME", and "RUN_AND_BUILD_TIME".
- "type": "GENERAL", #
- Optional. Default value is "GENERAL". * GENERAL: A
- plain-text environment variable * SECRET: A secret
- encrypted environment variable. Known values are:
- "GENERAL" and "SECRET".
- "value": "str" #
- Optional. The value. If the type is ``SECRET``"" ,
- the value will be encrypted on first submission. On
- following submissions, the encrypted value should be
- used.
- }
- ],
- "git": {
- "branch": "str", # Optional.
- The name of the branch to use.
- "repo_clone_url": "str" #
- Optional. The clone URL of the repo. Example:
- ``https://github.com/digitalocean/sample-golang.git``.
- },
- "github": {
- "branch": "str", # Optional.
- The name of the branch to use.
- "deploy_on_push": bool, #
- Optional. Whether to automatically deploy new commits
- made to the repo.
- "repo": "str" # Optional.
- The name of the repo in the format owner/repo. Example:
- ``digitalocean/sample-golang``.
- },
- "gitlab": {
- "branch": "str", # Optional.
- The name of the branch to use.
- "deploy_on_push": bool, #
- Optional. Whether to automatically deploy new commits
- made to the repo.
- "repo": "str" # Optional.
- The name of the repo in the format owner/repo. Example:
- ``digitalocean/sample-golang``.
- },
- "log_destinations": [
- {
- "name": "str", #
- Required.
- "datadog": {
- "api_key":
- "str", # Datadog API key. Required.
- "endpoint":
- "str" # Optional. Datadog HTTP log intake
- endpoint.
- },
- "logtail": {
- "token":
- "str" # Optional. Logtail token.
- },
- "open_search": {
- "basic_auth":
- {
- "password": "str", # Optional. Password for
- user defined in User. Is required when
- ``endpoint`` is set. Cannot be set if using a
- DigitalOcean DBaaS OpenSearch cluster.
- "user": "str" # Optional. Username to
- authenticate with. Only required when
- ``endpoint`` is set. Defaults to ``doadmin``
- when ``cluster_name`` is set.
- },
- "cluster_name": "str", # Optional. The name of a
- DigitalOcean DBaaS OpenSearch cluster to use as a
- log forwarding destination. Cannot be specified
- if ``endpoint`` is also specified.
- "endpoint":
- "str", # Optional. OpenSearch API Endpoint. Only
- HTTPS is supported. Format:
- https://:code:``::code:``. Cannot be
- specified if ``cluster_name`` is also specified.
- "index_name":
- "logs" # Optional. Default value is "logs". The
- index name to use for the logs. If not set, the
- default index name is "logs".
- },
- "papertrail": {
- "endpoint":
- "str" # Papertrail syslog endpoint. Required.
+ "id": 0, #
+ Unique identifier for the addon. Required.
+ "low_volume":
+ 0, # The minimum volume for the volume pricing
+ tier. Required.
+ "max_volume":
+ 0, # The maximum volume for the volume pricing
+ tier. Required.
+ "price_per_unit": "str" # The price per unit for
+ the volume tier in US dollars. Required.
}
- }
- ],
- "routes": [
- {
- "path": "str", #
- Optional. (Deprecated - Use Ingress Rules instead).
- An HTTP path prefix. Paths must start with / and must
- be unique across all components within an app.
- "preserve_path_prefix": bool # Optional. An optional
- flag to preserve the path that is forwarded to the
- backend service. By default, the HTTP request path
- will be trimmed from the left when forwarded to the
- component. For example, a component with
- ``path=/api`` will have requests to ``/api/list``
- trimmed to ``/list``. If this value is ``true``"" ,
- the path will remain ``/api/list``.
- }
- ],
- "source_dir": "str" # Optional. An
- optional path to the working directory to use for the build.
- For Dockerfile builds, this will be used as the build
- context. Must be relative to the root of the repo.
- }
- ],
- "ingress": {
- "custom_error_page_url": "str", # Optional.
- Optional HTTPS URL of a custom error page to display when the app
- is unreachable. The page is shown in a full-viewport iframe. The
- target must allow framing: avoid ``X-Frame-Options: DENY`` and a
- restrictive ``Content-Security-Policy`` ``frame-ancestors`` that
- blocks the platform. If omitted, the default platform error page
- is used.
- "rules": [
+ ]
+ }
+ ],
+ "features": [
{
- "component": {
- "name": "str", # The
- name of the component to route to. Required.
- "preserve_path_prefix": "str", # Optional. An
- optional flag to preserve the path that is forwarded
- to the backend service. By default, the HTTP request
- path will be trimmed from the left when forwarded to
- the component. For example, a component with
- ``path=/api`` will have requests to ``/api/list``
- trimmed to ``/list``. If this value is ``true``"" ,
- the path will remain ``/api/list``. Note: this is not
- applicable for Functions Components and is mutually
- exclusive with ``rewrite``.
- "rewrite": "str" #
- Optional. An optional field that will rewrite the
- path of the component to be what is specified here.
- By default, the HTTP request path will be trimmed
- from the left when forwarded to the component. For
- example, a component with ``path=/api`` will have
- requests to ``/api/list`` trimmed to ``/list``. If
- you specified the rewrite to be ``/v1/``"" , requests
- to ``/api/list`` would be rewritten to ``/v1/list``.
- Note: this is mutually exclusive with
- ``preserve_path_prefix``.
- },
- "cors": {
- "allow_credentials":
- bool, # Optional. Whether browsers should expose the
- response to the client-side JavaScript code when the
- request"u2019s credentials mode is include. This
- configures the ``Access-Control-Allow-Credentials``
- header.
- "allow_headers": [
- "str" #
- Optional. The set of allowed HTTP request
- headers. This configures the
- ``Access-Control-Allow-Headers`` header.
- ],
- "allow_methods": [
- "str" #
- Optional. The set of allowed HTTP methods. This
- configures the ``Access-Control-Allow-Methods``
- header.
- ],
- "allow_origins": [
- {
- "exact": "str", # Optional. Exact string
- match. Only 1 of ``exact``"" , ``prefix``"" ,
- or ``regex`` must be set. An empty string is
- a valid value and will be serialized
- explicitly rather than being omitted from the
- payload.
- "prefix": "str", # Optional. Prefix-based
- match. Only 1 of ``exact``"" , ``prefix``"" ,
- or ``regex`` must be set.
- "regex": "str" # Optional. RE2 style
- regex-based match. Only 1 of ``exact``"" ,
- ``prefix``"" , or ``regex`` must be set. For
- more information about RE2 syntax, see:
- https://github.com/google/re2/wiki/Syntax.
- }
- ],
- "expose_headers": [
- "str" #
- Optional. The set of HTTP response headers that
- browsers are allowed to access. This configures
- the ``Access-Control-Expose-Headers`` header.
- ],
- "max_age": "str" #
- Optional. An optional duration specifying how long
- browsers can cache the results of a preflight
- request. This configures the
- ``Access-Control-Max-Age`` header.
- },
- "match": {
- "authority": {
- "exact":
- "str" # Exact string match. An empty string is a
- valid value and will be serialized explicitly
- rather than being omitted from the payload.
- Required.
- },
- "path": {
- "prefix":
- "str" # Prefix-based match. For example,
- ``/api`` will match ``/api``"" , ``/api/``"" ,
- and any nested paths such as
- ``/api/v1/endpoint``. Required.
- }
- },
- "redirect": {
- "authority": "str",
- # Optional. The authority/host to redirect to. This
- can be a hostname or IP address. Note: use ``port``
- to set the port.
- "port": 0, #
- Optional. The port to redirect to.
- "redirect_code": 0,
- # Optional. The redirect code to use. Defaults to
- ``302``. Supported values are 300, 301, 302, 303,
- 304, 307, 308.
- "scheme": "str", #
- Optional. The scheme to redirect to. Supported values
- are ``http`` or ``https``. Default: ``https``.
- "uri": "str" #
- Optional. An optional URI path to redirect to. Note:
- if this is specified the whole URI of the original
- request will be overwritten to this value,
- irrespective of the original request URI being
- matched.
- }
+ "created_at": "2020-02-20
+ 00:00:00", # Timestamp when the feature was created.
+ Required.
+ "id": 0, # Unique identifier
+ for the app feature. Required.
+ "name": "str", # Name of the
+ feature. Required.
+ "type": "str", # Feature
+ type, indicating the kind of data it holds. Required.
+ Known values are: "unknown", "string", "boolean", and
+ "allowance".
+ "updated_at": "2020-02-20
+ 00:00:00", # Timestamp when the feature was last
+ updated. Required.
+ "value": {},
+ "unit": "str" # Optional.
+ Unit of measurement for the feature, if applicable. Units
+ apply to allowance features. Known values are:
+ "unit_unknown", "GB", "GIB", "count", "byte", and
+ "byte_second".
}
]
- },
- "jobs": [
- {
- "bitbucket": {
- "branch": "str", # Optional.
- The name of the branch to use.
- "deploy_on_push": bool, #
- Optional. Whether to automatically deploy new commits
- made to the repo.
- "repo": "str" # Optional.
- The name of the repo in the format owner/repo. Example:
- ``digitalocean/sample-golang``.
- },
- "build_command": "str", # Optional.
- An optional build command to run while building this
- component from source.
- "dockerfile_path": "str", #
- Optional. The path to the Dockerfile relative to the root of
- the repo. If set, it will be used to build this component.
- Otherwise, App Platform will attempt to build it using
- buildpacks.
- "environment_slug": "str", #
- Optional. An environment slug describing the type of this
- app. For a full list, please refer to `the product
- documentation
- `_.
- "envs": [
- {
- "key": "str", # The
- variable name. Required.
- "scope":
- "RUN_AND_BUILD_TIME", # Optional. Default value is
- "RUN_AND_BUILD_TIME". * RUN_TIME: Made available only
- at run-time * BUILD_TIME: Made available only at
- build-time * RUN_AND_BUILD_TIME: Made available at
- both build and run-time. Known values are: "UNSET",
- "RUN_TIME", "BUILD_TIME", and "RUN_AND_BUILD_TIME".
- "type": "GENERAL", #
- Optional. Default value is "GENERAL". * GENERAL: A
- plain-text environment variable * SECRET: A secret
- encrypted environment variable. Known values are:
- "GENERAL" and "SECRET".
- "value": "str" #
- Optional. The value. If the type is ``SECRET``"" ,
- the value will be encrypted on first submission. On
- following submissions, the encrypted value should be
- used.
- }
- ],
- "git": {
- "branch": "str", # Optional.
- The name of the branch to use.
- "repo_clone_url": "str" #
- Optional. The clone URL of the repo. Example:
- ``https://github.com/digitalocean/sample-golang.git``.
- },
- "github": {
- "branch": "str", # Optional.
- The name of the branch to use.
- "deploy_on_push": bool, #
- Optional. Whether to automatically deploy new commits
- made to the repo.
- "repo": "str" # Optional.
- The name of the repo in the format owner/repo. Example:
- ``digitalocean/sample-golang``.
- },
- "gitlab": {
- "branch": "str", # Optional.
- The name of the branch to use.
- "deploy_on_push": bool, #
- Optional. Whether to automatically deploy new commits
- made to the repo.
- "repo": "str" # Optional.
- The name of the repo in the format owner/repo. Example:
- ``digitalocean/sample-golang``.
- },
- "image": {
- "deploy_on_push": {
- "enabled": bool #
- Optional. Whether to automatically deploy new images.
- Can only be used for images hosted in DOCR and can
- only be used with an image tag, not a specific
- digest.
- },
- "digest": "str", # Optional.
- The image digest. Cannot be specified if tag is provided.
- "registry": "str", #
- Optional. The registry name. Must be left empty for the
- ``DOCR`` registry type.
- "registry_credentials":
- "str", # Optional. The credentials to be able to pull
- the image. The value will be encrypted on first
- submission. On following submissions, the encrypted value
- should be used. * "$username:$access_token" for
- registries of type ``DOCKER_HUB``. *
- "$username:$access_token" for registries of type
- ``GHCR``.
- "registry_type": "str", #
- Optional. * DOCKER_HUB: The DockerHub container registry
- type. * DOCR: The DigitalOcean container registry type. *
- GHCR: The Github container registry type. Known values
- are: "DOCKER_HUB", "DOCR", and "GHCR".
- "repository": "str", #
- Optional. The repository name.
- "tag": "latest" # Optional.
- Default value is "latest". The repository tag. Defaults
- to ``latest`` if not provided and no digest is provided.
- Cannot be specified if digest is provided.
- },
- "instance_count": 1, # Optional.
- Default value is 1. The amount of instances that this
- component should be scaled to. Default: 1. Must not be set if
- autoscaling is used.
- "instance_size_slug": {},
- "kind": "UNSPECIFIED", # Optional.
- Default value is "UNSPECIFIED". * UNSPECIFIED: Default job
- type, will auto-complete to POST_DEPLOY kind. * PRE_DEPLOY:
- Indicates a job that runs before an app deployment. *
- POST_DEPLOY: Indicates a job that runs after an app
- deployment. * FAILED_DEPLOY: Indicates a job that runs after
- a component fails to deploy. Known values are: "UNSPECIFIED",
- "PRE_DEPLOY", "POST_DEPLOY", and "FAILED_DEPLOY".
- "log_destinations": [
+ }
+ ],
+ "tos": "str" # The Terms of Service URL for the resource.
+ Required.
+ }
+ ]
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = kwargs.pop("headers", {}) or {}
+ _params = kwargs.pop("params", {}) or {}
+
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ _request = build_addons_get_app_request(
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+ @distributed_trace_async
+ async def get_app_metadata(self, app_slug: str, **kwargs: Any) -> JSON:
+ # pylint: disable=line-too-long
+ """Get Metadata for an Add-On Application.
+
+ To find out what metadata is required for a specific add-on, send a GET request to
+ ``/v2/add-ons/apps/{app_slug}/metadata``.
+ Metadata varies by application.
+
+ :param app_slug: The slug identifier for the application whose metadata is being requested.
+ Required.
+ :type app_slug: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 200
+ response == {
+ "metadata": [
+ {
+ "description": "str", # A brief description of the metadata
+ item. Required.
+ "display_name": "str", # The display name of the metadata
+ item. Required.
+ "id": 0, # Unique identifier for the addon metadata item.
+ Required.
+ "name": "str", # The name of the metadata item. Required.
+ "type": "str", # The data type of the metadata value.
+ Required. Known values are: "string" and "boolean".
+ "options": [
+ "str" # Optional. options.
+ ]
+ }
+ ]
+ }
+ # response body for status code(s): 404
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = kwargs.pop("headers", {}) or {}
+ _params = kwargs.pop("params", {}) or {}
+
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ _request = build_addons_get_app_metadata_request(
+ app_slug=app_slug,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 404]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ if response.status_code == 200:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+ @distributed_trace_async
+ async def list(self, **kwargs: Any) -> JSON:
+ # pylint: disable=line-too-long
+ """List all Add-On Resources.
+
+ To fetch all Add-On Resources under your team, send a GET request to ``/v2/add-ons/saas``.
+
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 200
+ response == {
+ "resources": [
+ {
+ "app_slug": "str", # The slug identifier for the application
+ associated with the resource. Required.
+ "has_config": bool, # Indicates if the resource has
+ configuration values set by the vendor. Required.
+ "name": "str", # The name of the addon resource. Required.
+ "plan_slug": "str", # The slug identifier for the plan
+ associated with the resource. Required.
+ "state": "str", # The state the resource is currently in.
+ Required. Known values are: "pending", "provisioning", "provisioned",
+ "deprovisioning", "deprovisioned", "provisioning-failed",
+ "deprovisioning-failed", and "suspended".
+ "uuid": "str", # The unique identifier for the addon
+ resource. Required.
+ "app_name": "str", # Optional. The name of the application
+ associated with the resource.
+ "message": "str", # Optional. A message related to the
+ resource, if applicable.
+ "metadata": [
+ {
+ "name": "str", # The name of the metadata
+ item to be set. Required.
+ "value": {}
+ }
+ ],
+ "plan_name": "str", # Optional. The name of the plan
+ associated with the resource.
+ "plan_price_per_month": 0, # Optional. The price of the plan
+ per month in US dollars.
+ "sso_url": "str" # Optional. The Single Sign-On URL for the
+ resource, if applicable.
+ }
+ ]
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = kwargs.pop("headers", {}) or {}
+ _params = kwargs.pop("params", {}) or {}
+
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ _request = build_addons_list_request(
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+ @overload
+ async def create(
+ self, body: JSON, *, content_type: str = "application/json", **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """Create/Provision a New Add-on Resource.
+
+ To create an add-on resource, send a POST request to ``/v2/add-ons/saas`` with required
+ parameters.
+ Some add-ons require additional metadata to be provided in the request body. To find out
+ what metadata is required for a specific add-on, send a GET request to
+ ``/v2/add-ons/apps/{app_slug}/metadata``.
+
+ :param body: Required.
+ :type body: JSON
+ :keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
+ Default value is "application/json".
+ :paramtype content_type: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "app_slug": "str", # The slug identifier for the application associated with
+ the resource. Required.
+ "metadata": [
+ {
+ "name": "str", # The name of the metadata item to be set.
+ Required.
+ "value": {}
+ }
+ ],
+ "name": "str", # The name of the addon resource. Required.
+ "plan_slug": "str", # The slug identifier for the plan associated with the
+ resource. Required.
+ "fleet_uuid": "str", # Optional. UUID of the fleet/project to which this
+ resource will belong.
+ "linked_droplet_id": 0 # Optional. ID of the droplet to be linked to this
+ resource, if applicable.
+ }
+
+ # response body for status code(s): 200
+ response == {
+ "resource": {
+ "app_slug": "str", # The slug identifier for the application
+ associated with the resource. Required.
+ "has_config": bool, # Indicates if the resource has configuration
+ values set by the vendor. Required.
+ "name": "str", # The name of the addon resource. Required.
+ "plan_slug": "str", # The slug identifier for the plan associated
+ with the resource. Required.
+ "state": "str", # The state the resource is currently in. Required.
+ Known values are: "pending", "provisioning", "provisioned", "deprovisioning",
+ "deprovisioned", "provisioning-failed", "deprovisioning-failed", and
+ "suspended".
+ "uuid": "str", # The unique identifier for the addon resource.
+ Required.
+ "app_name": "str", # Optional. The name of the application
+ associated with the resource.
+ "message": "str", # Optional. A message related to the resource, if
+ applicable.
+ "metadata": [
+ {
+ "name": "str", # The name of the metadata item to be
+ set. Required.
+ "value": {}
+ }
+ ],
+ "plan_name": "str", # Optional. The name of the plan associated with
+ the resource.
+ "plan_price_per_month": 0, # Optional. The price of the plan per
+ month in US dollars.
+ "sso_url": "str" # Optional. The Single Sign-On URL for the
+ resource, if applicable.
+ }
+ }
+ """
+
+ @overload
+ async def create(
+ self, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """Create/Provision a New Add-on Resource.
+
+ To create an add-on resource, send a POST request to ``/v2/add-ons/saas`` with required
+ parameters.
+ Some add-ons require additional metadata to be provided in the request body. To find out
+ what metadata is required for a specific add-on, send a GET request to
+ ``/v2/add-ons/apps/{app_slug}/metadata``.
+
+ :param body: Required.
+ :type body: IO[bytes]
+ :keyword content_type: Body Parameter content-type. Content type parameter for binary body.
+ Default value is "application/json".
+ :paramtype content_type: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 200
+ response == {
+ "resource": {
+ "app_slug": "str", # The slug identifier for the application
+ associated with the resource. Required.
+ "has_config": bool, # Indicates if the resource has configuration
+ values set by the vendor. Required.
+ "name": "str", # The name of the addon resource. Required.
+ "plan_slug": "str", # The slug identifier for the plan associated
+ with the resource. Required.
+ "state": "str", # The state the resource is currently in. Required.
+ Known values are: "pending", "provisioning", "provisioned", "deprovisioning",
+ "deprovisioned", "provisioning-failed", "deprovisioning-failed", and
+ "suspended".
+ "uuid": "str", # The unique identifier for the addon resource.
+ Required.
+ "app_name": "str", # Optional. The name of the application
+ associated with the resource.
+ "message": "str", # Optional. A message related to the resource, if
+ applicable.
+ "metadata": [
+ {
+ "name": "str", # The name of the metadata item to be
+ set. Required.
+ "value": {}
+ }
+ ],
+ "plan_name": "str", # Optional. The name of the plan associated with
+ the resource.
+ "plan_price_per_month": 0, # Optional. The price of the plan per
+ month in US dollars.
+ "sso_url": "str" # Optional. The Single Sign-On URL for the
+ resource, if applicable.
+ }
+ }
+ """
+
+ @distributed_trace_async
+ async def create(self, body: Union[JSON, IO[bytes]], **kwargs: Any) -> JSON:
+ # pylint: disable=line-too-long
+ """Create/Provision a New Add-on Resource.
+
+ To create an add-on resource, send a POST request to ``/v2/add-ons/saas`` with required
+ parameters.
+ Some add-ons require additional metadata to be provided in the request body. To find out
+ what metadata is required for a specific add-on, send a GET request to
+ ``/v2/add-ons/apps/{app_slug}/metadata``.
+
+ :param body: Is either a JSON type or a IO[bytes] type. Required.
+ :type body: JSON or IO[bytes]
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "app_slug": "str", # The slug identifier for the application associated with
+ the resource. Required.
+ "metadata": [
+ {
+ "name": "str", # The name of the metadata item to be set.
+ Required.
+ "value": {}
+ }
+ ],
+ "name": "str", # The name of the addon resource. Required.
+ "plan_slug": "str", # The slug identifier for the plan associated with the
+ resource. Required.
+ "fleet_uuid": "str", # Optional. UUID of the fleet/project to which this
+ resource will belong.
+ "linked_droplet_id": 0 # Optional. ID of the droplet to be linked to this
+ resource, if applicable.
+ }
+
+ # response body for status code(s): 200
+ response == {
+ "resource": {
+ "app_slug": "str", # The slug identifier for the application
+ associated with the resource. Required.
+ "has_config": bool, # Indicates if the resource has configuration
+ values set by the vendor. Required.
+ "name": "str", # The name of the addon resource. Required.
+ "plan_slug": "str", # The slug identifier for the plan associated
+ with the resource. Required.
+ "state": "str", # The state the resource is currently in. Required.
+ Known values are: "pending", "provisioning", "provisioned", "deprovisioning",
+ "deprovisioned", "provisioning-failed", "deprovisioning-failed", and
+ "suspended".
+ "uuid": "str", # The unique identifier for the addon resource.
+ Required.
+ "app_name": "str", # Optional. The name of the application
+ associated with the resource.
+ "message": "str", # Optional. A message related to the resource, if
+ applicable.
+ "metadata": [
+ {
+ "name": "str", # The name of the metadata item to be
+ set. Required.
+ "value": {}
+ }
+ ],
+ "plan_name": "str", # Optional. The name of the plan associated with
+ the resource.
+ "plan_price_per_month": 0, # Optional. The price of the plan per
+ month in US dollars.
+ "sso_url": "str" # Optional. The Single Sign-On URL for the
+ resource, if applicable.
+ }
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
+ _params = kwargs.pop("params", {}) or {}
+
+ content_type: Optional[str] = kwargs.pop(
+ "content_type", _headers.pop("Content-Type", None)
+ )
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ content_type = content_type or "application/json"
+ _json = None
+ _content = None
+ if isinstance(body, (IOBase, bytes)):
+ _content = body
+ else:
+ _json = body
+
+ _request = build_addons_create_request(
+ content_type=content_type,
+ json=_json,
+ content=_content,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+ @distributed_trace_async
+ async def get(self, resource_uuid: str, **kwargs: Any) -> JSON:
+ # pylint: disable=line-too-long
+ """Get details on an Add-On Resource.
+
+ To fetch details of a specific Add-On Resource, send a GET request to
+ ``/v2/add-ons/saas/{resource_uuid}``.
+ Replace ``{resource_uuid}`` with the UUID of the resource you want to retrieve.
+
+ :param resource_uuid: The UUID of the add-on resource to retrieve. Required.
+ :type resource_uuid: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 200
+ response == {
+ "resource": {
+ "app_slug": "str", # The slug identifier for the application
+ associated with the resource. Required.
+ "has_config": bool, # Indicates if the resource has configuration
+ values set by the vendor. Required.
+ "name": "str", # The name of the addon resource. Required.
+ "plan_slug": "str", # The slug identifier for the plan associated
+ with the resource. Required.
+ "state": "str", # The state the resource is currently in. Required.
+ Known values are: "pending", "provisioning", "provisioned", "deprovisioning",
+ "deprovisioned", "provisioning-failed", "deprovisioning-failed", and
+ "suspended".
+ "uuid": "str", # The unique identifier for the addon resource.
+ Required.
+ "app_name": "str", # Optional. The name of the application
+ associated with the resource.
+ "message": "str", # Optional. A message related to the resource, if
+ applicable.
+ "metadata": [
+ {
+ "name": "str", # The name of the metadata item to be
+ set. Required.
+ "value": {}
+ }
+ ],
+ "plan_name": "str", # Optional. The name of the plan associated with
+ the resource.
+ "plan_price_per_month": 0, # Optional. The price of the plan per
+ month in US dollars.
+ "sso_url": "str" # Optional. The Single Sign-On URL for the
+ resource, if applicable.
+ }
+ }
+ # response body for status code(s): 404
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = kwargs.pop("headers", {}) or {}
+ _params = kwargs.pop("params", {}) or {}
+
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ _request = build_addons_get_request(
+ resource_uuid=resource_uuid,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 404]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ if response.status_code == 200:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+ @distributed_trace_async
+ async def delete(self, resource_uuid: str, **kwargs: Any) -> Optional[JSON]:
+ # pylint: disable=line-too-long
+ """Delete/Deprovision an Add-on Resource.
+
+ To delete an add-on resource, send a DELETE request to ``/v2/add-ons/saas/{resource_uuid}``
+ with the UUID of the resource to delete.
+ You cannot retrieve the resource after it has been deleted. The response indicates a request
+ was sent to the 3rd party add-on provider to delete the resource.
+ You will no longer be billed for this resource.
+
+ :param resource_uuid: A unique identifier for the add-on resource. Required.
+ :type resource_uuid: str
+ :return: JSON object or None
+ :rtype: JSON or None
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 404
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = kwargs.pop("headers", {}) or {}
+ _params = kwargs.pop("params", {}) or {}
+
+ cls: ClsType[Optional[JSON]] = kwargs.pop("cls", None)
+
+ _request = build_addons_delete_request(
+ resource_uuid=resource_uuid,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 404]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ deserialized = None
+ response_headers = {}
+ if response.status_code == 200:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, deserialized, response_headers) # type: ignore
+
+ return deserialized # type: ignore
+
+ @overload
+ async def patch(
+ self,
+ resource_uuid: str,
+ body: JSON,
+ *,
+ content_type: str = "application/json",
+ **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """Update the name for an Add-On Resource.
+
+ To change the name of an Add-On Resource, send a PATCH request to
+ ``/v2/add-ons/saas/{resource_uuid}``.
+ Replace ``{resource_uuid}`` with the UUID of the resource for which you want to change the
+ name.
+
+ :param resource_uuid: The UUID of the add-on resource to rename. Required.
+ :type resource_uuid: str
+ :param body: Required.
+ :type body: JSON
+ :keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
+ Default value is "application/json".
+ :paramtype content_type: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "name": "str" # The new name for the add-on resource. Required.
+ }
+
+ # response body for status code(s): 200
+ response == {
+ "resource": {
+ "app_slug": "str", # The slug identifier for the application
+ associated with the resource. Required.
+ "has_config": bool, # Indicates if the resource has configuration
+ values set by the vendor. Required.
+ "name": "str", # The name of the addon resource. Required.
+ "plan_slug": "str", # The slug identifier for the plan associated
+ with the resource. Required.
+ "state": "str", # The state the resource is currently in. Required.
+ Known values are: "pending", "provisioning", "provisioned", "deprovisioning",
+ "deprovisioned", "provisioning-failed", "deprovisioning-failed", and
+ "suspended".
+ "uuid": "str", # The unique identifier for the addon resource.
+ Required.
+ "app_name": "str", # Optional. The name of the application
+ associated with the resource.
+ "message": "str", # Optional. A message related to the resource, if
+ applicable.
+ "metadata": [
+ {
+ "name": "str", # The name of the metadata item to be
+ set. Required.
+ "value": {}
+ }
+ ],
+ "plan_name": "str", # Optional. The name of the plan associated with
+ the resource.
+ "plan_price_per_month": 0, # Optional. The price of the plan per
+ month in US dollars.
+ "sso_url": "str" # Optional. The Single Sign-On URL for the
+ resource, if applicable.
+ }
+ }
+ # response body for status code(s): 404
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+
+ @overload
+ async def patch(
+ self,
+ resource_uuid: str,
+ body: IO[bytes],
+ *,
+ content_type: str = "application/json",
+ **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """Update the name for an Add-On Resource.
+
+ To change the name of an Add-On Resource, send a PATCH request to
+ ``/v2/add-ons/saas/{resource_uuid}``.
+ Replace ``{resource_uuid}`` with the UUID of the resource for which you want to change the
+ name.
+
+ :param resource_uuid: The UUID of the add-on resource to rename. Required.
+ :type resource_uuid: str
+ :param body: Required.
+ :type body: IO[bytes]
+ :keyword content_type: Body Parameter content-type. Content type parameter for binary body.
+ Default value is "application/json".
+ :paramtype content_type: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 200
+ response == {
+ "resource": {
+ "app_slug": "str", # The slug identifier for the application
+ associated with the resource. Required.
+ "has_config": bool, # Indicates if the resource has configuration
+ values set by the vendor. Required.
+ "name": "str", # The name of the addon resource. Required.
+ "plan_slug": "str", # The slug identifier for the plan associated
+ with the resource. Required.
+ "state": "str", # The state the resource is currently in. Required.
+ Known values are: "pending", "provisioning", "provisioned", "deprovisioning",
+ "deprovisioned", "provisioning-failed", "deprovisioning-failed", and
+ "suspended".
+ "uuid": "str", # The unique identifier for the addon resource.
+ Required.
+ "app_name": "str", # Optional. The name of the application
+ associated with the resource.
+ "message": "str", # Optional. A message related to the resource, if
+ applicable.
+ "metadata": [
+ {
+ "name": "str", # The name of the metadata item to be
+ set. Required.
+ "value": {}
+ }
+ ],
+ "plan_name": "str", # Optional. The name of the plan associated with
+ the resource.
+ "plan_price_per_month": 0, # Optional. The price of the plan per
+ month in US dollars.
+ "sso_url": "str" # Optional. The Single Sign-On URL for the
+ resource, if applicable.
+ }
+ }
+ # response body for status code(s): 404
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+
+ @distributed_trace_async
+ async def patch(
+ self, resource_uuid: str, body: Union[JSON, IO[bytes]], **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """Update the name for an Add-On Resource.
+
+ To change the name of an Add-On Resource, send a PATCH request to
+ ``/v2/add-ons/saas/{resource_uuid}``.
+ Replace ``{resource_uuid}`` with the UUID of the resource for which you want to change the
+ name.
+
+ :param resource_uuid: The UUID of the add-on resource to rename. Required.
+ :type resource_uuid: str
+ :param body: Is either a JSON type or a IO[bytes] type. Required.
+ :type body: JSON or IO[bytes]
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "name": "str" # The new name for the add-on resource. Required.
+ }
+
+ # response body for status code(s): 200
+ response == {
+ "resource": {
+ "app_slug": "str", # The slug identifier for the application
+ associated with the resource. Required.
+ "has_config": bool, # Indicates if the resource has configuration
+ values set by the vendor. Required.
+ "name": "str", # The name of the addon resource. Required.
+ "plan_slug": "str", # The slug identifier for the plan associated
+ with the resource. Required.
+ "state": "str", # The state the resource is currently in. Required.
+ Known values are: "pending", "provisioning", "provisioned", "deprovisioning",
+ "deprovisioned", "provisioning-failed", "deprovisioning-failed", and
+ "suspended".
+ "uuid": "str", # The unique identifier for the addon resource.
+ Required.
+ "app_name": "str", # Optional. The name of the application
+ associated with the resource.
+ "message": "str", # Optional. A message related to the resource, if
+ applicable.
+ "metadata": [
+ {
+ "name": "str", # The name of the metadata item to be
+ set. Required.
+ "value": {}
+ }
+ ],
+ "plan_name": "str", # Optional. The name of the plan associated with
+ the resource.
+ "plan_price_per_month": 0, # Optional. The price of the plan per
+ month in US dollars.
+ "sso_url": "str" # Optional. The Single Sign-On URL for the
+ resource, if applicable.
+ }
+ }
+ # response body for status code(s): 404
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
+ _params = kwargs.pop("params", {}) or {}
+
+ content_type: Optional[str] = kwargs.pop(
+ "content_type", _headers.pop("Content-Type", None)
+ )
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ content_type = content_type or "application/json"
+ _json = None
+ _content = None
+ if isinstance(body, (IOBase, bytes)):
+ _content = body
+ else:
+ _json = body
+
+ _request = build_addons_patch_request(
+ resource_uuid=resource_uuid,
+ content_type=content_type,
+ json=_json,
+ content=_content,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 404]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ if response.status_code == 200:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+ @overload
+ async def patch_plan(
+ self,
+ resource_uuid: str,
+ body: JSON,
+ *,
+ content_type: str = "application/json",
+ **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """Update the plan for an Add-On Resource.
+
+ To change the plan associated with an Add-On Resource, send a PATCH request to
+ ``/v2/add-ons/saas/{resource_uuid}/plan``.
+ Replace ``{resource_uuid}`` with the UUID of the resource for which you want to change the
+ plan.
+
+ :param resource_uuid: The UUID of the add-on resource to update. Required.
+ :type resource_uuid: str
+ :param body: Required.
+ :type body: JSON
+ :keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
+ Default value is "application/json".
+ :paramtype content_type: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "plan_slug": "str" # The slug identifier for the new plan to apply to the
+ add-on resource. Required.
+ }
+
+ # response body for status code(s): 200
+ response == {
+ "resource": {
+ "app_slug": "str", # The slug identifier for the application
+ associated with the resource. Required.
+ "has_config": bool, # Indicates if the resource has configuration
+ values set by the vendor. Required.
+ "name": "str", # The name of the addon resource. Required.
+ "plan_slug": "str", # The slug identifier for the plan associated
+ with the resource. Required.
+ "state": "str", # The state the resource is currently in. Required.
+ Known values are: "pending", "provisioning", "provisioned", "deprovisioning",
+ "deprovisioned", "provisioning-failed", "deprovisioning-failed", and
+ "suspended".
+ "uuid": "str", # The unique identifier for the addon resource.
+ Required.
+ "app_name": "str", # Optional. The name of the application
+ associated with the resource.
+ "message": "str", # Optional. A message related to the resource, if
+ applicable.
+ "metadata": [
+ {
+ "name": "str", # The name of the metadata item to be
+ set. Required.
+ "value": {}
+ }
+ ],
+ "plan_name": "str", # Optional. The name of the plan associated with
+ the resource.
+ "plan_price_per_month": 0, # Optional. The price of the plan per
+ month in US dollars.
+ "sso_url": "str" # Optional. The Single Sign-On URL for the
+ resource, if applicable.
+ }
+ }
+ # response body for status code(s): 404
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+
+ @overload
+ async def patch_plan(
+ self,
+ resource_uuid: str,
+ body: IO[bytes],
+ *,
+ content_type: str = "application/json",
+ **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """Update the plan for an Add-On Resource.
+
+ To change the plan associated with an Add-On Resource, send a PATCH request to
+ ``/v2/add-ons/saas/{resource_uuid}/plan``.
+ Replace ``{resource_uuid}`` with the UUID of the resource for which you want to change the
+ plan.
+
+ :param resource_uuid: The UUID of the add-on resource to update. Required.
+ :type resource_uuid: str
+ :param body: Required.
+ :type body: IO[bytes]
+ :keyword content_type: Body Parameter content-type. Content type parameter for binary body.
+ Default value is "application/json".
+ :paramtype content_type: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 200
+ response == {
+ "resource": {
+ "app_slug": "str", # The slug identifier for the application
+ associated with the resource. Required.
+ "has_config": bool, # Indicates if the resource has configuration
+ values set by the vendor. Required.
+ "name": "str", # The name of the addon resource. Required.
+ "plan_slug": "str", # The slug identifier for the plan associated
+ with the resource. Required.
+ "state": "str", # The state the resource is currently in. Required.
+ Known values are: "pending", "provisioning", "provisioned", "deprovisioning",
+ "deprovisioned", "provisioning-failed", "deprovisioning-failed", and
+ "suspended".
+ "uuid": "str", # The unique identifier for the addon resource.
+ Required.
+ "app_name": "str", # Optional. The name of the application
+ associated with the resource.
+ "message": "str", # Optional. A message related to the resource, if
+ applicable.
+ "metadata": [
+ {
+ "name": "str", # The name of the metadata item to be
+ set. Required.
+ "value": {}
+ }
+ ],
+ "plan_name": "str", # Optional. The name of the plan associated with
+ the resource.
+ "plan_price_per_month": 0, # Optional. The price of the plan per
+ month in US dollars.
+ "sso_url": "str" # Optional. The Single Sign-On URL for the
+ resource, if applicable.
+ }
+ }
+ # response body for status code(s): 404
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+
+ @distributed_trace_async
+ async def patch_plan(
+ self, resource_uuid: str, body: Union[JSON, IO[bytes]], **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """Update the plan for an Add-On Resource.
+
+ To change the plan associated with an Add-On Resource, send a PATCH request to
+ ``/v2/add-ons/saas/{resource_uuid}/plan``.
+ Replace ``{resource_uuid}`` with the UUID of the resource for which you want to change the
+ plan.
+
+ :param resource_uuid: The UUID of the add-on resource to update. Required.
+ :type resource_uuid: str
+ :param body: Is either a JSON type or a IO[bytes] type. Required.
+ :type body: JSON or IO[bytes]
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "plan_slug": "str" # The slug identifier for the new plan to apply to the
+ add-on resource. Required.
+ }
+
+ # response body for status code(s): 200
+ response == {
+ "resource": {
+ "app_slug": "str", # The slug identifier for the application
+ associated with the resource. Required.
+ "has_config": bool, # Indicates if the resource has configuration
+ values set by the vendor. Required.
+ "name": "str", # The name of the addon resource. Required.
+ "plan_slug": "str", # The slug identifier for the plan associated
+ with the resource. Required.
+ "state": "str", # The state the resource is currently in. Required.
+ Known values are: "pending", "provisioning", "provisioned", "deprovisioning",
+ "deprovisioned", "provisioning-failed", "deprovisioning-failed", and
+ "suspended".
+ "uuid": "str", # The unique identifier for the addon resource.
+ Required.
+ "app_name": "str", # Optional. The name of the application
+ associated with the resource.
+ "message": "str", # Optional. A message related to the resource, if
+ applicable.
+ "metadata": [
+ {
+ "name": "str", # The name of the metadata item to be
+ set. Required.
+ "value": {}
+ }
+ ],
+ "plan_name": "str", # Optional. The name of the plan associated with
+ the resource.
+ "plan_price_per_month": 0, # Optional. The price of the plan per
+ month in US dollars.
+ "sso_url": "str" # Optional. The Single Sign-On URL for the
+ resource, if applicable.
+ }
+ }
+ # response body for status code(s): 404
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
+ _params = kwargs.pop("params", {}) or {}
+
+ content_type: Optional[str] = kwargs.pop(
+ "content_type", _headers.pop("Content-Type", None)
+ )
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ content_type = content_type or "application/json"
+ _json = None
+ _content = None
+ if isinstance(body, (IOBase, bytes)):
+ _content = body
+ else:
+ _json = body
+
+ _request = build_addons_patch_plan_request(
+ resource_uuid=resource_uuid,
+ content_type=content_type,
+ json=_json,
+ content=_content,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 404]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ if response.status_code == 200:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+
+class HarnessOperations: # pylint: disable=too-many-public-methods
+ """
+ .. warning::
+ **DO NOT** instantiate this class directly.
+
+ Instead, you should access the following operations through
+ :class:`~pydo.aio.GeneratedClient`'s
+ :attr:`harness` attribute.
+ """
+
+ def __init__(self, *args, **kwargs) -> None:
+ input_args = list(args)
+ self._client = input_args.pop(0) if input_args else kwargs.pop("client")
+ self._config = input_args.pop(0) if input_args else kwargs.pop("config")
+ self._serialize = input_args.pop(0) if input_args else kwargs.pop("serializer")
+ self._deserialize = (
+ input_args.pop(0) if input_args else kwargs.pop("deserializer")
+ )
+
+ @distributed_trace_async
+ async def list_configs(
+ self,
+ *,
+ page_size: int = 50,
+ page_token: Optional[str] = None,
+ search: Optional[str] = None,
+ **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """List active Environment Configs for the caller's team.
+
+ Returns lightweight team-scoped config metadata without loading or returning environment-spec
+ JSON. Soft-deleted configs are excluded.
+
+ :keyword page_size: Page size. Defaults to 50 when omitted. Values above 200 are rejected.
+ Default value is 50.
+ :paramtype page_size: int
+ :keyword page_token: Opaque keyset cursor returned by the previous page. Default value is None.
+ :paramtype page_token: str
+ :keyword search: Optional case-insensitive substring filter on config name (contains). Empty or
+ omitted returns the unfiltered page. At most 64 characters. Default value is None.
+ :paramtype search: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 200
+ response == {
+ "configs": [
+ {
+ "agentspec_schema_version": "str", # The manifest contract
+ the server accepted at create time: the manifest's own apiVersion for
+ legacy envelope parses (currently agents.digitalocean.com/v1alpha1), or
+ agents.digitalocean.com/flat.v1 for flat-format parses. Required.
+ "content_hash": "str", # Lowercase SHA-256 hex digest of the
+ canonical sanitized manifest JSON. Required.
+ "created_at": "2020-02-20 00:00:00", # Required.
+ "created_by": "str", # Authenticated user identity that
+ created the config. Required.
+ "id": "str", # Required.
+ "name": "str", # Required.
+ "updated_at": "2020-02-20 00:00:00" # Required.
+ }
+ ],
+ "next_page_token": "str" # Optional.
+ }
+ # response body for status code(s): 400
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = kwargs.pop("headers", {}) or {}
+ _params = kwargs.pop("params", {}) or {}
+
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ _request = build_harness_list_configs_request(
+ page_size=page_size,
+ page_token=page_token,
+ search=search,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 400]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ if response.status_code == 200:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 400:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+ @overload
+ async def create_config(
+ self, body: JSON, *, content_type: str = "application/json", **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """Create an Environment Config (environment spec + optional Insights opt-in).
+
+ Accepts name, environment-spec YAML text, and optional Insights telemetry opt-in. Tenant
+ secrets are declared inside the environment spec (write-only values), not as sibling request
+ fields. Responses never echo secret values; GET/create may include credential slot metadata
+ (name/source/provider only). Configs are immutable after create.
+
+ :param body: Environment Config create body. Secret values live in the environment-spec YAML
+ and are never returned. Required.
+ :type body: JSON
+ :keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
+ Default value is "application/json".
+ :paramtype content_type: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "manifest_yaml": "str", # Customer environment-spec YAML text. The HTTP JSON
+ body is capped at 1 MiB and this field is capped at 512 KiB. Required.
+ "name": "str", # Config name, case-insensitively unique among the team's
+ active configs. Required.
+ "insights": {
+ "logs": bool, # Optional. Whether the agent's logs are sent to
+ Insights.
+ "metrics": bool, # Optional. Accepted and stored for parity with the
+ Insights schema, but metrics are always collected: unregistered metrics are
+ dropped at ingest rather than opted out of here.
+ "traces": bool # Optional. Whether the agent's traces are sent to
+ Insights.
+ }
+ }
+
+ # response body for status code(s): 201
+ response == {
+ "config": {
+ "agentspec_schema_version": "str", # The manifest contract the
+ server accepted at create time: the manifest's own apiVersion for legacy
+ envelope parses (currently agents.digitalocean.com/v1alpha1), or
+ agents.digitalocean.com/flat.v1 for flat-format parses. Required.
+ "content_hash": "str", # Lowercase SHA-256 hex digest of the
+ canonical sanitized manifest JSON. Required.
+ "created_at": "2020-02-20 00:00:00", # Required.
+ "created_by": "str", # Authenticated user identity that created the
+ config. Required.
+ "id": "str", # Required.
+ "manifest": {
+ "apiVersion": "str", # Optional. Legacy envelope only - must
+ be "agents.digitalocean.com/v1alpha1", and its presence is what routes
+ the document to the deprecated legacy parser. Flat-format manifests carry
+ no version key (the endpoint owns the contract); required, with kind and
+ spec, when authoring the legacy format.
+ "agents.digitalocean.com/v1alpha1"
+ "kind": "str", # Optional. Must be "Agent". "Agent"
+ "metadata": {
+ "description": "str", # Optional. Free-form
+ description (max 1024 chars), stored and echoed back for Console /
+ catalog surfaces.
+ "labels": {
+ "str": "str" # Optional. Dictionary of
+ :code:``.
+ },
+ "name": "str" # Optional. Optional team-unique
+ session name: 1-64 chars of letters, digits, '-', '.', '_', starting
+ and ending alphanumeric; case-insensitive; must not be UUID-shaped.
+ Omit to have the control plane generate one
+ ("session-:code:``-:code:``"). Unique among
+ the team's ACTIVE (non-terminal) sessions; destroying a session frees
+ its name for reuse.
+ },
+ "spec": {
+ "runtime": {
+ "adapter": "str", # Required. Known values
+ are: "claude-code", "opencode", "codex", "cursor", "hermes",
+ "codex-agentapi", "custom", "codex-cli", "cursor-cli",
+ "openai-agents", "claude-agent-sdk", "crewai", and "langgraph".
+ "config": {
+ "str": {} # Optional. OPAQUE,
+ provider-specific runtime config. Only for adapter:
+ codex-agentapi today, where it is the OpenAI Agents API
+ create-session body (agent/environment/input) that doctl
+ forwards verbatim to OpenAI's POST /v1/agents/sessions;
+ harness-api stores and echoes it but never parses or
+ validates its contents (so DO stays forward-compatible as
+ OpenAI's schema evolves). The OpenAI session_id is passed on
+ the create call (the openai_session_id query parameter), not
+ in this block.
+ },
+ "custom": {
+ "image": "str", # Required.
+ "entrypoint": [
+ "str" # Optional. BYO
+ container; requires adapter: custom. image is required
+ and should be digest-pinned.
+ ]
+ }
+ },
+ "defaults": {
+ "budget": {
+ "maxCostUSD": 0.0, # Optional.
+ Accepted, not yet enforced (returns a warning). Advisory
+ per-run ceilings, clamped server-side to tenant policy.
+ "maxSteps": 0, # Optional. Accepted,
+ not yet enforced (returns a warning). Advisory per-run
+ ceilings, clamped server-side to tenant policy.
+ "maxWallClockSeconds": 0, #
+ Optional. Accepted, not yet enforced (returns a warning).
+ Advisory per-run ceilings, clamped server-side to tenant
+ policy.
+ "onBreach": "str" # Optional. Known
+ values are: "pause", "humanInput", and "fail".
+ }
+ },
+ "env": {
+ "str": "str" # Optional. Non-secret guest
+ env (debug-readable - never put secrets here; use spec.secrets).
+ Reserved platform keys (TEAM_ID, SESSION_ID, SANDBOX_ID,
+ CONTROL_PLANE_CALLBACK_URL, SANDBOX_TEMPLATE,
+ SANDBOX_AGENT_WORKDIR, SIZE_SLUG, SANDBOX_IMAGE_ID,
+ SANDBOX_OCI_REF, PLANO"" *PERMISSION*"" *) are rejected.
+ Credential-looking values (dop"" *v1*..., sk-..., ghp_...)
+ trigger a create-time warning.
+ },
+ "memory": {
+ "backend": "str", # Required.
+ "scope": "str" # Optional. Known values are:
+ "tenant", "user", "agent", and "session".
+ },
+ "mode": "str", # Optional. Explicit lifecycle
+ discriminator. Defaults to "interactive" (spec.serving forbidden);
+ "served" requires spec.serving. Known values are: "interactive" and
+ "served".
+ "model": {
+ "default": "str", # Optional. Accepted, not
+ yet enforced (returns a warning). Model routing (Plano);
+ catalog-validated when enforcement lands.
+ "profile": "str", # Optional. Accepted, not
+ yet enforced (returns a warning). Model routing (Plano);
+ catalog-validated when enforcement lands.
+ "routing": "str" # Optional. Accepted, not
+ yet enforced (returns a warning). Model routing (Plano);
+ catalog-validated when enforcement lands.
+ },
+ "permissions": {
+ "defaultAction": "str", # Optional.
+ Disposition for tool calls that match no rule. Defaults to "ask"
+ when omitted. Known values are: "allow", "ask", and "deny".
+ "filesystem": {
+ "allowWrite": [
+ "str" # Optional. Additional
+ writable paths beyond the workspace. Values must not
+ contain shell-style ${VAR}/$VAR expansions.
+ ],
+ "mode": "str" # Optional. Known
+ values are: "read-only" and "workspace-write".
+ },
+ "network": {
+ "allow": [
+ "str" # Optional. Network
+ boundary. Narrows (subtract-only) spec.sandbox.egress;
+ link-local/internal addresses stay blocked by the broader
+ egress policy.
+ ],
+ "default": "str" # Optional. Known
+ values are: "allow" and "deny".
+ },
+ "rules": [
+ {
+ "action": "str", # Required.
+ Known values are: "allow", "ask", and "deny".
+ "tool": "str", # Tool
+ taxonomy this rule matches (e.g. bash, file.read,
+ file.write, web.fetch, git.*, mcp). Required.
+ "enforcement": "str", #
+ Optional. What happens when the agent cannot enforce the
+ rule exactly. "strict" rejects the session; "best-effort"
+ degrades to the closest more-restrictive form and warns
+ (never widens). Defaults to strict for deny rules,
+ best-effort otherwise. Known values are: "strict" and
+ "best-effort".
+ "match": {
+ "str": "str" #
+ Optional. Optional keys narrowing the rule (e.g.
+ {"command": "npm run deploy"} for bash). Values are
+ globs and must not contain shell-style ${VAR}/$VAR
+ expansions.
+ }
+ }
+ ]
+ },
+ "sandbox": {
+ "egress": {
+ "allow": [
+ {
+ "host": "str" #
+ Required.
+ }
+ ],
+ "allowIps": [
+ "str" # Optional. Exact
+ IPv4/IPv6 literals (not CIDRs).
+ ],
+ "subnetUuid": "str", # Optional.
+ Optional subnet within vpcUuid.
+ "unrestricted": bool, # Optional.
+ When true, opts out of the platform-default host allowlist
+ union. Mutually exclusive with allow / allowIps / vpcUuid /
+ subnetUuid.
+ "vpcUuid": "str" # Optional.
+ Customer VPC UUID. Create-time immutable.
+ },
+ "idleTimeoutSeconds": 0, # Optional.
+ Inactivity suspend timeout. 0 means tenant policy default.
+ "maxLifetimeSeconds": 0, # Optional. Hard
+ wall-clock ceiling for the whole session, independent of
+ activity. Accepted, not yet enforced (returns a warning).
+ "mounts": [
+ {
+ "accessKeyRef": "str", #
+ Names a declared tenantSecret slot in spec.secrets.
+ Required.
+ "bucket": "str", # Required.
+ "path": "str", # Absolute
+ guest path the mount appears at. Required.
+ "secretKeyRef": "str", #
+ Names a declared tenantSecret slot in spec.secrets.
+ Required.
+ "type": "str", # Required.
+ "s3fuse"
+ "endpoint": "str", #
+ Optional. Optional storage endpoint override; https://
+ only.
+ "readOnly": bool # Optional.
+ Requested data mounts. Accepted, not yet enforced
+ (returns a warning). accessKeyRef/secretKeyRef name
+ declared tenantSecret slots in spec.secrets, validated at
+ create; declare those slots with env: false so the keys
+ stay mount-scoped and out of the guest env.
+ }
+ ],
+ "persistentWorkspace": bool, # Optional.
+ Canonical runnable environment spec JSON, immutable after create.
+ Validated non-secret spec.env and spec.permissions remain;
+ spec.secrets retains name/source/provider but omits ref and the
+ write-only value; metadata.name is cleared while safe metadata
+ such as labels remains. Required.
+ "sizeSlug": "str", # Optional. Requested
+ sandbox size (catalog: GET /v2/agents/sessions/sandbox/sizes).
+ Empty means the service default.
+ "template": "str" # Optional. Optional
+ sandbox template. Empty (or the legacy placeholder "coding")
+ means "no preference": the template derives from the adapter.
+ },
+ "secrets": [
+ {
+ "name": "str", # Required.
+ "source": "str", # Required. Known
+ values are: "oauth" and "tenantSecret".
+ "env": bool, # Optional. Whether the
+ resolved credential is injected into the guest env. Omitted
+ means true; false is for mount-only slots (tenantSecret
+ only).
+ "provider": "str", # Optional.
+ Declared credential requirements. source tenantSecret is
+ enforced today: value is write-only plaintext, extracted into
+ Secrets Manager at create and never persisted or returned.
+ source oauth requires provider, carries no value, and is
+ accepted but not yet enforced. ref is legacy and ignored. env
+ false keeps the resolved value out of the guest environment
+ (mount-only slots).
+ "ref": "str", # Optional. Declared
+ credential requirements. source tenantSecret is enforced
+ today: value is write-only plaintext, extracted into Secrets
+ Manager at create and never persisted or returned. source
+ oauth requires provider, carries no value, and is accepted
+ but not yet enforced. ref is legacy and ignored. env false
+ keeps the resolved value out of the guest environment
+ (mount-only slots).
+ "value": "str" # Optional.
+ Write-only tenantSecret plaintext; never persisted or
+ returned.
+ }
+ ],
+ "serving": {
+ "maxReplicas": 0, # Optional. Present only
+ when spec.mode is "served" (autoscaled fleet).
+ "minReplicas": 0, # Optional. Present only
+ when spec.mode is "served" (autoscaled fleet).
+ "scaleToZero": {
+ "idleSeconds": 0 # Optional. Present
+ only when spec.mode is "served" (autoscaled fleet).
+ },
+ "targetConcurrency": 0 # Optional. Present
+ only when spec.mode is "served" (autoscaled fleet).
+ },
+ "skills": [
+ {
+ "description": "str", #
+ Load-bearing: the agent reads it to decide WHEN to load the
+ skill (progressive disclosure); write it as "Use when ...".
+ Max 1024 chars. Required.
+ "instructions": "str", # The
+ markdown body (the content below the SKILL.md frontmatter).
+ Max 32 KiB. Required.
+ "name": "str", # Unique across the
+ list; 1-64 chars of lowercase letters, digits, and single
+ hyphen separators - no consecutive hyphens, per the Agent
+ Skills spec (safe as a directory name at materialization).
+ Required.
+ "allowedTools": [
+ "str" # Optional. Advisory
+ scoping of which tools the skill expects to use
+ (experimental in the skills standard). NOT a security
+ boundary - spec.permissions remains the only enforcement
+ surface.
+ ],
+ "license": "str", # Optional.
+ Optional standard passthrough (e.g. Apache-2.0).
+ "metadata": {
+ "str": "str" # Optional.
+ Optional string-map passthrough (e.g. author), rendered
+ into the frontmatter verbatim.
+ }
+ }
+ ],
+ "tools": {
+ "bundle": "str", # Optional. Accepted, not
+ yet enforced (returns a warning). Exactly one of mcpServers or
+ bundle.
+ "mcpServers": [
+ {
+ "auth": {
+ "secretRef": "str",
+ # Tenant-vault secret name. Required.
+ "header": "str" #
+ Optional. HTTP header the credential is sent in.
+ Defaults to Authorization.
+ },
+ "name": "str", # Optional.
+ Inline server name (required with url): 1-64 chars of
+ lowercase letters, digits, '-', '.', '_', starting/ending
+ alphanumeric. Unique across the list. Must not start with
+ do. (reserved for catalog refs).
+ "preloadTools": [
+ "str" # Optional.
+ Catalog form only. Individual tools (optional integer
+ pin) advertised directly in the session MCP
+ tools/list next to the
+ action_search/action_invoke/action_code meta tools.
+ Each entry must appear in tools when tools is set;
+ toolbelt references are rejected. Every preloaded
+ schema is in the model's context on every turn, so
+ keep this to a handful of tools. Omitted means
+ nothing is preloaded.
+ ],
+ "ref": "str", # Optional.
+ DO-owned catalog reference (catalog form); do.* only,
+ e.g. do.actions. Mutually exclusive with name/url/auth.
+ "tools": [
+ "str" # Optional.
+ Optional selection allowlist; omitted means all tools
+ the server advertises. Each entry is an individual
+ tool name with an optional integer version pin (e.g.
+ web_search, execute_code@3) or a toolbelt reference -
+ a server-defined named tool group written
+ toolbelt:[@:code:``] (e.g.
+ toolbelt:read-only@1; catalog refs only). Versions
+ are integer pins (no semver). The server owns belt
+ expansion; a pinned tool or belt attaches exactly
+ that version, an unpinned one resolves at session
+ create and is frozen for the session (no floating
+ latest). Entries non-empty, unique per server. The
+ selection bounds the session and is never preloaded
+ into the session MCP tools/list; see preloadTools.
+ ],
+ "url": "str" # Optional.
+ Inline server endpoint; https:// only.
+ }
+ ]
+ },
+ "workspace": {
+ "repos": [
+ "str" # Optional. GitHub OWNER/REPO
+ entries, unique. The first entry becomes the session's
+ repo_hint; the full list is the forward shape for multi-repo
+ sessions.
+ ]
+ }
+ }
+ },
+ "name": "str", # Required.
+ "updated_at": "2020-02-20 00:00:00", # Required.
+ "credentials": [
+ {
+ "name": "str", # Required.
+ "provider": "str", # Optional. Redacted credential
+ slot metadata (name/source/provider). Secret values are never
+ included.
+ "source": "str" # Optional. Known values are:
+ "tenantSecret" and "oauth".
+ }
+ ],
+ "insights": {
+ "logs": bool, # Optional. Whether the agent's logs are sent
+ to Insights.
+ "metrics": bool, # Optional. Accepted and stored for parity
+ with the Insights schema, but metrics are always collected: unregistered
+ metrics are dropped at ingest rather than opted out of here.
+ "traces": bool # Optional. Whether the agent's traces are
+ sent to Insights.
+ }
+ }
+ }
+ # response body for status code(s): 400, 409, 413, 415
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+
+ @overload
+ async def create_config(
+ self, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """Create an Environment Config (environment spec + optional Insights opt-in).
+
+ Accepts name, environment-spec YAML text, and optional Insights telemetry opt-in. Tenant
+ secrets are declared inside the environment spec (write-only values), not as sibling request
+ fields. Responses never echo secret values; GET/create may include credential slot metadata
+ (name/source/provider only). Configs are immutable after create.
+
+ :param body: Environment Config create body. Secret values live in the environment-spec YAML
+ and are never returned. Required.
+ :type body: IO[bytes]
+ :keyword content_type: Body Parameter content-type. Content type parameter for binary body.
+ Default value is "application/json".
+ :paramtype content_type: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 201
+ response == {
+ "config": {
+ "agentspec_schema_version": "str", # The manifest contract the
+ server accepted at create time: the manifest's own apiVersion for legacy
+ envelope parses (currently agents.digitalocean.com/v1alpha1), or
+ agents.digitalocean.com/flat.v1 for flat-format parses. Required.
+ "content_hash": "str", # Lowercase SHA-256 hex digest of the
+ canonical sanitized manifest JSON. Required.
+ "created_at": "2020-02-20 00:00:00", # Required.
+ "created_by": "str", # Authenticated user identity that created the
+ config. Required.
+ "id": "str", # Required.
+ "manifest": {
+ "apiVersion": "str", # Optional. Legacy envelope only - must
+ be "agents.digitalocean.com/v1alpha1", and its presence is what routes
+ the document to the deprecated legacy parser. Flat-format manifests carry
+ no version key (the endpoint owns the contract); required, with kind and
+ spec, when authoring the legacy format.
+ "agents.digitalocean.com/v1alpha1"
+ "kind": "str", # Optional. Must be "Agent". "Agent"
+ "metadata": {
+ "description": "str", # Optional. Free-form
+ description (max 1024 chars), stored and echoed back for Console /
+ catalog surfaces.
+ "labels": {
+ "str": "str" # Optional. Dictionary of
+ :code:``.
+ },
+ "name": "str" # Optional. Optional team-unique
+ session name: 1-64 chars of letters, digits, '-', '.', '_', starting
+ and ending alphanumeric; case-insensitive; must not be UUID-shaped.
+ Omit to have the control plane generate one
+ ("session-:code:``-:code:``"). Unique among
+ the team's ACTIVE (non-terminal) sessions; destroying a session frees
+ its name for reuse.
+ },
+ "spec": {
+ "runtime": {
+ "adapter": "str", # Required. Known values
+ are: "claude-code", "opencode", "codex", "cursor", "hermes",
+ "codex-agentapi", "custom", "codex-cli", "cursor-cli",
+ "openai-agents", "claude-agent-sdk", "crewai", and "langgraph".
+ "config": {
+ "str": {} # Optional. OPAQUE,
+ provider-specific runtime config. Only for adapter:
+ codex-agentapi today, where it is the OpenAI Agents API
+ create-session body (agent/environment/input) that doctl
+ forwards verbatim to OpenAI's POST /v1/agents/sessions;
+ harness-api stores and echoes it but never parses or
+ validates its contents (so DO stays forward-compatible as
+ OpenAI's schema evolves). The OpenAI session_id is passed on
+ the create call (the openai_session_id query parameter), not
+ in this block.
+ },
+ "custom": {
+ "image": "str", # Required.
+ "entrypoint": [
+ "str" # Optional. BYO
+ container; requires adapter: custom. image is required
+ and should be digest-pinned.
+ ]
+ }
+ },
+ "defaults": {
+ "budget": {
+ "maxCostUSD": 0.0, # Optional.
+ Accepted, not yet enforced (returns a warning). Advisory
+ per-run ceilings, clamped server-side to tenant policy.
+ "maxSteps": 0, # Optional. Accepted,
+ not yet enforced (returns a warning). Advisory per-run
+ ceilings, clamped server-side to tenant policy.
+ "maxWallClockSeconds": 0, #
+ Optional. Accepted, not yet enforced (returns a warning).
+ Advisory per-run ceilings, clamped server-side to tenant
+ policy.
+ "onBreach": "str" # Optional. Known
+ values are: "pause", "humanInput", and "fail".
+ }
+ },
+ "env": {
+ "str": "str" # Optional. Non-secret guest
+ env (debug-readable - never put secrets here; use spec.secrets).
+ Reserved platform keys (TEAM_ID, SESSION_ID, SANDBOX_ID,
+ CONTROL_PLANE_CALLBACK_URL, SANDBOX_TEMPLATE,
+ SANDBOX_AGENT_WORKDIR, SIZE_SLUG, SANDBOX_IMAGE_ID,
+ SANDBOX_OCI_REF, PLANO"" *PERMISSION*"" *) are rejected.
+ Credential-looking values (dop"" *v1*..., sk-..., ghp_...)
+ trigger a create-time warning.
+ },
+ "memory": {
+ "backend": "str", # Required.
+ "scope": "str" # Optional. Known values are:
+ "tenant", "user", "agent", and "session".
+ },
+ "mode": "str", # Optional. Explicit lifecycle
+ discriminator. Defaults to "interactive" (spec.serving forbidden);
+ "served" requires spec.serving. Known values are: "interactive" and
+ "served".
+ "model": {
+ "default": "str", # Optional. Accepted, not
+ yet enforced (returns a warning). Model routing (Plano);
+ catalog-validated when enforcement lands.
+ "profile": "str", # Optional. Accepted, not
+ yet enforced (returns a warning). Model routing (Plano);
+ catalog-validated when enforcement lands.
+ "routing": "str" # Optional. Accepted, not
+ yet enforced (returns a warning). Model routing (Plano);
+ catalog-validated when enforcement lands.
+ },
+ "permissions": {
+ "defaultAction": "str", # Optional.
+ Disposition for tool calls that match no rule. Defaults to "ask"
+ when omitted. Known values are: "allow", "ask", and "deny".
+ "filesystem": {
+ "allowWrite": [
+ "str" # Optional. Additional
+ writable paths beyond the workspace. Values must not
+ contain shell-style ${VAR}/$VAR expansions.
+ ],
+ "mode": "str" # Optional. Known
+ values are: "read-only" and "workspace-write".
+ },
+ "network": {
+ "allow": [
+ "str" # Optional. Network
+ boundary. Narrows (subtract-only) spec.sandbox.egress;
+ link-local/internal addresses stay blocked by the broader
+ egress policy.
+ ],
+ "default": "str" # Optional. Known
+ values are: "allow" and "deny".
+ },
+ "rules": [
+ {
+ "action": "str", # Required.
+ Known values are: "allow", "ask", and "deny".
+ "tool": "str", # Tool
+ taxonomy this rule matches (e.g. bash, file.read,
+ file.write, web.fetch, git.*, mcp). Required.
+ "enforcement": "str", #
+ Optional. What happens when the agent cannot enforce the
+ rule exactly. "strict" rejects the session; "best-effort"
+ degrades to the closest more-restrictive form and warns
+ (never widens). Defaults to strict for deny rules,
+ best-effort otherwise. Known values are: "strict" and
+ "best-effort".
+ "match": {
+ "str": "str" #
+ Optional. Optional keys narrowing the rule (e.g.
+ {"command": "npm run deploy"} for bash). Values are
+ globs and must not contain shell-style ${VAR}/$VAR
+ expansions.
+ }
+ }
+ ]
+ },
+ "sandbox": {
+ "egress": {
+ "allow": [
+ {
+ "host": "str" #
+ Required.
+ }
+ ],
+ "allowIps": [
+ "str" # Optional. Exact
+ IPv4/IPv6 literals (not CIDRs).
+ ],
+ "subnetUuid": "str", # Optional.
+ Optional subnet within vpcUuid.
+ "unrestricted": bool, # Optional.
+ When true, opts out of the platform-default host allowlist
+ union. Mutually exclusive with allow / allowIps / vpcUuid /
+ subnetUuid.
+ "vpcUuid": "str" # Optional.
+ Customer VPC UUID. Create-time immutable.
+ },
+ "idleTimeoutSeconds": 0, # Optional.
+ Inactivity suspend timeout. 0 means tenant policy default.
+ "maxLifetimeSeconds": 0, # Optional. Hard
+ wall-clock ceiling for the whole session, independent of
+ activity. Accepted, not yet enforced (returns a warning).
+ "mounts": [
+ {
+ "accessKeyRef": "str", #
+ Names a declared tenantSecret slot in spec.secrets.
+ Required.
+ "bucket": "str", # Required.
+ "path": "str", # Absolute
+ guest path the mount appears at. Required.
+ "secretKeyRef": "str", #
+ Names a declared tenantSecret slot in spec.secrets.
+ Required.
+ "type": "str", # Required.
+ "s3fuse"
+ "endpoint": "str", #
+ Optional. Optional storage endpoint override; https://
+ only.
+ "readOnly": bool # Optional.
+ Requested data mounts. Accepted, not yet enforced
+ (returns a warning). accessKeyRef/secretKeyRef name
+ declared tenantSecret slots in spec.secrets, validated at
+ create; declare those slots with env: false so the keys
+ stay mount-scoped and out of the guest env.
+ }
+ ],
+ "persistentWorkspace": bool, # Optional.
+ Canonical runnable environment spec JSON, immutable after create.
+ Validated non-secret spec.env and spec.permissions remain;
+ spec.secrets retains name/source/provider but omits ref and the
+ write-only value; metadata.name is cleared while safe metadata
+ such as labels remains. Required.
+ "sizeSlug": "str", # Optional. Requested
+ sandbox size (catalog: GET /v2/agents/sessions/sandbox/sizes).
+ Empty means the service default.
+ "template": "str" # Optional. Optional
+ sandbox template. Empty (or the legacy placeholder "coding")
+ means "no preference": the template derives from the adapter.
+ },
+ "secrets": [
+ {
+ "name": "str", # Required.
+ "source": "str", # Required. Known
+ values are: "oauth" and "tenantSecret".
+ "env": bool, # Optional. Whether the
+ resolved credential is injected into the guest env. Omitted
+ means true; false is for mount-only slots (tenantSecret
+ only).
+ "provider": "str", # Optional.
+ Declared credential requirements. source tenantSecret is
+ enforced today: value is write-only plaintext, extracted into
+ Secrets Manager at create and never persisted or returned.
+ source oauth requires provider, carries no value, and is
+ accepted but not yet enforced. ref is legacy and ignored. env
+ false keeps the resolved value out of the guest environment
+ (mount-only slots).
+ "ref": "str", # Optional. Declared
+ credential requirements. source tenantSecret is enforced
+ today: value is write-only plaintext, extracted into Secrets
+ Manager at create and never persisted or returned. source
+ oauth requires provider, carries no value, and is accepted
+ but not yet enforced. ref is legacy and ignored. env false
+ keeps the resolved value out of the guest environment
+ (mount-only slots).
+ "value": "str" # Optional.
+ Write-only tenantSecret plaintext; never persisted or
+ returned.
+ }
+ ],
+ "serving": {
+ "maxReplicas": 0, # Optional. Present only
+ when spec.mode is "served" (autoscaled fleet).
+ "minReplicas": 0, # Optional. Present only
+ when spec.mode is "served" (autoscaled fleet).
+ "scaleToZero": {
+ "idleSeconds": 0 # Optional. Present
+ only when spec.mode is "served" (autoscaled fleet).
+ },
+ "targetConcurrency": 0 # Optional. Present
+ only when spec.mode is "served" (autoscaled fleet).
+ },
+ "skills": [
+ {
+ "description": "str", #
+ Load-bearing: the agent reads it to decide WHEN to load the
+ skill (progressive disclosure); write it as "Use when ...".
+ Max 1024 chars. Required.
+ "instructions": "str", # The
+ markdown body (the content below the SKILL.md frontmatter).
+ Max 32 KiB. Required.
+ "name": "str", # Unique across the
+ list; 1-64 chars of lowercase letters, digits, and single
+ hyphen separators - no consecutive hyphens, per the Agent
+ Skills spec (safe as a directory name at materialization).
+ Required.
+ "allowedTools": [
+ "str" # Optional. Advisory
+ scoping of which tools the skill expects to use
+ (experimental in the skills standard). NOT a security
+ boundary - spec.permissions remains the only enforcement
+ surface.
+ ],
+ "license": "str", # Optional.
+ Optional standard passthrough (e.g. Apache-2.0).
+ "metadata": {
+ "str": "str" # Optional.
+ Optional string-map passthrough (e.g. author), rendered
+ into the frontmatter verbatim.
+ }
+ }
+ ],
+ "tools": {
+ "bundle": "str", # Optional. Accepted, not
+ yet enforced (returns a warning). Exactly one of mcpServers or
+ bundle.
+ "mcpServers": [
+ {
+ "auth": {
+ "secretRef": "str",
+ # Tenant-vault secret name. Required.
+ "header": "str" #
+ Optional. HTTP header the credential is sent in.
+ Defaults to Authorization.
+ },
+ "name": "str", # Optional.
+ Inline server name (required with url): 1-64 chars of
+ lowercase letters, digits, '-', '.', '_', starting/ending
+ alphanumeric. Unique across the list. Must not start with
+ do. (reserved for catalog refs).
+ "preloadTools": [
+ "str" # Optional.
+ Catalog form only. Individual tools (optional integer
+ pin) advertised directly in the session MCP
+ tools/list next to the
+ action_search/action_invoke/action_code meta tools.
+ Each entry must appear in tools when tools is set;
+ toolbelt references are rejected. Every preloaded
+ schema is in the model's context on every turn, so
+ keep this to a handful of tools. Omitted means
+ nothing is preloaded.
+ ],
+ "ref": "str", # Optional.
+ DO-owned catalog reference (catalog form); do.* only,
+ e.g. do.actions. Mutually exclusive with name/url/auth.
+ "tools": [
+ "str" # Optional.
+ Optional selection allowlist; omitted means all tools
+ the server advertises. Each entry is an individual
+ tool name with an optional integer version pin (e.g.
+ web_search, execute_code@3) or a toolbelt reference -
+ a server-defined named tool group written
+ toolbelt:[@:code:``] (e.g.
+ toolbelt:read-only@1; catalog refs only). Versions
+ are integer pins (no semver). The server owns belt
+ expansion; a pinned tool or belt attaches exactly
+ that version, an unpinned one resolves at session
+ create and is frozen for the session (no floating
+ latest). Entries non-empty, unique per server. The
+ selection bounds the session and is never preloaded
+ into the session MCP tools/list; see preloadTools.
+ ],
+ "url": "str" # Optional.
+ Inline server endpoint; https:// only.
+ }
+ ]
+ },
+ "workspace": {
+ "repos": [
+ "str" # Optional. GitHub OWNER/REPO
+ entries, unique. The first entry becomes the session's
+ repo_hint; the full list is the forward shape for multi-repo
+ sessions.
+ ]
+ }
+ }
+ },
+ "name": "str", # Required.
+ "updated_at": "2020-02-20 00:00:00", # Required.
+ "credentials": [
+ {
+ "name": "str", # Required.
+ "provider": "str", # Optional. Redacted credential
+ slot metadata (name/source/provider). Secret values are never
+ included.
+ "source": "str" # Optional. Known values are:
+ "tenantSecret" and "oauth".
+ }
+ ],
+ "insights": {
+ "logs": bool, # Optional. Whether the agent's logs are sent
+ to Insights.
+ "metrics": bool, # Optional. Accepted and stored for parity
+ with the Insights schema, but metrics are always collected: unregistered
+ metrics are dropped at ingest rather than opted out of here.
+ "traces": bool # Optional. Whether the agent's traces are
+ sent to Insights.
+ }
+ }
+ }
+ # response body for status code(s): 400, 409, 413, 415
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+
+ @distributed_trace_async
+ async def create_config(self, body: Union[JSON, IO[bytes]], **kwargs: Any) -> JSON:
+ # pylint: disable=line-too-long
+ """Create an Environment Config (environment spec + optional Insights opt-in).
+
+ Accepts name, environment-spec YAML text, and optional Insights telemetry opt-in. Tenant
+ secrets are declared inside the environment spec (write-only values), not as sibling request
+ fields. Responses never echo secret values; GET/create may include credential slot metadata
+ (name/source/provider only). Configs are immutable after create.
+
+ :param body: Environment Config create body. Secret values live in the environment-spec YAML
+ and are never returned. Is either a JSON type or a IO[bytes] type. Required.
+ :type body: JSON or IO[bytes]
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "manifest_yaml": "str", # Customer environment-spec YAML text. The HTTP JSON
+ body is capped at 1 MiB and this field is capped at 512 KiB. Required.
+ "name": "str", # Config name, case-insensitively unique among the team's
+ active configs. Required.
+ "insights": {
+ "logs": bool, # Optional. Whether the agent's logs are sent to
+ Insights.
+ "metrics": bool, # Optional. Accepted and stored for parity with the
+ Insights schema, but metrics are always collected: unregistered metrics are
+ dropped at ingest rather than opted out of here.
+ "traces": bool # Optional. Whether the agent's traces are sent to
+ Insights.
+ }
+ }
+
+ # response body for status code(s): 201
+ response == {
+ "config": {
+ "agentspec_schema_version": "str", # The manifest contract the
+ server accepted at create time: the manifest's own apiVersion for legacy
+ envelope parses (currently agents.digitalocean.com/v1alpha1), or
+ agents.digitalocean.com/flat.v1 for flat-format parses. Required.
+ "content_hash": "str", # Lowercase SHA-256 hex digest of the
+ canonical sanitized manifest JSON. Required.
+ "created_at": "2020-02-20 00:00:00", # Required.
+ "created_by": "str", # Authenticated user identity that created the
+ config. Required.
+ "id": "str", # Required.
+ "manifest": {
+ "apiVersion": "str", # Optional. Legacy envelope only - must
+ be "agents.digitalocean.com/v1alpha1", and its presence is what routes
+ the document to the deprecated legacy parser. Flat-format manifests carry
+ no version key (the endpoint owns the contract); required, with kind and
+ spec, when authoring the legacy format.
+ "agents.digitalocean.com/v1alpha1"
+ "kind": "str", # Optional. Must be "Agent". "Agent"
+ "metadata": {
+ "description": "str", # Optional. Free-form
+ description (max 1024 chars), stored and echoed back for Console /
+ catalog surfaces.
+ "labels": {
+ "str": "str" # Optional. Dictionary of
+ :code:``.
+ },
+ "name": "str" # Optional. Optional team-unique
+ session name: 1-64 chars of letters, digits, '-', '.', '_', starting
+ and ending alphanumeric; case-insensitive; must not be UUID-shaped.
+ Omit to have the control plane generate one
+ ("session-:code:``-:code:``"). Unique among
+ the team's ACTIVE (non-terminal) sessions; destroying a session frees
+ its name for reuse.
+ },
+ "spec": {
+ "runtime": {
+ "adapter": "str", # Required. Known values
+ are: "claude-code", "opencode", "codex", "cursor", "hermes",
+ "codex-agentapi", "custom", "codex-cli", "cursor-cli",
+ "openai-agents", "claude-agent-sdk", "crewai", and "langgraph".
+ "config": {
+ "str": {} # Optional. OPAQUE,
+ provider-specific runtime config. Only for adapter:
+ codex-agentapi today, where it is the OpenAI Agents API
+ create-session body (agent/environment/input) that doctl
+ forwards verbatim to OpenAI's POST /v1/agents/sessions;
+ harness-api stores and echoes it but never parses or
+ validates its contents (so DO stays forward-compatible as
+ OpenAI's schema evolves). The OpenAI session_id is passed on
+ the create call (the openai_session_id query parameter), not
+ in this block.
+ },
+ "custom": {
+ "image": "str", # Required.
+ "entrypoint": [
+ "str" # Optional. BYO
+ container; requires adapter: custom. image is required
+ and should be digest-pinned.
+ ]
+ }
+ },
+ "defaults": {
+ "budget": {
+ "maxCostUSD": 0.0, # Optional.
+ Accepted, not yet enforced (returns a warning). Advisory
+ per-run ceilings, clamped server-side to tenant policy.
+ "maxSteps": 0, # Optional. Accepted,
+ not yet enforced (returns a warning). Advisory per-run
+ ceilings, clamped server-side to tenant policy.
+ "maxWallClockSeconds": 0, #
+ Optional. Accepted, not yet enforced (returns a warning).
+ Advisory per-run ceilings, clamped server-side to tenant
+ policy.
+ "onBreach": "str" # Optional. Known
+ values are: "pause", "humanInput", and "fail".
+ }
+ },
+ "env": {
+ "str": "str" # Optional. Non-secret guest
+ env (debug-readable - never put secrets here; use spec.secrets).
+ Reserved platform keys (TEAM_ID, SESSION_ID, SANDBOX_ID,
+ CONTROL_PLANE_CALLBACK_URL, SANDBOX_TEMPLATE,
+ SANDBOX_AGENT_WORKDIR, SIZE_SLUG, SANDBOX_IMAGE_ID,
+ SANDBOX_OCI_REF, PLANO"" *PERMISSION*"" *) are rejected.
+ Credential-looking values (dop"" *v1*..., sk-..., ghp_...)
+ trigger a create-time warning.
+ },
+ "memory": {
+ "backend": "str", # Required.
+ "scope": "str" # Optional. Known values are:
+ "tenant", "user", "agent", and "session".
+ },
+ "mode": "str", # Optional. Explicit lifecycle
+ discriminator. Defaults to "interactive" (spec.serving forbidden);
+ "served" requires spec.serving. Known values are: "interactive" and
+ "served".
+ "model": {
+ "default": "str", # Optional. Accepted, not
+ yet enforced (returns a warning). Model routing (Plano);
+ catalog-validated when enforcement lands.
+ "profile": "str", # Optional. Accepted, not
+ yet enforced (returns a warning). Model routing (Plano);
+ catalog-validated when enforcement lands.
+ "routing": "str" # Optional. Accepted, not
+ yet enforced (returns a warning). Model routing (Plano);
+ catalog-validated when enforcement lands.
+ },
+ "permissions": {
+ "defaultAction": "str", # Optional.
+ Disposition for tool calls that match no rule. Defaults to "ask"
+ when omitted. Known values are: "allow", "ask", and "deny".
+ "filesystem": {
+ "allowWrite": [
+ "str" # Optional. Additional
+ writable paths beyond the workspace. Values must not
+ contain shell-style ${VAR}/$VAR expansions.
+ ],
+ "mode": "str" # Optional. Known
+ values are: "read-only" and "workspace-write".
+ },
+ "network": {
+ "allow": [
+ "str" # Optional. Network
+ boundary. Narrows (subtract-only) spec.sandbox.egress;
+ link-local/internal addresses stay blocked by the broader
+ egress policy.
+ ],
+ "default": "str" # Optional. Known
+ values are: "allow" and "deny".
+ },
+ "rules": [
+ {
+ "action": "str", # Required.
+ Known values are: "allow", "ask", and "deny".
+ "tool": "str", # Tool
+ taxonomy this rule matches (e.g. bash, file.read,
+ file.write, web.fetch, git.*, mcp). Required.
+ "enforcement": "str", #
+ Optional. What happens when the agent cannot enforce the
+ rule exactly. "strict" rejects the session; "best-effort"
+ degrades to the closest more-restrictive form and warns
+ (never widens). Defaults to strict for deny rules,
+ best-effort otherwise. Known values are: "strict" and
+ "best-effort".
+ "match": {
+ "str": "str" #
+ Optional. Optional keys narrowing the rule (e.g.
+ {"command": "npm run deploy"} for bash). Values are
+ globs and must not contain shell-style ${VAR}/$VAR
+ expansions.
+ }
+ }
+ ]
+ },
+ "sandbox": {
+ "egress": {
+ "allow": [
+ {
+ "host": "str" #
+ Required.
+ }
+ ],
+ "allowIps": [
+ "str" # Optional. Exact
+ IPv4/IPv6 literals (not CIDRs).
+ ],
+ "subnetUuid": "str", # Optional.
+ Optional subnet within vpcUuid.
+ "unrestricted": bool, # Optional.
+ When true, opts out of the platform-default host allowlist
+ union. Mutually exclusive with allow / allowIps / vpcUuid /
+ subnetUuid.
+ "vpcUuid": "str" # Optional.
+ Customer VPC UUID. Create-time immutable.
+ },
+ "idleTimeoutSeconds": 0, # Optional.
+ Inactivity suspend timeout. 0 means tenant policy default.
+ "maxLifetimeSeconds": 0, # Optional. Hard
+ wall-clock ceiling for the whole session, independent of
+ activity. Accepted, not yet enforced (returns a warning).
+ "mounts": [
+ {
+ "accessKeyRef": "str", #
+ Names a declared tenantSecret slot in spec.secrets.
+ Required.
+ "bucket": "str", # Required.
+ "path": "str", # Absolute
+ guest path the mount appears at. Required.
+ "secretKeyRef": "str", #
+ Names a declared tenantSecret slot in spec.secrets.
+ Required.
+ "type": "str", # Required.
+ "s3fuse"
+ "endpoint": "str", #
+ Optional. Optional storage endpoint override; https://
+ only.
+ "readOnly": bool # Optional.
+ Requested data mounts. Accepted, not yet enforced
+ (returns a warning). accessKeyRef/secretKeyRef name
+ declared tenantSecret slots in spec.secrets, validated at
+ create; declare those slots with env: false so the keys
+ stay mount-scoped and out of the guest env.
+ }
+ ],
+ "persistentWorkspace": bool, # Optional.
+ Canonical runnable environment spec JSON, immutable after create.
+ Validated non-secret spec.env and spec.permissions remain;
+ spec.secrets retains name/source/provider but omits ref and the
+ write-only value; metadata.name is cleared while safe metadata
+ such as labels remains. Required.
+ "sizeSlug": "str", # Optional. Requested
+ sandbox size (catalog: GET /v2/agents/sessions/sandbox/sizes).
+ Empty means the service default.
+ "template": "str" # Optional. Optional
+ sandbox template. Empty (or the legacy placeholder "coding")
+ means "no preference": the template derives from the adapter.
+ },
+ "secrets": [
+ {
+ "name": "str", # Required.
+ "source": "str", # Required. Known
+ values are: "oauth" and "tenantSecret".
+ "env": bool, # Optional. Whether the
+ resolved credential is injected into the guest env. Omitted
+ means true; false is for mount-only slots (tenantSecret
+ only).
+ "provider": "str", # Optional.
+ Declared credential requirements. source tenantSecret is
+ enforced today: value is write-only plaintext, extracted into
+ Secrets Manager at create and never persisted or returned.
+ source oauth requires provider, carries no value, and is
+ accepted but not yet enforced. ref is legacy and ignored. env
+ false keeps the resolved value out of the guest environment
+ (mount-only slots).
+ "ref": "str", # Optional. Declared
+ credential requirements. source tenantSecret is enforced
+ today: value is write-only plaintext, extracted into Secrets
+ Manager at create and never persisted or returned. source
+ oauth requires provider, carries no value, and is accepted
+ but not yet enforced. ref is legacy and ignored. env false
+ keeps the resolved value out of the guest environment
+ (mount-only slots).
+ "value": "str" # Optional.
+ Write-only tenantSecret plaintext; never persisted or
+ returned.
+ }
+ ],
+ "serving": {
+ "maxReplicas": 0, # Optional. Present only
+ when spec.mode is "served" (autoscaled fleet).
+ "minReplicas": 0, # Optional. Present only
+ when spec.mode is "served" (autoscaled fleet).
+ "scaleToZero": {
+ "idleSeconds": 0 # Optional. Present
+ only when spec.mode is "served" (autoscaled fleet).
+ },
+ "targetConcurrency": 0 # Optional. Present
+ only when spec.mode is "served" (autoscaled fleet).
+ },
+ "skills": [
+ {
+ "description": "str", #
+ Load-bearing: the agent reads it to decide WHEN to load the
+ skill (progressive disclosure); write it as "Use when ...".
+ Max 1024 chars. Required.
+ "instructions": "str", # The
+ markdown body (the content below the SKILL.md frontmatter).
+ Max 32 KiB. Required.
+ "name": "str", # Unique across the
+ list; 1-64 chars of lowercase letters, digits, and single
+ hyphen separators - no consecutive hyphens, per the Agent
+ Skills spec (safe as a directory name at materialization).
+ Required.
+ "allowedTools": [
+ "str" # Optional. Advisory
+ scoping of which tools the skill expects to use
+ (experimental in the skills standard). NOT a security
+ boundary - spec.permissions remains the only enforcement
+ surface.
+ ],
+ "license": "str", # Optional.
+ Optional standard passthrough (e.g. Apache-2.0).
+ "metadata": {
+ "str": "str" # Optional.
+ Optional string-map passthrough (e.g. author), rendered
+ into the frontmatter verbatim.
+ }
+ }
+ ],
+ "tools": {
+ "bundle": "str", # Optional. Accepted, not
+ yet enforced (returns a warning). Exactly one of mcpServers or
+ bundle.
+ "mcpServers": [
+ {
+ "auth": {
+ "secretRef": "str",
+ # Tenant-vault secret name. Required.
+ "header": "str" #
+ Optional. HTTP header the credential is sent in.
+ Defaults to Authorization.
+ },
+ "name": "str", # Optional.
+ Inline server name (required with url): 1-64 chars of
+ lowercase letters, digits, '-', '.', '_', starting/ending
+ alphanumeric. Unique across the list. Must not start with
+ do. (reserved for catalog refs).
+ "preloadTools": [
+ "str" # Optional.
+ Catalog form only. Individual tools (optional integer
+ pin) advertised directly in the session MCP
+ tools/list next to the
+ action_search/action_invoke/action_code meta tools.
+ Each entry must appear in tools when tools is set;
+ toolbelt references are rejected. Every preloaded
+ schema is in the model's context on every turn, so
+ keep this to a handful of tools. Omitted means
+ nothing is preloaded.
+ ],
+ "ref": "str", # Optional.
+ DO-owned catalog reference (catalog form); do.* only,
+ e.g. do.actions. Mutually exclusive with name/url/auth.
+ "tools": [
+ "str" # Optional.
+ Optional selection allowlist; omitted means all tools
+ the server advertises. Each entry is an individual
+ tool name with an optional integer version pin (e.g.
+ web_search, execute_code@3) or a toolbelt reference -
+ a server-defined named tool group written
+ toolbelt:[@:code:``] (e.g.
+ toolbelt:read-only@1; catalog refs only). Versions
+ are integer pins (no semver). The server owns belt
+ expansion; a pinned tool or belt attaches exactly
+ that version, an unpinned one resolves at session
+ create and is frozen for the session (no floating
+ latest). Entries non-empty, unique per server. The
+ selection bounds the session and is never preloaded
+ into the session MCP tools/list; see preloadTools.
+ ],
+ "url": "str" # Optional.
+ Inline server endpoint; https:// only.
+ }
+ ]
+ },
+ "workspace": {
+ "repos": [
+ "str" # Optional. GitHub OWNER/REPO
+ entries, unique. The first entry becomes the session's
+ repo_hint; the full list is the forward shape for multi-repo
+ sessions.
+ ]
+ }
+ }
+ },
+ "name": "str", # Required.
+ "updated_at": "2020-02-20 00:00:00", # Required.
+ "credentials": [
+ {
+ "name": "str", # Required.
+ "provider": "str", # Optional. Redacted credential
+ slot metadata (name/source/provider). Secret values are never
+ included.
+ "source": "str" # Optional. Known values are:
+ "tenantSecret" and "oauth".
+ }
+ ],
+ "insights": {
+ "logs": bool, # Optional. Whether the agent's logs are sent
+ to Insights.
+ "metrics": bool, # Optional. Accepted and stored for parity
+ with the Insights schema, but metrics are always collected: unregistered
+ metrics are dropped at ingest rather than opted out of here.
+ "traces": bool # Optional. Whether the agent's traces are
+ sent to Insights.
+ }
+ }
+ }
+ # response body for status code(s): 400, 409, 413, 415
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
+ _params = kwargs.pop("params", {}) or {}
+
+ content_type: Optional[str] = kwargs.pop(
+ "content_type", _headers.pop("Content-Type", None)
+ )
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ content_type = content_type or "application/json"
+ _json = None
+ _content = None
+ if isinstance(body, (IOBase, bytes)):
+ _content = body
+ else:
+ _json = body
+
+ _request = build_harness_create_config_request(
+ content_type=content_type,
+ json=_json,
+ content=_content,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [201, 400, 409, 413, 415]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ if response.status_code == 201:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 400:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 409:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 413:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 415:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+ @distributed_trace_async
+ async def get_config(self, config_id: str, **kwargs: Any) -> JSON:
+ # pylint: disable=line-too-long
+ """Get an active Environment Config and its environment spec.
+
+ Returns one team-scoped Environment Config including the sanitized environment spec and
+ redacted credential slot metadata. Secret values are never returned.
+
+ :param config_id: The Environment Config UUID. Required.
+ :type config_id: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 200
+ response == {
+ "config": {
+ "agentspec_schema_version": "str", # The manifest contract the
+ server accepted at create time: the manifest's own apiVersion for legacy
+ envelope parses (currently agents.digitalocean.com/v1alpha1), or
+ agents.digitalocean.com/flat.v1 for flat-format parses. Required.
+ "content_hash": "str", # Lowercase SHA-256 hex digest of the
+ canonical sanitized manifest JSON. Required.
+ "created_at": "2020-02-20 00:00:00", # Required.
+ "created_by": "str", # Authenticated user identity that created the
+ config. Required.
+ "id": "str", # Required.
+ "manifest": {
+ "apiVersion": "str", # Optional. Legacy envelope only - must
+ be "agents.digitalocean.com/v1alpha1", and its presence is what routes
+ the document to the deprecated legacy parser. Flat-format manifests carry
+ no version key (the endpoint owns the contract); required, with kind and
+ spec, when authoring the legacy format.
+ "agents.digitalocean.com/v1alpha1"
+ "kind": "str", # Optional. Must be "Agent". "Agent"
+ "metadata": {
+ "description": "str", # Optional. Free-form
+ description (max 1024 chars), stored and echoed back for Console /
+ catalog surfaces.
+ "labels": {
+ "str": "str" # Optional. Dictionary of
+ :code:``.
+ },
+ "name": "str" # Optional. Optional team-unique
+ session name: 1-64 chars of letters, digits, '-', '.', '_', starting
+ and ending alphanumeric; case-insensitive; must not be UUID-shaped.
+ Omit to have the control plane generate one
+ ("session-:code:``-:code:``"). Unique among
+ the team's ACTIVE (non-terminal) sessions; destroying a session frees
+ its name for reuse.
+ },
+ "spec": {
+ "runtime": {
+ "adapter": "str", # Required. Known values
+ are: "claude-code", "opencode", "codex", "cursor", "hermes",
+ "codex-agentapi", "custom", "codex-cli", "cursor-cli",
+ "openai-agents", "claude-agent-sdk", "crewai", and "langgraph".
+ "config": {
+ "str": {} # Optional. OPAQUE,
+ provider-specific runtime config. Only for adapter:
+ codex-agentapi today, where it is the OpenAI Agents API
+ create-session body (agent/environment/input) that doctl
+ forwards verbatim to OpenAI's POST /v1/agents/sessions;
+ harness-api stores and echoes it but never parses or
+ validates its contents (so DO stays forward-compatible as
+ OpenAI's schema evolves). The OpenAI session_id is passed on
+ the create call (the openai_session_id query parameter), not
+ in this block.
+ },
+ "custom": {
+ "image": "str", # Required.
+ "entrypoint": [
+ "str" # Optional. BYO
+ container; requires adapter: custom. image is required
+ and should be digest-pinned.
+ ]
+ }
+ },
+ "defaults": {
+ "budget": {
+ "maxCostUSD": 0.0, # Optional.
+ Accepted, not yet enforced (returns a warning). Advisory
+ per-run ceilings, clamped server-side to tenant policy.
+ "maxSteps": 0, # Optional. Accepted,
+ not yet enforced (returns a warning). Advisory per-run
+ ceilings, clamped server-side to tenant policy.
+ "maxWallClockSeconds": 0, #
+ Optional. Accepted, not yet enforced (returns a warning).
+ Advisory per-run ceilings, clamped server-side to tenant
+ policy.
+ "onBreach": "str" # Optional. Known
+ values are: "pause", "humanInput", and "fail".
+ }
+ },
+ "env": {
+ "str": "str" # Optional. Non-secret guest
+ env (debug-readable - never put secrets here; use spec.secrets).
+ Reserved platform keys (TEAM_ID, SESSION_ID, SANDBOX_ID,
+ CONTROL_PLANE_CALLBACK_URL, SANDBOX_TEMPLATE,
+ SANDBOX_AGENT_WORKDIR, SIZE_SLUG, SANDBOX_IMAGE_ID,
+ SANDBOX_OCI_REF, PLANO"" *PERMISSION*"" *) are rejected.
+ Credential-looking values (dop"" *v1*..., sk-..., ghp_...)
+ trigger a create-time warning.
+ },
+ "memory": {
+ "backend": "str", # Required.
+ "scope": "str" # Optional. Known values are:
+ "tenant", "user", "agent", and "session".
+ },
+ "mode": "str", # Optional. Explicit lifecycle
+ discriminator. Defaults to "interactive" (spec.serving forbidden);
+ "served" requires spec.serving. Known values are: "interactive" and
+ "served".
+ "model": {
+ "default": "str", # Optional. Accepted, not
+ yet enforced (returns a warning). Model routing (Plano);
+ catalog-validated when enforcement lands.
+ "profile": "str", # Optional. Accepted, not
+ yet enforced (returns a warning). Model routing (Plano);
+ catalog-validated when enforcement lands.
+ "routing": "str" # Optional. Accepted, not
+ yet enforced (returns a warning). Model routing (Plano);
+ catalog-validated when enforcement lands.
+ },
+ "permissions": {
+ "defaultAction": "str", # Optional.
+ Disposition for tool calls that match no rule. Defaults to "ask"
+ when omitted. Known values are: "allow", "ask", and "deny".
+ "filesystem": {
+ "allowWrite": [
+ "str" # Optional. Additional
+ writable paths beyond the workspace. Values must not
+ contain shell-style ${VAR}/$VAR expansions.
+ ],
+ "mode": "str" # Optional. Known
+ values are: "read-only" and "workspace-write".
+ },
+ "network": {
+ "allow": [
+ "str" # Optional. Network
+ boundary. Narrows (subtract-only) spec.sandbox.egress;
+ link-local/internal addresses stay blocked by the broader
+ egress policy.
+ ],
+ "default": "str" # Optional. Known
+ values are: "allow" and "deny".
+ },
+ "rules": [
+ {
+ "action": "str", # Required.
+ Known values are: "allow", "ask", and "deny".
+ "tool": "str", # Tool
+ taxonomy this rule matches (e.g. bash, file.read,
+ file.write, web.fetch, git.*, mcp). Required.
+ "enforcement": "str", #
+ Optional. What happens when the agent cannot enforce the
+ rule exactly. "strict" rejects the session; "best-effort"
+ degrades to the closest more-restrictive form and warns
+ (never widens). Defaults to strict for deny rules,
+ best-effort otherwise. Known values are: "strict" and
+ "best-effort".
+ "match": {
+ "str": "str" #
+ Optional. Optional keys narrowing the rule (e.g.
+ {"command": "npm run deploy"} for bash). Values are
+ globs and must not contain shell-style ${VAR}/$VAR
+ expansions.
+ }
+ }
+ ]
+ },
+ "sandbox": {
+ "egress": {
+ "allow": [
+ {
+ "host": "str" #
+ Required.
+ }
+ ],
+ "allowIps": [
+ "str" # Optional. Exact
+ IPv4/IPv6 literals (not CIDRs).
+ ],
+ "subnetUuid": "str", # Optional.
+ Optional subnet within vpcUuid.
+ "unrestricted": bool, # Optional.
+ When true, opts out of the platform-default host allowlist
+ union. Mutually exclusive with allow / allowIps / vpcUuid /
+ subnetUuid.
+ "vpcUuid": "str" # Optional.
+ Customer VPC UUID. Create-time immutable.
+ },
+ "idleTimeoutSeconds": 0, # Optional.
+ Inactivity suspend timeout. 0 means tenant policy default.
+ "maxLifetimeSeconds": 0, # Optional. Hard
+ wall-clock ceiling for the whole session, independent of
+ activity. Accepted, not yet enforced (returns a warning).
+ "mounts": [
+ {
+ "accessKeyRef": "str", #
+ Names a declared tenantSecret slot in spec.secrets.
+ Required.
+ "bucket": "str", # Required.
+ "path": "str", # Absolute
+ guest path the mount appears at. Required.
+ "secretKeyRef": "str", #
+ Names a declared tenantSecret slot in spec.secrets.
+ Required.
+ "type": "str", # Required.
+ "s3fuse"
+ "endpoint": "str", #
+ Optional. Optional storage endpoint override; https://
+ only.
+ "readOnly": bool # Optional.
+ Requested data mounts. Accepted, not yet enforced
+ (returns a warning). accessKeyRef/secretKeyRef name
+ declared tenantSecret slots in spec.secrets, validated at
+ create; declare those slots with env: false so the keys
+ stay mount-scoped and out of the guest env.
+ }
+ ],
+ "persistentWorkspace": bool, # Optional.
+ Canonical runnable environment spec JSON, immutable after create.
+ Validated non-secret spec.env and spec.permissions remain;
+ spec.secrets retains name/source/provider but omits ref and the
+ write-only value; metadata.name is cleared while safe metadata
+ such as labels remains. Required.
+ "sizeSlug": "str", # Optional. Requested
+ sandbox size (catalog: GET /v2/agents/sessions/sandbox/sizes).
+ Empty means the service default.
+ "template": "str" # Optional. Optional
+ sandbox template. Empty (or the legacy placeholder "coding")
+ means "no preference": the template derives from the adapter.
+ },
+ "secrets": [
+ {
+ "name": "str", # Required.
+ "source": "str", # Required. Known
+ values are: "oauth" and "tenantSecret".
+ "env": bool, # Optional. Whether the
+ resolved credential is injected into the guest env. Omitted
+ means true; false is for mount-only slots (tenantSecret
+ only).
+ "provider": "str", # Optional.
+ Declared credential requirements. source tenantSecret is
+ enforced today: value is write-only plaintext, extracted into
+ Secrets Manager at create and never persisted or returned.
+ source oauth requires provider, carries no value, and is
+ accepted but not yet enforced. ref is legacy and ignored. env
+ false keeps the resolved value out of the guest environment
+ (mount-only slots).
+ "ref": "str", # Optional. Declared
+ credential requirements. source tenantSecret is enforced
+ today: value is write-only plaintext, extracted into Secrets
+ Manager at create and never persisted or returned. source
+ oauth requires provider, carries no value, and is accepted
+ but not yet enforced. ref is legacy and ignored. env false
+ keeps the resolved value out of the guest environment
+ (mount-only slots).
+ "value": "str" # Optional.
+ Write-only tenantSecret plaintext; never persisted or
+ returned.
+ }
+ ],
+ "serving": {
+ "maxReplicas": 0, # Optional. Present only
+ when spec.mode is "served" (autoscaled fleet).
+ "minReplicas": 0, # Optional. Present only
+ when spec.mode is "served" (autoscaled fleet).
+ "scaleToZero": {
+ "idleSeconds": 0 # Optional. Present
+ only when spec.mode is "served" (autoscaled fleet).
+ },
+ "targetConcurrency": 0 # Optional. Present
+ only when spec.mode is "served" (autoscaled fleet).
+ },
+ "skills": [
+ {
+ "description": "str", #
+ Load-bearing: the agent reads it to decide WHEN to load the
+ skill (progressive disclosure); write it as "Use when ...".
+ Max 1024 chars. Required.
+ "instructions": "str", # The
+ markdown body (the content below the SKILL.md frontmatter).
+ Max 32 KiB. Required.
+ "name": "str", # Unique across the
+ list; 1-64 chars of lowercase letters, digits, and single
+ hyphen separators - no consecutive hyphens, per the Agent
+ Skills spec (safe as a directory name at materialization).
+ Required.
+ "allowedTools": [
+ "str" # Optional. Advisory
+ scoping of which tools the skill expects to use
+ (experimental in the skills standard). NOT a security
+ boundary - spec.permissions remains the only enforcement
+ surface.
+ ],
+ "license": "str", # Optional.
+ Optional standard passthrough (e.g. Apache-2.0).
+ "metadata": {
+ "str": "str" # Optional.
+ Optional string-map passthrough (e.g. author), rendered
+ into the frontmatter verbatim.
+ }
+ }
+ ],
+ "tools": {
+ "bundle": "str", # Optional. Accepted, not
+ yet enforced (returns a warning). Exactly one of mcpServers or
+ bundle.
+ "mcpServers": [
+ {
+ "auth": {
+ "secretRef": "str",
+ # Tenant-vault secret name. Required.
+ "header": "str" #
+ Optional. HTTP header the credential is sent in.
+ Defaults to Authorization.
+ },
+ "name": "str", # Optional.
+ Inline server name (required with url): 1-64 chars of
+ lowercase letters, digits, '-', '.', '_', starting/ending
+ alphanumeric. Unique across the list. Must not start with
+ do. (reserved for catalog refs).
+ "preloadTools": [
+ "str" # Optional.
+ Catalog form only. Individual tools (optional integer
+ pin) advertised directly in the session MCP
+ tools/list next to the
+ action_search/action_invoke/action_code meta tools.
+ Each entry must appear in tools when tools is set;
+ toolbelt references are rejected. Every preloaded
+ schema is in the model's context on every turn, so
+ keep this to a handful of tools. Omitted means
+ nothing is preloaded.
+ ],
+ "ref": "str", # Optional.
+ DO-owned catalog reference (catalog form); do.* only,
+ e.g. do.actions. Mutually exclusive with name/url/auth.
+ "tools": [
+ "str" # Optional.
+ Optional selection allowlist; omitted means all tools
+ the server advertises. Each entry is an individual
+ tool name with an optional integer version pin (e.g.
+ web_search, execute_code@3) or a toolbelt reference -
+ a server-defined named tool group written
+ toolbelt:[@:code:``] (e.g.
+ toolbelt:read-only@1; catalog refs only). Versions
+ are integer pins (no semver). The server owns belt
+ expansion; a pinned tool or belt attaches exactly
+ that version, an unpinned one resolves at session
+ create and is frozen for the session (no floating
+ latest). Entries non-empty, unique per server. The
+ selection bounds the session and is never preloaded
+ into the session MCP tools/list; see preloadTools.
+ ],
+ "url": "str" # Optional.
+ Inline server endpoint; https:// only.
+ }
+ ]
+ },
+ "workspace": {
+ "repos": [
+ "str" # Optional. GitHub OWNER/REPO
+ entries, unique. The first entry becomes the session's
+ repo_hint; the full list is the forward shape for multi-repo
+ sessions.
+ ]
+ }
+ }
+ },
+ "name": "str", # Required.
+ "updated_at": "2020-02-20 00:00:00", # Required.
+ "credentials": [
+ {
+ "name": "str", # Required.
+ "provider": "str", # Optional. Redacted credential
+ slot metadata (name/source/provider). Secret values are never
+ included.
+ "source": "str" # Optional. Known values are:
+ "tenantSecret" and "oauth".
+ }
+ ],
+ "insights": {
+ "logs": bool, # Optional. Whether the agent's logs are sent
+ to Insights.
+ "metrics": bool, # Optional. Accepted and stored for parity
+ with the Insights schema, but metrics are always collected: unregistered
+ metrics are dropped at ingest rather than opted out of here.
+ "traces": bool # Optional. Whether the agent's traces are
+ sent to Insights.
+ }
+ }
+ }
+ # response body for status code(s): 400, 404
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = kwargs.pop("headers", {}) or {}
+ _params = kwargs.pop("params", {}) or {}
+
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ _request = build_harness_get_config_request(
+ config_id=config_id,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 400, 404]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ if response.status_code == 200:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 400:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+ @distributed_trace_async
+ async def delete_config(self, config_id: str, **kwargs: Any) -> Optional[JSON]:
+ # pylint: disable=line-too-long
+ """Soft-delete an Environment Config.
+
+ Releases the active team-scoped name; the config row is retained (soft delete), so sessions
+ created from it keep a resolvable config_id.
+
+ :param config_id: The Environment Config UUID. Required.
+ :type config_id: str
+ :return: JSON object or None
+ :rtype: JSON or None
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 400, 404, 409
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = kwargs.pop("headers", {}) or {}
+ _params = kwargs.pop("params", {}) or {}
+
+ cls: ClsType[Optional[JSON]] = kwargs.pop("cls", None)
+
+ _request = build_harness_delete_config_request(
+ config_id=config_id,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [204, 400, 404, 409]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ deserialized = None
+ response_headers = {}
+ if response.status_code == 204:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.status_code == 400:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 409:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, deserialized, response_headers) # type: ignore
+
+ return deserialized # type: ignore
+
+ @overload
+ async def create_config_clone(
+ self,
+ config_id: str,
+ body: JSON,
+ *,
+ content_type: str = "application/json",
+ **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """Clone an Environment Config under a new name.
+
+ Copies the source config's sanitized manifest to a new UUID. Source and clone are independent
+ (no lineage). Credential bindings are never copied: if the manifest declares secret slots,
+ supply secrets/oauth_assignments again (write-only). content_hash matches the source when the
+ manifest is unchanged.
+
+ :param config_id: The Environment Config UUID. Required.
+ :type config_id: str
+ :param body: Clone body with required new name plus write-only credentials for any declared
+ slots. Required.
+ :type body: JSON
+ :keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
+ Default value is "application/json".
+ :paramtype content_type: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "name": "str", # New config name, unique among the team's active configs.
+ Required.
+ "oauth_assignments": {
+ "str": "str" # Optional. Write-only map from oauth logical slot to
+ an OAuth assignment UUID. Required when the source declares those slots;
+ never copied from the source.
+ },
+ "secrets": {
+ "str": "str" # Optional. Write-only map from tenantSecret logical
+ slot to plaintext. Required when the source declares those slots; never
+ copied from the source.
+ }
+ }
+
+ # response body for status code(s): 201
+ response == {
+ "config": {
+ "agentspec_schema_version": "str", # The manifest contract the
+ server accepted at create time: the manifest's own apiVersion for legacy
+ envelope parses (currently agents.digitalocean.com/v1alpha1), or
+ agents.digitalocean.com/flat.v1 for flat-format parses. Required.
+ "content_hash": "str", # Lowercase SHA-256 hex digest of the
+ canonical sanitized manifest JSON. Required.
+ "created_at": "2020-02-20 00:00:00", # Required.
+ "created_by": "str", # Authenticated user identity that created the
+ config. Required.
+ "id": "str", # Required.
+ "manifest": {
+ "apiVersion": "str", # Optional. Legacy envelope only - must
+ be "agents.digitalocean.com/v1alpha1", and its presence is what routes
+ the document to the deprecated legacy parser. Flat-format manifests carry
+ no version key (the endpoint owns the contract); required, with kind and
+ spec, when authoring the legacy format.
+ "agents.digitalocean.com/v1alpha1"
+ "kind": "str", # Optional. Must be "Agent". "Agent"
+ "metadata": {
+ "description": "str", # Optional. Free-form
+ description (max 1024 chars), stored and echoed back for Console /
+ catalog surfaces.
+ "labels": {
+ "str": "str" # Optional. Dictionary of
+ :code:``.
+ },
+ "name": "str" # Optional. Optional team-unique
+ session name: 1-64 chars of letters, digits, '-', '.', '_', starting
+ and ending alphanumeric; case-insensitive; must not be UUID-shaped.
+ Omit to have the control plane generate one
+ ("session-:code:``-:code:``"). Unique among
+ the team's ACTIVE (non-terminal) sessions; destroying a session frees
+ its name for reuse.
+ },
+ "spec": {
+ "runtime": {
+ "adapter": "str", # Required. Known values
+ are: "claude-code", "opencode", "codex", "cursor", "hermes",
+ "codex-agentapi", "custom", "codex-cli", "cursor-cli",
+ "openai-agents", "claude-agent-sdk", "crewai", and "langgraph".
+ "config": {
+ "str": {} # Optional. OPAQUE,
+ provider-specific runtime config. Only for adapter:
+ codex-agentapi today, where it is the OpenAI Agents API
+ create-session body (agent/environment/input) that doctl
+ forwards verbatim to OpenAI's POST /v1/agents/sessions;
+ harness-api stores and echoes it but never parses or
+ validates its contents (so DO stays forward-compatible as
+ OpenAI's schema evolves). The OpenAI session_id is passed on
+ the create call (the openai_session_id query parameter), not
+ in this block.
+ },
+ "custom": {
+ "image": "str", # Required.
+ "entrypoint": [
+ "str" # Optional. BYO
+ container; requires adapter: custom. image is required
+ and should be digest-pinned.
+ ]
+ }
+ },
+ "defaults": {
+ "budget": {
+ "maxCostUSD": 0.0, # Optional.
+ Accepted, not yet enforced (returns a warning). Advisory
+ per-run ceilings, clamped server-side to tenant policy.
+ "maxSteps": 0, # Optional. Accepted,
+ not yet enforced (returns a warning). Advisory per-run
+ ceilings, clamped server-side to tenant policy.
+ "maxWallClockSeconds": 0, #
+ Optional. Accepted, not yet enforced (returns a warning).
+ Advisory per-run ceilings, clamped server-side to tenant
+ policy.
+ "onBreach": "str" # Optional. Known
+ values are: "pause", "humanInput", and "fail".
+ }
+ },
+ "env": {
+ "str": "str" # Optional. Non-secret guest
+ env (debug-readable - never put secrets here; use spec.secrets).
+ Reserved platform keys (TEAM_ID, SESSION_ID, SANDBOX_ID,
+ CONTROL_PLANE_CALLBACK_URL, SANDBOX_TEMPLATE,
+ SANDBOX_AGENT_WORKDIR, SIZE_SLUG, SANDBOX_IMAGE_ID,
+ SANDBOX_OCI_REF, PLANO"" *PERMISSION*"" *) are rejected.
+ Credential-looking values (dop"" *v1*..., sk-..., ghp_...)
+ trigger a create-time warning.
+ },
+ "memory": {
+ "backend": "str", # Required.
+ "scope": "str" # Optional. Known values are:
+ "tenant", "user", "agent", and "session".
+ },
+ "mode": "str", # Optional. Explicit lifecycle
+ discriminator. Defaults to "interactive" (spec.serving forbidden);
+ "served" requires spec.serving. Known values are: "interactive" and
+ "served".
+ "model": {
+ "default": "str", # Optional. Accepted, not
+ yet enforced (returns a warning). Model routing (Plano);
+ catalog-validated when enforcement lands.
+ "profile": "str", # Optional. Accepted, not
+ yet enforced (returns a warning). Model routing (Plano);
+ catalog-validated when enforcement lands.
+ "routing": "str" # Optional. Accepted, not
+ yet enforced (returns a warning). Model routing (Plano);
+ catalog-validated when enforcement lands.
+ },
+ "permissions": {
+ "defaultAction": "str", # Optional.
+ Disposition for tool calls that match no rule. Defaults to "ask"
+ when omitted. Known values are: "allow", "ask", and "deny".
+ "filesystem": {
+ "allowWrite": [
+ "str" # Optional. Additional
+ writable paths beyond the workspace. Values must not
+ contain shell-style ${VAR}/$VAR expansions.
+ ],
+ "mode": "str" # Optional. Known
+ values are: "read-only" and "workspace-write".
+ },
+ "network": {
+ "allow": [
+ "str" # Optional. Network
+ boundary. Narrows (subtract-only) spec.sandbox.egress;
+ link-local/internal addresses stay blocked by the broader
+ egress policy.
+ ],
+ "default": "str" # Optional. Known
+ values are: "allow" and "deny".
+ },
+ "rules": [
+ {
+ "action": "str", # Required.
+ Known values are: "allow", "ask", and "deny".
+ "tool": "str", # Tool
+ taxonomy this rule matches (e.g. bash, file.read,
+ file.write, web.fetch, git.*, mcp). Required.
+ "enforcement": "str", #
+ Optional. What happens when the agent cannot enforce the
+ rule exactly. "strict" rejects the session; "best-effort"
+ degrades to the closest more-restrictive form and warns
+ (never widens). Defaults to strict for deny rules,
+ best-effort otherwise. Known values are: "strict" and
+ "best-effort".
+ "match": {
+ "str": "str" #
+ Optional. Optional keys narrowing the rule (e.g.
+ {"command": "npm run deploy"} for bash). Values are
+ globs and must not contain shell-style ${VAR}/$VAR
+ expansions.
+ }
+ }
+ ]
+ },
+ "sandbox": {
+ "egress": {
+ "allow": [
+ {
+ "host": "str" #
+ Required.
+ }
+ ],
+ "allowIps": [
+ "str" # Optional. Exact
+ IPv4/IPv6 literals (not CIDRs).
+ ],
+ "subnetUuid": "str", # Optional.
+ Optional subnet within vpcUuid.
+ "unrestricted": bool, # Optional.
+ When true, opts out of the platform-default host allowlist
+ union. Mutually exclusive with allow / allowIps / vpcUuid /
+ subnetUuid.
+ "vpcUuid": "str" # Optional.
+ Customer VPC UUID. Create-time immutable.
+ },
+ "idleTimeoutSeconds": 0, # Optional.
+ Inactivity suspend timeout. 0 means tenant policy default.
+ "maxLifetimeSeconds": 0, # Optional. Hard
+ wall-clock ceiling for the whole session, independent of
+ activity. Accepted, not yet enforced (returns a warning).
+ "mounts": [
+ {
+ "accessKeyRef": "str", #
+ Names a declared tenantSecret slot in spec.secrets.
+ Required.
+ "bucket": "str", # Required.
+ "path": "str", # Absolute
+ guest path the mount appears at. Required.
+ "secretKeyRef": "str", #
+ Names a declared tenantSecret slot in spec.secrets.
+ Required.
+ "type": "str", # Required.
+ "s3fuse"
+ "endpoint": "str", #
+ Optional. Optional storage endpoint override; https://
+ only.
+ "readOnly": bool # Optional.
+ Requested data mounts. Accepted, not yet enforced
+ (returns a warning). accessKeyRef/secretKeyRef name
+ declared tenantSecret slots in spec.secrets, validated at
+ create; declare those slots with env: false so the keys
+ stay mount-scoped and out of the guest env.
+ }
+ ],
+ "persistentWorkspace": bool, # Optional.
+ Canonical runnable environment spec JSON, immutable after create.
+ Validated non-secret spec.env and spec.permissions remain;
+ spec.secrets retains name/source/provider but omits ref and the
+ write-only value; metadata.name is cleared while safe metadata
+ such as labels remains. Required.
+ "sizeSlug": "str", # Optional. Requested
+ sandbox size (catalog: GET /v2/agents/sessions/sandbox/sizes).
+ Empty means the service default.
+ "template": "str" # Optional. Optional
+ sandbox template. Empty (or the legacy placeholder "coding")
+ means "no preference": the template derives from the adapter.
+ },
+ "secrets": [
+ {
+ "name": "str", # Required.
+ "source": "str", # Required. Known
+ values are: "oauth" and "tenantSecret".
+ "env": bool, # Optional. Whether the
+ resolved credential is injected into the guest env. Omitted
+ means true; false is for mount-only slots (tenantSecret
+ only).
+ "provider": "str", # Optional.
+ Declared credential requirements. source tenantSecret is
+ enforced today: value is write-only plaintext, extracted into
+ Secrets Manager at create and never persisted or returned.
+ source oauth requires provider, carries no value, and is
+ accepted but not yet enforced. ref is legacy and ignored. env
+ false keeps the resolved value out of the guest environment
+ (mount-only slots).
+ "ref": "str", # Optional. Declared
+ credential requirements. source tenantSecret is enforced
+ today: value is write-only plaintext, extracted into Secrets
+ Manager at create and never persisted or returned. source
+ oauth requires provider, carries no value, and is accepted
+ but not yet enforced. ref is legacy and ignored. env false
+ keeps the resolved value out of the guest environment
+ (mount-only slots).
+ "value": "str" # Optional.
+ Write-only tenantSecret plaintext; never persisted or
+ returned.
+ }
+ ],
+ "serving": {
+ "maxReplicas": 0, # Optional. Present only
+ when spec.mode is "served" (autoscaled fleet).
+ "minReplicas": 0, # Optional. Present only
+ when spec.mode is "served" (autoscaled fleet).
+ "scaleToZero": {
+ "idleSeconds": 0 # Optional. Present
+ only when spec.mode is "served" (autoscaled fleet).
+ },
+ "targetConcurrency": 0 # Optional. Present
+ only when spec.mode is "served" (autoscaled fleet).
+ },
+ "skills": [
+ {
+ "description": "str", #
+ Load-bearing: the agent reads it to decide WHEN to load the
+ skill (progressive disclosure); write it as "Use when ...".
+ Max 1024 chars. Required.
+ "instructions": "str", # The
+ markdown body (the content below the SKILL.md frontmatter).
+ Max 32 KiB. Required.
+ "name": "str", # Unique across the
+ list; 1-64 chars of lowercase letters, digits, and single
+ hyphen separators - no consecutive hyphens, per the Agent
+ Skills spec (safe as a directory name at materialization).
+ Required.
+ "allowedTools": [
+ "str" # Optional. Advisory
+ scoping of which tools the skill expects to use
+ (experimental in the skills standard). NOT a security
+ boundary - spec.permissions remains the only enforcement
+ surface.
+ ],
+ "license": "str", # Optional.
+ Optional standard passthrough (e.g. Apache-2.0).
+ "metadata": {
+ "str": "str" # Optional.
+ Optional string-map passthrough (e.g. author), rendered
+ into the frontmatter verbatim.
+ }
+ }
+ ],
+ "tools": {
+ "bundle": "str", # Optional. Accepted, not
+ yet enforced (returns a warning). Exactly one of mcpServers or
+ bundle.
+ "mcpServers": [
+ {
+ "auth": {
+ "secretRef": "str",
+ # Tenant-vault secret name. Required.
+ "header": "str" #
+ Optional. HTTP header the credential is sent in.
+ Defaults to Authorization.
+ },
+ "name": "str", # Optional.
+ Inline server name (required with url): 1-64 chars of
+ lowercase letters, digits, '-', '.', '_', starting/ending
+ alphanumeric. Unique across the list. Must not start with
+ do. (reserved for catalog refs).
+ "preloadTools": [
+ "str" # Optional.
+ Catalog form only. Individual tools (optional integer
+ pin) advertised directly in the session MCP
+ tools/list next to the
+ action_search/action_invoke/action_code meta tools.
+ Each entry must appear in tools when tools is set;
+ toolbelt references are rejected. Every preloaded
+ schema is in the model's context on every turn, so
+ keep this to a handful of tools. Omitted means
+ nothing is preloaded.
+ ],
+ "ref": "str", # Optional.
+ DO-owned catalog reference (catalog form); do.* only,
+ e.g. do.actions. Mutually exclusive with name/url/auth.
+ "tools": [
+ "str" # Optional.
+ Optional selection allowlist; omitted means all tools
+ the server advertises. Each entry is an individual
+ tool name with an optional integer version pin (e.g.
+ web_search, execute_code@3) or a toolbelt reference -
+ a server-defined named tool group written
+ toolbelt:[@:code:``] (e.g.
+ toolbelt:read-only@1; catalog refs only). Versions
+ are integer pins (no semver). The server owns belt
+ expansion; a pinned tool or belt attaches exactly
+ that version, an unpinned one resolves at session
+ create and is frozen for the session (no floating
+ latest). Entries non-empty, unique per server. The
+ selection bounds the session and is never preloaded
+ into the session MCP tools/list; see preloadTools.
+ ],
+ "url": "str" # Optional.
+ Inline server endpoint; https:// only.
+ }
+ ]
+ },
+ "workspace": {
+ "repos": [
+ "str" # Optional. GitHub OWNER/REPO
+ entries, unique. The first entry becomes the session's
+ repo_hint; the full list is the forward shape for multi-repo
+ sessions.
+ ]
+ }
+ }
+ },
+ "name": "str", # Required.
+ "updated_at": "2020-02-20 00:00:00", # Required.
+ "credentials": [
+ {
+ "name": "str", # Required.
+ "provider": "str", # Optional. Redacted credential
+ slot metadata (name/source/provider). Secret values are never
+ included.
+ "source": "str" # Optional. Known values are:
+ "tenantSecret" and "oauth".
+ }
+ ],
+ "insights": {
+ "logs": bool, # Optional. Whether the agent's logs are sent
+ to Insights.
+ "metrics": bool, # Optional. Accepted and stored for parity
+ with the Insights schema, but metrics are always collected: unregistered
+ metrics are dropped at ingest rather than opted out of here.
+ "traces": bool # Optional. Whether the agent's traces are
+ sent to Insights.
+ }
+ }
+ }
+ # response body for status code(s): 400, 404, 409, 413, 415
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+
+ @overload
+ async def create_config_clone(
+ self,
+ config_id: str,
+ body: IO[bytes],
+ *,
+ content_type: str = "application/json",
+ **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """Clone an Environment Config under a new name.
+
+ Copies the source config's sanitized manifest to a new UUID. Source and clone are independent
+ (no lineage). Credential bindings are never copied: if the manifest declares secret slots,
+ supply secrets/oauth_assignments again (write-only). content_hash matches the source when the
+ manifest is unchanged.
+
+ :param config_id: The Environment Config UUID. Required.
+ :type config_id: str
+ :param body: Clone body with required new name plus write-only credentials for any declared
+ slots. Required.
+ :type body: IO[bytes]
+ :keyword content_type: Body Parameter content-type. Content type parameter for binary body.
+ Default value is "application/json".
+ :paramtype content_type: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 201
+ response == {
+ "config": {
+ "agentspec_schema_version": "str", # The manifest contract the
+ server accepted at create time: the manifest's own apiVersion for legacy
+ envelope parses (currently agents.digitalocean.com/v1alpha1), or
+ agents.digitalocean.com/flat.v1 for flat-format parses. Required.
+ "content_hash": "str", # Lowercase SHA-256 hex digest of the
+ canonical sanitized manifest JSON. Required.
+ "created_at": "2020-02-20 00:00:00", # Required.
+ "created_by": "str", # Authenticated user identity that created the
+ config. Required.
+ "id": "str", # Required.
+ "manifest": {
+ "apiVersion": "str", # Optional. Legacy envelope only - must
+ be "agents.digitalocean.com/v1alpha1", and its presence is what routes
+ the document to the deprecated legacy parser. Flat-format manifests carry
+ no version key (the endpoint owns the contract); required, with kind and
+ spec, when authoring the legacy format.
+ "agents.digitalocean.com/v1alpha1"
+ "kind": "str", # Optional. Must be "Agent". "Agent"
+ "metadata": {
+ "description": "str", # Optional. Free-form
+ description (max 1024 chars), stored and echoed back for Console /
+ catalog surfaces.
+ "labels": {
+ "str": "str" # Optional. Dictionary of
+ :code:``.
+ },
+ "name": "str" # Optional. Optional team-unique
+ session name: 1-64 chars of letters, digits, '-', '.', '_', starting
+ and ending alphanumeric; case-insensitive; must not be UUID-shaped.
+ Omit to have the control plane generate one
+ ("session-:code:``-:code:``"). Unique among
+ the team's ACTIVE (non-terminal) sessions; destroying a session frees
+ its name for reuse.
+ },
+ "spec": {
+ "runtime": {
+ "adapter": "str", # Required. Known values
+ are: "claude-code", "opencode", "codex", "cursor", "hermes",
+ "codex-agentapi", "custom", "codex-cli", "cursor-cli",
+ "openai-agents", "claude-agent-sdk", "crewai", and "langgraph".
+ "config": {
+ "str": {} # Optional. OPAQUE,
+ provider-specific runtime config. Only for adapter:
+ codex-agentapi today, where it is the OpenAI Agents API
+ create-session body (agent/environment/input) that doctl
+ forwards verbatim to OpenAI's POST /v1/agents/sessions;
+ harness-api stores and echoes it but never parses or
+ validates its contents (so DO stays forward-compatible as
+ OpenAI's schema evolves). The OpenAI session_id is passed on
+ the create call (the openai_session_id query parameter), not
+ in this block.
+ },
+ "custom": {
+ "image": "str", # Required.
+ "entrypoint": [
+ "str" # Optional. BYO
+ container; requires adapter: custom. image is required
+ and should be digest-pinned.
+ ]
+ }
+ },
+ "defaults": {
+ "budget": {
+ "maxCostUSD": 0.0, # Optional.
+ Accepted, not yet enforced (returns a warning). Advisory
+ per-run ceilings, clamped server-side to tenant policy.
+ "maxSteps": 0, # Optional. Accepted,
+ not yet enforced (returns a warning). Advisory per-run
+ ceilings, clamped server-side to tenant policy.
+ "maxWallClockSeconds": 0, #
+ Optional. Accepted, not yet enforced (returns a warning).
+ Advisory per-run ceilings, clamped server-side to tenant
+ policy.
+ "onBreach": "str" # Optional. Known
+ values are: "pause", "humanInput", and "fail".
+ }
+ },
+ "env": {
+ "str": "str" # Optional. Non-secret guest
+ env (debug-readable - never put secrets here; use spec.secrets).
+ Reserved platform keys (TEAM_ID, SESSION_ID, SANDBOX_ID,
+ CONTROL_PLANE_CALLBACK_URL, SANDBOX_TEMPLATE,
+ SANDBOX_AGENT_WORKDIR, SIZE_SLUG, SANDBOX_IMAGE_ID,
+ SANDBOX_OCI_REF, PLANO"" *PERMISSION*"" *) are rejected.
+ Credential-looking values (dop"" *v1*..., sk-..., ghp_...)
+ trigger a create-time warning.
+ },
+ "memory": {
+ "backend": "str", # Required.
+ "scope": "str" # Optional. Known values are:
+ "tenant", "user", "agent", and "session".
+ },
+ "mode": "str", # Optional. Explicit lifecycle
+ discriminator. Defaults to "interactive" (spec.serving forbidden);
+ "served" requires spec.serving. Known values are: "interactive" and
+ "served".
+ "model": {
+ "default": "str", # Optional. Accepted, not
+ yet enforced (returns a warning). Model routing (Plano);
+ catalog-validated when enforcement lands.
+ "profile": "str", # Optional. Accepted, not
+ yet enforced (returns a warning). Model routing (Plano);
+ catalog-validated when enforcement lands.
+ "routing": "str" # Optional. Accepted, not
+ yet enforced (returns a warning). Model routing (Plano);
+ catalog-validated when enforcement lands.
+ },
+ "permissions": {
+ "defaultAction": "str", # Optional.
+ Disposition for tool calls that match no rule. Defaults to "ask"
+ when omitted. Known values are: "allow", "ask", and "deny".
+ "filesystem": {
+ "allowWrite": [
+ "str" # Optional. Additional
+ writable paths beyond the workspace. Values must not
+ contain shell-style ${VAR}/$VAR expansions.
+ ],
+ "mode": "str" # Optional. Known
+ values are: "read-only" and "workspace-write".
+ },
+ "network": {
+ "allow": [
+ "str" # Optional. Network
+ boundary. Narrows (subtract-only) spec.sandbox.egress;
+ link-local/internal addresses stay blocked by the broader
+ egress policy.
+ ],
+ "default": "str" # Optional. Known
+ values are: "allow" and "deny".
+ },
+ "rules": [
+ {
+ "action": "str", # Required.
+ Known values are: "allow", "ask", and "deny".
+ "tool": "str", # Tool
+ taxonomy this rule matches (e.g. bash, file.read,
+ file.write, web.fetch, git.*, mcp). Required.
+ "enforcement": "str", #
+ Optional. What happens when the agent cannot enforce the
+ rule exactly. "strict" rejects the session; "best-effort"
+ degrades to the closest more-restrictive form and warns
+ (never widens). Defaults to strict for deny rules,
+ best-effort otherwise. Known values are: "strict" and
+ "best-effort".
+ "match": {
+ "str": "str" #
+ Optional. Optional keys narrowing the rule (e.g.
+ {"command": "npm run deploy"} for bash). Values are
+ globs and must not contain shell-style ${VAR}/$VAR
+ expansions.
+ }
+ }
+ ]
+ },
+ "sandbox": {
+ "egress": {
+ "allow": [
+ {
+ "host": "str" #
+ Required.
+ }
+ ],
+ "allowIps": [
+ "str" # Optional. Exact
+ IPv4/IPv6 literals (not CIDRs).
+ ],
+ "subnetUuid": "str", # Optional.
+ Optional subnet within vpcUuid.
+ "unrestricted": bool, # Optional.
+ When true, opts out of the platform-default host allowlist
+ union. Mutually exclusive with allow / allowIps / vpcUuid /
+ subnetUuid.
+ "vpcUuid": "str" # Optional.
+ Customer VPC UUID. Create-time immutable.
+ },
+ "idleTimeoutSeconds": 0, # Optional.
+ Inactivity suspend timeout. 0 means tenant policy default.
+ "maxLifetimeSeconds": 0, # Optional. Hard
+ wall-clock ceiling for the whole session, independent of
+ activity. Accepted, not yet enforced (returns a warning).
+ "mounts": [
+ {
+ "accessKeyRef": "str", #
+ Names a declared tenantSecret slot in spec.secrets.
+ Required.
+ "bucket": "str", # Required.
+ "path": "str", # Absolute
+ guest path the mount appears at. Required.
+ "secretKeyRef": "str", #
+ Names a declared tenantSecret slot in spec.secrets.
+ Required.
+ "type": "str", # Required.
+ "s3fuse"
+ "endpoint": "str", #
+ Optional. Optional storage endpoint override; https://
+ only.
+ "readOnly": bool # Optional.
+ Requested data mounts. Accepted, not yet enforced
+ (returns a warning). accessKeyRef/secretKeyRef name
+ declared tenantSecret slots in spec.secrets, validated at
+ create; declare those slots with env: false so the keys
+ stay mount-scoped and out of the guest env.
+ }
+ ],
+ "persistentWorkspace": bool, # Optional.
+ Canonical runnable environment spec JSON, immutable after create.
+ Validated non-secret spec.env and spec.permissions remain;
+ spec.secrets retains name/source/provider but omits ref and the
+ write-only value; metadata.name is cleared while safe metadata
+ such as labels remains. Required.
+ "sizeSlug": "str", # Optional. Requested
+ sandbox size (catalog: GET /v2/agents/sessions/sandbox/sizes).
+ Empty means the service default.
+ "template": "str" # Optional. Optional
+ sandbox template. Empty (or the legacy placeholder "coding")
+ means "no preference": the template derives from the adapter.
+ },
+ "secrets": [
+ {
+ "name": "str", # Required.
+ "source": "str", # Required. Known
+ values are: "oauth" and "tenantSecret".
+ "env": bool, # Optional. Whether the
+ resolved credential is injected into the guest env. Omitted
+ means true; false is for mount-only slots (tenantSecret
+ only).
+ "provider": "str", # Optional.
+ Declared credential requirements. source tenantSecret is
+ enforced today: value is write-only plaintext, extracted into
+ Secrets Manager at create and never persisted or returned.
+ source oauth requires provider, carries no value, and is
+ accepted but not yet enforced. ref is legacy and ignored. env
+ false keeps the resolved value out of the guest environment
+ (mount-only slots).
+ "ref": "str", # Optional. Declared
+ credential requirements. source tenantSecret is enforced
+ today: value is write-only plaintext, extracted into Secrets
+ Manager at create and never persisted or returned. source
+ oauth requires provider, carries no value, and is accepted
+ but not yet enforced. ref is legacy and ignored. env false
+ keeps the resolved value out of the guest environment
+ (mount-only slots).
+ "value": "str" # Optional.
+ Write-only tenantSecret plaintext; never persisted or
+ returned.
+ }
+ ],
+ "serving": {
+ "maxReplicas": 0, # Optional. Present only
+ when spec.mode is "served" (autoscaled fleet).
+ "minReplicas": 0, # Optional. Present only
+ when spec.mode is "served" (autoscaled fleet).
+ "scaleToZero": {
+ "idleSeconds": 0 # Optional. Present
+ only when spec.mode is "served" (autoscaled fleet).
+ },
+ "targetConcurrency": 0 # Optional. Present
+ only when spec.mode is "served" (autoscaled fleet).
+ },
+ "skills": [
+ {
+ "description": "str", #
+ Load-bearing: the agent reads it to decide WHEN to load the
+ skill (progressive disclosure); write it as "Use when ...".
+ Max 1024 chars. Required.
+ "instructions": "str", # The
+ markdown body (the content below the SKILL.md frontmatter).
+ Max 32 KiB. Required.
+ "name": "str", # Unique across the
+ list; 1-64 chars of lowercase letters, digits, and single
+ hyphen separators - no consecutive hyphens, per the Agent
+ Skills spec (safe as a directory name at materialization).
+ Required.
+ "allowedTools": [
+ "str" # Optional. Advisory
+ scoping of which tools the skill expects to use
+ (experimental in the skills standard). NOT a security
+ boundary - spec.permissions remains the only enforcement
+ surface.
+ ],
+ "license": "str", # Optional.
+ Optional standard passthrough (e.g. Apache-2.0).
+ "metadata": {
+ "str": "str" # Optional.
+ Optional string-map passthrough (e.g. author), rendered
+ into the frontmatter verbatim.
+ }
+ }
+ ],
+ "tools": {
+ "bundle": "str", # Optional. Accepted, not
+ yet enforced (returns a warning). Exactly one of mcpServers or
+ bundle.
+ "mcpServers": [
+ {
+ "auth": {
+ "secretRef": "str",
+ # Tenant-vault secret name. Required.
+ "header": "str" #
+ Optional. HTTP header the credential is sent in.
+ Defaults to Authorization.
+ },
+ "name": "str", # Optional.
+ Inline server name (required with url): 1-64 chars of
+ lowercase letters, digits, '-', '.', '_', starting/ending
+ alphanumeric. Unique across the list. Must not start with
+ do. (reserved for catalog refs).
+ "preloadTools": [
+ "str" # Optional.
+ Catalog form only. Individual tools (optional integer
+ pin) advertised directly in the session MCP
+ tools/list next to the
+ action_search/action_invoke/action_code meta tools.
+ Each entry must appear in tools when tools is set;
+ toolbelt references are rejected. Every preloaded
+ schema is in the model's context on every turn, so
+ keep this to a handful of tools. Omitted means
+ nothing is preloaded.
+ ],
+ "ref": "str", # Optional.
+ DO-owned catalog reference (catalog form); do.* only,
+ e.g. do.actions. Mutually exclusive with name/url/auth.
+ "tools": [
+ "str" # Optional.
+ Optional selection allowlist; omitted means all tools
+ the server advertises. Each entry is an individual
+ tool name with an optional integer version pin (e.g.
+ web_search, execute_code@3) or a toolbelt reference -
+ a server-defined named tool group written
+ toolbelt:[@:code:``] (e.g.
+ toolbelt:read-only@1; catalog refs only). Versions
+ are integer pins (no semver). The server owns belt
+ expansion; a pinned tool or belt attaches exactly
+ that version, an unpinned one resolves at session
+ create and is frozen for the session (no floating
+ latest). Entries non-empty, unique per server. The
+ selection bounds the session and is never preloaded
+ into the session MCP tools/list; see preloadTools.
+ ],
+ "url": "str" # Optional.
+ Inline server endpoint; https:// only.
+ }
+ ]
+ },
+ "workspace": {
+ "repos": [
+ "str" # Optional. GitHub OWNER/REPO
+ entries, unique. The first entry becomes the session's
+ repo_hint; the full list is the forward shape for multi-repo
+ sessions.
+ ]
+ }
+ }
+ },
+ "name": "str", # Required.
+ "updated_at": "2020-02-20 00:00:00", # Required.
+ "credentials": [
+ {
+ "name": "str", # Required.
+ "provider": "str", # Optional. Redacted credential
+ slot metadata (name/source/provider). Secret values are never
+ included.
+ "source": "str" # Optional. Known values are:
+ "tenantSecret" and "oauth".
+ }
+ ],
+ "insights": {
+ "logs": bool, # Optional. Whether the agent's logs are sent
+ to Insights.
+ "metrics": bool, # Optional. Accepted and stored for parity
+ with the Insights schema, but metrics are always collected: unregistered
+ metrics are dropped at ingest rather than opted out of here.
+ "traces": bool # Optional. Whether the agent's traces are
+ sent to Insights.
+ }
+ }
+ }
+ # response body for status code(s): 400, 404, 409, 413, 415
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+
+ @distributed_trace_async
+ async def create_config_clone(
+ self, config_id: str, body: Union[JSON, IO[bytes]], **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """Clone an Environment Config under a new name.
+
+ Copies the source config's sanitized manifest to a new UUID. Source and clone are independent
+ (no lineage). Credential bindings are never copied: if the manifest declares secret slots,
+ supply secrets/oauth_assignments again (write-only). content_hash matches the source when the
+ manifest is unchanged.
+
+ :param config_id: The Environment Config UUID. Required.
+ :type config_id: str
+ :param body: Clone body with required new name plus write-only credentials for any declared
+ slots. Is either a JSON type or a IO[bytes] type. Required.
+ :type body: JSON or IO[bytes]
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "name": "str", # New config name, unique among the team's active configs.
+ Required.
+ "oauth_assignments": {
+ "str": "str" # Optional. Write-only map from oauth logical slot to
+ an OAuth assignment UUID. Required when the source declares those slots;
+ never copied from the source.
+ },
+ "secrets": {
+ "str": "str" # Optional. Write-only map from tenantSecret logical
+ slot to plaintext. Required when the source declares those slots; never
+ copied from the source.
+ }
+ }
+
+ # response body for status code(s): 201
+ response == {
+ "config": {
+ "agentspec_schema_version": "str", # The manifest contract the
+ server accepted at create time: the manifest's own apiVersion for legacy
+ envelope parses (currently agents.digitalocean.com/v1alpha1), or
+ agents.digitalocean.com/flat.v1 for flat-format parses. Required.
+ "content_hash": "str", # Lowercase SHA-256 hex digest of the
+ canonical sanitized manifest JSON. Required.
+ "created_at": "2020-02-20 00:00:00", # Required.
+ "created_by": "str", # Authenticated user identity that created the
+ config. Required.
+ "id": "str", # Required.
+ "manifest": {
+ "apiVersion": "str", # Optional. Legacy envelope only - must
+ be "agents.digitalocean.com/v1alpha1", and its presence is what routes
+ the document to the deprecated legacy parser. Flat-format manifests carry
+ no version key (the endpoint owns the contract); required, with kind and
+ spec, when authoring the legacy format.
+ "agents.digitalocean.com/v1alpha1"
+ "kind": "str", # Optional. Must be "Agent". "Agent"
+ "metadata": {
+ "description": "str", # Optional. Free-form
+ description (max 1024 chars), stored and echoed back for Console /
+ catalog surfaces.
+ "labels": {
+ "str": "str" # Optional. Dictionary of
+ :code:``.
+ },
+ "name": "str" # Optional. Optional team-unique
+ session name: 1-64 chars of letters, digits, '-', '.', '_', starting
+ and ending alphanumeric; case-insensitive; must not be UUID-shaped.
+ Omit to have the control plane generate one
+ ("session-:code:``-:code:``"). Unique among
+ the team's ACTIVE (non-terminal) sessions; destroying a session frees
+ its name for reuse.
+ },
+ "spec": {
+ "runtime": {
+ "adapter": "str", # Required. Known values
+ are: "claude-code", "opencode", "codex", "cursor", "hermes",
+ "codex-agentapi", "custom", "codex-cli", "cursor-cli",
+ "openai-agents", "claude-agent-sdk", "crewai", and "langgraph".
+ "config": {
+ "str": {} # Optional. OPAQUE,
+ provider-specific runtime config. Only for adapter:
+ codex-agentapi today, where it is the OpenAI Agents API
+ create-session body (agent/environment/input) that doctl
+ forwards verbatim to OpenAI's POST /v1/agents/sessions;
+ harness-api stores and echoes it but never parses or
+ validates its contents (so DO stays forward-compatible as
+ OpenAI's schema evolves). The OpenAI session_id is passed on
+ the create call (the openai_session_id query parameter), not
+ in this block.
+ },
+ "custom": {
+ "image": "str", # Required.
+ "entrypoint": [
+ "str" # Optional. BYO
+ container; requires adapter: custom. image is required
+ and should be digest-pinned.
+ ]
+ }
+ },
+ "defaults": {
+ "budget": {
+ "maxCostUSD": 0.0, # Optional.
+ Accepted, not yet enforced (returns a warning). Advisory
+ per-run ceilings, clamped server-side to tenant policy.
+ "maxSteps": 0, # Optional. Accepted,
+ not yet enforced (returns a warning). Advisory per-run
+ ceilings, clamped server-side to tenant policy.
+ "maxWallClockSeconds": 0, #
+ Optional. Accepted, not yet enforced (returns a warning).
+ Advisory per-run ceilings, clamped server-side to tenant
+ policy.
+ "onBreach": "str" # Optional. Known
+ values are: "pause", "humanInput", and "fail".
+ }
+ },
+ "env": {
+ "str": "str" # Optional. Non-secret guest
+ env (debug-readable - never put secrets here; use spec.secrets).
+ Reserved platform keys (TEAM_ID, SESSION_ID, SANDBOX_ID,
+ CONTROL_PLANE_CALLBACK_URL, SANDBOX_TEMPLATE,
+ SANDBOX_AGENT_WORKDIR, SIZE_SLUG, SANDBOX_IMAGE_ID,
+ SANDBOX_OCI_REF, PLANO"" *PERMISSION*"" *) are rejected.
+ Credential-looking values (dop"" *v1*..., sk-..., ghp_...)
+ trigger a create-time warning.
+ },
+ "memory": {
+ "backend": "str", # Required.
+ "scope": "str" # Optional. Known values are:
+ "tenant", "user", "agent", and "session".
+ },
+ "mode": "str", # Optional. Explicit lifecycle
+ discriminator. Defaults to "interactive" (spec.serving forbidden);
+ "served" requires spec.serving. Known values are: "interactive" and
+ "served".
+ "model": {
+ "default": "str", # Optional. Accepted, not
+ yet enforced (returns a warning). Model routing (Plano);
+ catalog-validated when enforcement lands.
+ "profile": "str", # Optional. Accepted, not
+ yet enforced (returns a warning). Model routing (Plano);
+ catalog-validated when enforcement lands.
+ "routing": "str" # Optional. Accepted, not
+ yet enforced (returns a warning). Model routing (Plano);
+ catalog-validated when enforcement lands.
+ },
+ "permissions": {
+ "defaultAction": "str", # Optional.
+ Disposition for tool calls that match no rule. Defaults to "ask"
+ when omitted. Known values are: "allow", "ask", and "deny".
+ "filesystem": {
+ "allowWrite": [
+ "str" # Optional. Additional
+ writable paths beyond the workspace. Values must not
+ contain shell-style ${VAR}/$VAR expansions.
+ ],
+ "mode": "str" # Optional. Known
+ values are: "read-only" and "workspace-write".
+ },
+ "network": {
+ "allow": [
+ "str" # Optional. Network
+ boundary. Narrows (subtract-only) spec.sandbox.egress;
+ link-local/internal addresses stay blocked by the broader
+ egress policy.
+ ],
+ "default": "str" # Optional. Known
+ values are: "allow" and "deny".
+ },
+ "rules": [
+ {
+ "action": "str", # Required.
+ Known values are: "allow", "ask", and "deny".
+ "tool": "str", # Tool
+ taxonomy this rule matches (e.g. bash, file.read,
+ file.write, web.fetch, git.*, mcp). Required.
+ "enforcement": "str", #
+ Optional. What happens when the agent cannot enforce the
+ rule exactly. "strict" rejects the session; "best-effort"
+ degrades to the closest more-restrictive form and warns
+ (never widens). Defaults to strict for deny rules,
+ best-effort otherwise. Known values are: "strict" and
+ "best-effort".
+ "match": {
+ "str": "str" #
+ Optional. Optional keys narrowing the rule (e.g.
+ {"command": "npm run deploy"} for bash). Values are
+ globs and must not contain shell-style ${VAR}/$VAR
+ expansions.
+ }
+ }
+ ]
+ },
+ "sandbox": {
+ "egress": {
+ "allow": [
+ {
+ "host": "str" #
+ Required.
+ }
+ ],
+ "allowIps": [
+ "str" # Optional. Exact
+ IPv4/IPv6 literals (not CIDRs).
+ ],
+ "subnetUuid": "str", # Optional.
+ Optional subnet within vpcUuid.
+ "unrestricted": bool, # Optional.
+ When true, opts out of the platform-default host allowlist
+ union. Mutually exclusive with allow / allowIps / vpcUuid /
+ subnetUuid.
+ "vpcUuid": "str" # Optional.
+ Customer VPC UUID. Create-time immutable.
+ },
+ "idleTimeoutSeconds": 0, # Optional.
+ Inactivity suspend timeout. 0 means tenant policy default.
+ "maxLifetimeSeconds": 0, # Optional. Hard
+ wall-clock ceiling for the whole session, independent of
+ activity. Accepted, not yet enforced (returns a warning).
+ "mounts": [
+ {
+ "accessKeyRef": "str", #
+ Names a declared tenantSecret slot in spec.secrets.
+ Required.
+ "bucket": "str", # Required.
+ "path": "str", # Absolute
+ guest path the mount appears at. Required.
+ "secretKeyRef": "str", #
+ Names a declared tenantSecret slot in spec.secrets.
+ Required.
+ "type": "str", # Required.
+ "s3fuse"
+ "endpoint": "str", #
+ Optional. Optional storage endpoint override; https://
+ only.
+ "readOnly": bool # Optional.
+ Requested data mounts. Accepted, not yet enforced
+ (returns a warning). accessKeyRef/secretKeyRef name
+ declared tenantSecret slots in spec.secrets, validated at
+ create; declare those slots with env: false so the keys
+ stay mount-scoped and out of the guest env.
+ }
+ ],
+ "persistentWorkspace": bool, # Optional.
+ Canonical runnable environment spec JSON, immutable after create.
+ Validated non-secret spec.env and spec.permissions remain;
+ spec.secrets retains name/source/provider but omits ref and the
+ write-only value; metadata.name is cleared while safe metadata
+ such as labels remains. Required.
+ "sizeSlug": "str", # Optional. Requested
+ sandbox size (catalog: GET /v2/agents/sessions/sandbox/sizes).
+ Empty means the service default.
+ "template": "str" # Optional. Optional
+ sandbox template. Empty (or the legacy placeholder "coding")
+ means "no preference": the template derives from the adapter.
+ },
+ "secrets": [
+ {
+ "name": "str", # Required.
+ "source": "str", # Required. Known
+ values are: "oauth" and "tenantSecret".
+ "env": bool, # Optional. Whether the
+ resolved credential is injected into the guest env. Omitted
+ means true; false is for mount-only slots (tenantSecret
+ only).
+ "provider": "str", # Optional.
+ Declared credential requirements. source tenantSecret is
+ enforced today: value is write-only plaintext, extracted into
+ Secrets Manager at create and never persisted or returned.
+ source oauth requires provider, carries no value, and is
+ accepted but not yet enforced. ref is legacy and ignored. env
+ false keeps the resolved value out of the guest environment
+ (mount-only slots).
+ "ref": "str", # Optional. Declared
+ credential requirements. source tenantSecret is enforced
+ today: value is write-only plaintext, extracted into Secrets
+ Manager at create and never persisted or returned. source
+ oauth requires provider, carries no value, and is accepted
+ but not yet enforced. ref is legacy and ignored. env false
+ keeps the resolved value out of the guest environment
+ (mount-only slots).
+ "value": "str" # Optional.
+ Write-only tenantSecret plaintext; never persisted or
+ returned.
+ }
+ ],
+ "serving": {
+ "maxReplicas": 0, # Optional. Present only
+ when spec.mode is "served" (autoscaled fleet).
+ "minReplicas": 0, # Optional. Present only
+ when spec.mode is "served" (autoscaled fleet).
+ "scaleToZero": {
+ "idleSeconds": 0 # Optional. Present
+ only when spec.mode is "served" (autoscaled fleet).
+ },
+ "targetConcurrency": 0 # Optional. Present
+ only when spec.mode is "served" (autoscaled fleet).
+ },
+ "skills": [
+ {
+ "description": "str", #
+ Load-bearing: the agent reads it to decide WHEN to load the
+ skill (progressive disclosure); write it as "Use when ...".
+ Max 1024 chars. Required.
+ "instructions": "str", # The
+ markdown body (the content below the SKILL.md frontmatter).
+ Max 32 KiB. Required.
+ "name": "str", # Unique across the
+ list; 1-64 chars of lowercase letters, digits, and single
+ hyphen separators - no consecutive hyphens, per the Agent
+ Skills spec (safe as a directory name at materialization).
+ Required.
+ "allowedTools": [
+ "str" # Optional. Advisory
+ scoping of which tools the skill expects to use
+ (experimental in the skills standard). NOT a security
+ boundary - spec.permissions remains the only enforcement
+ surface.
+ ],
+ "license": "str", # Optional.
+ Optional standard passthrough (e.g. Apache-2.0).
+ "metadata": {
+ "str": "str" # Optional.
+ Optional string-map passthrough (e.g. author), rendered
+ into the frontmatter verbatim.
+ }
+ }
+ ],
+ "tools": {
+ "bundle": "str", # Optional. Accepted, not
+ yet enforced (returns a warning). Exactly one of mcpServers or
+ bundle.
+ "mcpServers": [
+ {
+ "auth": {
+ "secretRef": "str",
+ # Tenant-vault secret name. Required.
+ "header": "str" #
+ Optional. HTTP header the credential is sent in.
+ Defaults to Authorization.
+ },
+ "name": "str", # Optional.
+ Inline server name (required with url): 1-64 chars of
+ lowercase letters, digits, '-', '.', '_', starting/ending
+ alphanumeric. Unique across the list. Must not start with
+ do. (reserved for catalog refs).
+ "preloadTools": [
+ "str" # Optional.
+ Catalog form only. Individual tools (optional integer
+ pin) advertised directly in the session MCP
+ tools/list next to the
+ action_search/action_invoke/action_code meta tools.
+ Each entry must appear in tools when tools is set;
+ toolbelt references are rejected. Every preloaded
+ schema is in the model's context on every turn, so
+ keep this to a handful of tools. Omitted means
+ nothing is preloaded.
+ ],
+ "ref": "str", # Optional.
+ DO-owned catalog reference (catalog form); do.* only,
+ e.g. do.actions. Mutually exclusive with name/url/auth.
+ "tools": [
+ "str" # Optional.
+ Optional selection allowlist; omitted means all tools
+ the server advertises. Each entry is an individual
+ tool name with an optional integer version pin (e.g.
+ web_search, execute_code@3) or a toolbelt reference -
+ a server-defined named tool group written
+ toolbelt:[@:code:``] (e.g.
+ toolbelt:read-only@1; catalog refs only). Versions
+ are integer pins (no semver). The server owns belt
+ expansion; a pinned tool or belt attaches exactly
+ that version, an unpinned one resolves at session
+ create and is frozen for the session (no floating
+ latest). Entries non-empty, unique per server. The
+ selection bounds the session and is never preloaded
+ into the session MCP tools/list; see preloadTools.
+ ],
+ "url": "str" # Optional.
+ Inline server endpoint; https:// only.
+ }
+ ]
+ },
+ "workspace": {
+ "repos": [
+ "str" # Optional. GitHub OWNER/REPO
+ entries, unique. The first entry becomes the session's
+ repo_hint; the full list is the forward shape for multi-repo
+ sessions.
+ ]
+ }
+ }
+ },
+ "name": "str", # Required.
+ "updated_at": "2020-02-20 00:00:00", # Required.
+ "credentials": [
+ {
+ "name": "str", # Required.
+ "provider": "str", # Optional. Redacted credential
+ slot metadata (name/source/provider). Secret values are never
+ included.
+ "source": "str" # Optional. Known values are:
+ "tenantSecret" and "oauth".
+ }
+ ],
+ "insights": {
+ "logs": bool, # Optional. Whether the agent's logs are sent
+ to Insights.
+ "metrics": bool, # Optional. Accepted and stored for parity
+ with the Insights schema, but metrics are always collected: unregistered
+ metrics are dropped at ingest rather than opted out of here.
+ "traces": bool # Optional. Whether the agent's traces are
+ sent to Insights.
+ }
+ }
+ }
+ # response body for status code(s): 400, 404, 409, 413, 415
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
+ _params = kwargs.pop("params", {}) or {}
+
+ content_type: Optional[str] = kwargs.pop(
+ "content_type", _headers.pop("Content-Type", None)
+ )
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ content_type = content_type or "application/json"
+ _json = None
+ _content = None
+ if isinstance(body, (IOBase, bytes)):
+ _content = body
+ else:
+ _json = body
+
+ _request = build_harness_create_config_clone_request(
+ config_id=config_id,
+ content_type=content_type,
+ json=_json,
+ content=_content,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [201, 400, 404, 409, 413, 415]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ if response.status_code == 201:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 400:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 409:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 413:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 415:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+ @distributed_trace_async
+ async def list_config_sessions(
+ self,
+ config_id: str,
+ *,
+ page_size: int = 50,
+ page_token: Optional[str] = None,
+ status: Optional[str] = None,
+ **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """List the sessions created from one Environment Config.
+
+ Enumerates the caller's team sessions whose session was created from this durable Environment
+ Config. Keyset-paginated on an opaque cursor, newest first, same shape and status semantics as
+ GET /v2/agents/sessions.
+
+ :param config_id: The Environment Config UUID. Required.
+ :type config_id: str
+ :keyword page_size: Page size. Defaults to 50 when omitted or non-positive; values above 200
+ are clamped to 200. Default value is 50.
+ :paramtype page_size: int
+ :keyword page_token: Opaque keyset cursor returned by the previous page. Empty starts from the
+ beginning. Default value is None.
+ :paramtype page_token: str
+ :keyword status: Optional filter on session status. Empty / SESSION_STATUS_UNSPECIFIED still
+ hides destroyed and failed sessions by default; SESSION_STATUS_ALL opts out and returns every
+ session regardless of status. Known values are: "SESSION_STATUS_UNSPECIFIED",
+ "SESSION_STATUS_PROVISIONING", "SESSION_STATUS_READY", "SESSION_STATUS_DETACHED",
+ "SESSION_STATUS_DESTROYING", "SESSION_STATUS_DESTROYED", "SESSION_STATUS_FAILED",
+ "SESSION_STATUS_PAUSED", and "SESSION_STATUS_ALL". Default value is None.
+ :paramtype status: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 200
+ response == {
+ "next_page_token": "str", # Optional. Opaque cursor for the next page. Empty
+ when there are no further pages.
+ "sessions": [
+ {
+ "agent_kind": "AGENT_KIND_UNSPECIFIED", # Optional. Default
+ value is "AGENT_KIND_UNSPECIFIED". AgentKind identifies what runs inside
+ the session sandbox. CreateSession accepts CLAUDE_CODE, OPENCODE,
+ CODEX_CLI, CURSOR_CLI, OPENAI_CODEX, LANGGRAPH, and CREWAI (the supported
+ set is overridable via HARNESS_SUPPORTED_AGENT_KINDS); other values are
+ rejected with 400. AGENT_KIND_OPENAI_CODEX is the OpenAI sandbox-provider
+ kind (DO runs codex exec-server; the agent loop lives at OpenAI).
+ AGENT_KIND_LANGGRAPH is the LangGraph framework adapter.
+ AGENT_KIND_CREWAI is the CrewAI Crew framework adapter: like LANGGRAPH
+ the template bakes no agent code, so spec.env must supply FRAMEWORK_REPO
+ and FRAMEWORK_REPO_SHA; a Crew kickoff is one-shot and exposes no HITL
+ surface. CREWAI is additionally gated per team and returns 400 for teams
+ it is not enabled for. Known values are: "AGENT_KIND_UNSPECIFIED",
+ "AGENT_KIND_CLAUDE_CODE", "AGENT_KIND_OPENCODE", "AGENT_KIND_CODEX_CLI",
+ "AGENT_KIND_CURSOR_CLI", "AGENT_KIND_NONE", "AGENT_KIND_CUSTOM",
+ "AGENT_KIND_HERMES", "AGENT_KIND_OPENAI_CODEX", "AGENT_KIND_LANGGRAPH",
+ and "AGENT_KIND_CREWAI".
+ "config_id": "str", # Optional. Durable Environment Config
+ UUID the session was created from (inline manifests persist a config too,
+ named after the session). Persisted and returned on create/get/list;
+ absent only for sessions created before config references were stored.
+ "created_at": "2020-02-20 00:00:00", # Optional.
+ "fork_from_checkpoint_id": "str", # Optional. Lineage:
+ harness-api checkpoint id (cp_:code:``) the child booted from at
+ fork time. Drives OHP inherited-history replay on attach. Omitted/empty
+ for root sessions and legacy forks created before this field was
+ persisted.
+ "fork_id": "str", # Optional. Lineage: branch label assigned
+ when this session was created by ForkSession (or rollback's internal
+ fork). Omitted/empty for root sessions.
+ "idle_timeout_seconds": 0, # Optional. This session's own
+ idle-pause timeout (manifest idle_timeout). Omitted when the session uses
+ the deployment-wide default.
+ "keep_warm": bool, # Optional. Session is exempt from idle
+ auto-pause (manifest keep_warm, or the agent-kind default: hermes
+ sessions keep warm). Pause requests against such a session are rejected
+ with 409. Omitted when false.
+ "last_event_at": "2020-02-20 00:00:00", # Optional.
+ Timestamp of the most recent event in this session's canonical stream.
+ Drives the inactivity policy that destroys idle sessions.
+ "name": "str", # Optional. User-assignable display name,
+ unique per team among non-terminal sessions. Usable in place of
+ session_id by clients (doctl / Console resolve it to the id via the
+ ListSessions ?name= filter; the {session_id} path stays UUID-only).
+ Supplied via the environment-spec metadata.name, or auto-generated
+ ("session-:code:``-:code:``") when omitted.
+ "openai_environment_id": "str", # Optional. OpenAI Agents
+ API environment id (env_"u2026), captured from the resolved
+ CODEX_ENVIRONMENT_ID guest env value. Populated only for
+ AGENT_KIND_OPENAI_CODEX sessions. Non-secret correlation metadata.
+ "openai_session_id": "str", # Optional. OpenAI Agents API
+ session id (sess_"u2026) this DO sandbox hosts. Populated only for
+ AGENT_KIND_OPENAI_CODEX sessions (empty otherwise). Non-secret
+ correlation metadata; a client (doctl agents attach) reads it to bridge
+ to the OpenAI session. See docs/design/openai-sandbox-provider.md.
+ "parent_session_id": "str", # Optional. Lineage: id of the
+ session this one was forked from. Omitted/empty for root (non-fork)
+ sessions.
+ "pause_reason": "str", # Optional. Why this session is
+ paused. Present only when status is SESSION_STATUS_PAUSED; omitted
+ otherwise. Known values: manual (PauseSession RPC), idle (inactivity
+ auto-pause), low_balance (prepay gate). Clients should treat an
+ unrecognized value as an opaque reason string.
+ "repo_hint": "str", # Optional. Optional repository hint
+ supplied at session creation (first spec.workspace.repos entry of the
+ manifest). Not authoritative; the agent may change repos in-session.
+ "resume_on_topoff": bool, # Optional. Session consents to
+ being resumed automatically when the team's prepayment balance is
+ restored after a low-balance pause. Defaults to false at create time; may
+ be toggled later via PATCH /v2/agents/sessions/{session_id}
+ (resume_on_topoff only). Only a session paused with reason low_balance
+ whose latest run did not complete is ever resumed automatically - a
+ session the customer paused themselves, or one that idled out, stays
+ paused regardless. Not an environment-spec field, and forks do not
+ inherit it. Omitted when false.
+ "sandbox_id": "str", # Optional. Sandbox identity for
+ support / debugging. Informational; omitted until a sandbox is allocated.
+ "session_id": "str", # Optional.
+ "status": "SESSION_STATUS_UNSPECIFIED", # Optional. Default
+ value is "SESSION_STATUS_UNSPECIFIED". SessionStatus is the lifecycle
+ state of the sandbox + agent pair. SESSION_STATUS_ALL is a ListSessions
+ status-filter value only -- no session is ever actually in this status.
+ SESSION_STATUS_LOCKED is reserved for internal use and never appears in
+ an end-user-facing response. Known values are:
+ "SESSION_STATUS_UNSPECIFIED", "SESSION_STATUS_PROVISIONING",
+ "SESSION_STATUS_READY", "SESSION_STATUS_DETACHED",
+ "SESSION_STATUS_DESTROYING", "SESSION_STATUS_DESTROYED",
+ "SESSION_STATUS_FAILED", "SESSION_STATUS_PAUSED", "SESSION_STATUS_ALL",
+ and "SESSION_STATUS_LOCKED".
+ "warnings": [
+ "str" # Optional. Non-fatal advisories computed from
+ the manifest at create time: one entry per populated
+ accepted-but-not-yet-enforced section (flat names: secrets, model,
+ tools, memory, budget, max_lifetime, mounts; legacy manifests get the
+ corresponding spec.* paths), a deprecation entry when a
+ legacy-envelope manifest or an adapter alias (codex-cli, cursor-cli)
+ is used, and a heuristic entry per credential-looking spec.env value.
+ Populated on the CreateSession response only.
+ ]
+ }
+ ]
+ }
+ # response body for status code(s): 400, 404
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = kwargs.pop("headers", {}) or {}
+ _params = kwargs.pop("params", {}) or {}
+
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ _request = build_harness_list_config_sessions_request(
+ config_id=config_id,
+ page_size=page_size,
+ page_token=page_token,
+ status=status,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 400, 404]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ if response.status_code == 200:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 400:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+ @distributed_trace_async
+ async def list_sessions(
+ self,
+ *,
+ page_size: int = 50,
+ page_token: Optional[str] = None,
+ status: str = "SESSION_STATUS_UNSPECIFIED",
+ name: Optional[str] = None,
+ search: Optional[str] = None,
+ **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """ListSessions enumerates sessions for the caller's tenant.
+
+ Keyset-paginated on an opaque cursor. Results are scoped to the authenticated team. Destroyed
+ and failed sessions are omitted by default (matching the Cloud Console); pass
+ ``status=SESSION_STATUS_ALL`` to list every session regardless of status, or an explicit status
+ such as ``status=SESSION_STATUS_FAILED`` or ``status=SESSION_STATUS_DESTROYED`` to list only
+ those.
+
+ :keyword page_size: Page size. Defaults to 50 when omitted or non-positive; values above 200
+ are clamped to 200 (not rejected). Default value is 50.
+ :paramtype page_size: int
+ :keyword page_token: Opaque keyset cursor returned by the previous page. Empty starts from the
+ beginning. Default value is None.
+ :paramtype page_token: str
+ :keyword status: Optional filter on session status. Empty / SESSION_STATUS_UNSPECIFIED means no
+ explicit filter, which still hides destroyed and failed sessions by default; SESSION_STATUS_ALL
+ opts out and returns every session regardless of status (no session is ever actually in this
+ status; it only means something as a filter value here); any other explicit status overrides
+ the default. Known values are: "SESSION_STATUS_UNSPECIFIED", "SESSION_STATUS_PROVISIONING",
+ "SESSION_STATUS_READY", "SESSION_STATUS_DETACHED", "SESSION_STATUS_DESTROYING",
+ "SESSION_STATUS_DESTROYED", "SESSION_STATUS_FAILED", "SESSION_STATUS_PAUSED",
+ "SESSION_STATUS_ALL", and "SESSION_STATUS_LOCKED". Default value is
+ "SESSION_STATUS_UNSPECIFIED".
+ :paramtype status: str
+ :keyword name: Optional exact-name filter (case-insensitive). Returns the single live
+ (non-terminal) session that currently holds this name for the caller's team, or an empty list
+ if none does. Matches the live holder only, so historical terminal rows and reused names never
+ make it ambiguous (per-team live-name uniqueness bounds it to at most one). This is how clients
+ (doctl / Console) resolve a session name to its id; the {session_id} path stays UUID-only.
+ Default value is None.
+ :paramtype name: str
+ :keyword search: Optional case-insensitive substring filter on session name (contains), for
+ callers that don't know the exact name (e.g. a UI search box). Unlike ``name``\\ , this may
+ return zero, one, or many sessions, including terminal ones. Independent of ``name``\\ ; at
+ most 64 characters. Default value is None.
+ :paramtype search: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 200
+ response == {
+ "next_page_token": "str", # Optional. Opaque cursor for the next page. Empty
+ when there are no further pages.
+ "sessions": [
+ {
+ "agent_kind": "AGENT_KIND_UNSPECIFIED", # Optional. Default
+ value is "AGENT_KIND_UNSPECIFIED". AgentKind identifies what runs inside
+ the session sandbox. CreateSession accepts CLAUDE_CODE, OPENCODE,
+ CODEX_CLI, CURSOR_CLI, OPENAI_CODEX, LANGGRAPH, and CREWAI (the supported
+ set is overridable via HARNESS_SUPPORTED_AGENT_KINDS); other values are
+ rejected with 400. AGENT_KIND_OPENAI_CODEX is the OpenAI sandbox-provider
+ kind (DO runs codex exec-server; the agent loop lives at OpenAI).
+ AGENT_KIND_LANGGRAPH is the LangGraph framework adapter.
+ AGENT_KIND_CREWAI is the CrewAI Crew framework adapter: like LANGGRAPH
+ the template bakes no agent code, so spec.env must supply FRAMEWORK_REPO
+ and FRAMEWORK_REPO_SHA; a Crew kickoff is one-shot and exposes no HITL
+ surface. CREWAI is additionally gated per team and returns 400 for teams
+ it is not enabled for. Known values are: "AGENT_KIND_UNSPECIFIED",
+ "AGENT_KIND_CLAUDE_CODE", "AGENT_KIND_OPENCODE", "AGENT_KIND_CODEX_CLI",
+ "AGENT_KIND_CURSOR_CLI", "AGENT_KIND_NONE", "AGENT_KIND_CUSTOM",
+ "AGENT_KIND_HERMES", "AGENT_KIND_OPENAI_CODEX", "AGENT_KIND_LANGGRAPH",
+ and "AGENT_KIND_CREWAI".
+ "config_id": "str", # Optional. Durable Environment Config
+ UUID the session was created from (inline manifests persist a config too,
+ named after the session). Persisted and returned on create/get/list;
+ absent only for sessions created before config references were stored.
+ "created_at": "2020-02-20 00:00:00", # Optional.
+ "fork_from_checkpoint_id": "str", # Optional. Lineage:
+ harness-api checkpoint id (cp_:code:``) the child booted from at
+ fork time. Drives OHP inherited-history replay on attach. Omitted/empty
+ for root sessions and legacy forks created before this field was
+ persisted.
+ "fork_id": "str", # Optional. Lineage: branch label assigned
+ when this session was created by ForkSession (or rollback's internal
+ fork). Omitted/empty for root sessions.
+ "idle_timeout_seconds": 0, # Optional. This session's own
+ idle-pause timeout (manifest idle_timeout). Omitted when the session uses
+ the deployment-wide default.
+ "keep_warm": bool, # Optional. Session is exempt from idle
+ auto-pause (manifest keep_warm, or the agent-kind default: hermes
+ sessions keep warm). Pause requests against such a session are rejected
+ with 409. Omitted when false.
+ "last_event_at": "2020-02-20 00:00:00", # Optional.
+ Timestamp of the most recent event in this session's canonical stream.
+ Drives the inactivity policy that destroys idle sessions.
+ "name": "str", # Optional. User-assignable display name,
+ unique per team among non-terminal sessions. Usable in place of
+ session_id by clients (doctl / Console resolve it to the id via the
+ ListSessions ?name= filter; the {session_id} path stays UUID-only).
+ Supplied via the environment-spec metadata.name, or auto-generated
+ ("session-:code:``-:code:``") when omitted.
+ "openai_environment_id": "str", # Optional. OpenAI Agents
+ API environment id (env_"u2026), captured from the resolved
+ CODEX_ENVIRONMENT_ID guest env value. Populated only for
+ AGENT_KIND_OPENAI_CODEX sessions. Non-secret correlation metadata.
+ "openai_session_id": "str", # Optional. OpenAI Agents API
+ session id (sess_"u2026) this DO sandbox hosts. Populated only for
+ AGENT_KIND_OPENAI_CODEX sessions (empty otherwise). Non-secret
+ correlation metadata; a client (doctl agents attach) reads it to bridge
+ to the OpenAI session. See docs/design/openai-sandbox-provider.md.
+ "parent_session_id": "str", # Optional. Lineage: id of the
+ session this one was forked from. Omitted/empty for root (non-fork)
+ sessions.
+ "pause_reason": "str", # Optional. Why this session is
+ paused. Present only when status is SESSION_STATUS_PAUSED; omitted
+ otherwise. Known values: manual (PauseSession RPC), idle (inactivity
+ auto-pause), low_balance (prepay gate). Clients should treat an
+ unrecognized value as an opaque reason string.
+ "repo_hint": "str", # Optional. Optional repository hint
+ supplied at session creation (first spec.workspace.repos entry of the
+ manifest). Not authoritative; the agent may change repos in-session.
+ "resume_on_topoff": bool, # Optional. Session consents to
+ being resumed automatically when the team's prepayment balance is
+ restored after a low-balance pause. Defaults to false at create time; may
+ be toggled later via PATCH /v2/agents/sessions/{session_id}
+ (resume_on_topoff only). Only a session paused with reason low_balance
+ whose latest run did not complete is ever resumed automatically - a
+ session the customer paused themselves, or one that idled out, stays
+ paused regardless. Not an environment-spec field, and forks do not
+ inherit it. Omitted when false.
+ "sandbox_id": "str", # Optional. Sandbox identity for
+ support / debugging. Informational; omitted until a sandbox is allocated.
+ "session_id": "str", # Optional.
+ "status": "SESSION_STATUS_UNSPECIFIED", # Optional. Default
+ value is "SESSION_STATUS_UNSPECIFIED". SessionStatus is the lifecycle
+ state of the sandbox + agent pair. SESSION_STATUS_ALL is a ListSessions
+ status-filter value only -- no session is ever actually in this status.
+ SESSION_STATUS_LOCKED is reserved for internal use and never appears in
+ an end-user-facing response. Known values are:
+ "SESSION_STATUS_UNSPECIFIED", "SESSION_STATUS_PROVISIONING",
+ "SESSION_STATUS_READY", "SESSION_STATUS_DETACHED",
+ "SESSION_STATUS_DESTROYING", "SESSION_STATUS_DESTROYED",
+ "SESSION_STATUS_FAILED", "SESSION_STATUS_PAUSED", "SESSION_STATUS_ALL",
+ and "SESSION_STATUS_LOCKED".
+ "warnings": [
+ "str" # Optional. Non-fatal advisories computed from
+ the manifest at create time: one entry per populated
+ accepted-but-not-yet-enforced section (flat names: secrets, model,
+ tools, memory, budget, max_lifetime, mounts; legacy manifests get the
+ corresponding spec.* paths), a deprecation entry when a
+ legacy-envelope manifest or an adapter alias (codex-cli, cursor-cli)
+ is used, and a heuristic entry per credential-looking spec.env value.
+ Populated on the CreateSession response only.
+ ]
+ }
+ ]
+ }
+ # response body for status code(s): 400, 404
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = kwargs.pop("headers", {}) or {}
+ _params = kwargs.pop("params", {}) or {}
+
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ _request = build_harness_list_sessions_request(
+ page_size=page_size,
+ page_token=page_token,
+ status=status,
+ name=name,
+ search=search,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 400, 404]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ if response.status_code == 200:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 400:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+ @overload
+ async def create_session(
+ self,
+ body: JSON,
+ *,
+ x_device_uuid: Optional[str] = None,
+ openai_session_id: Optional[str] = None,
+ resume_on_topoff: Optional[bool] = None,
+ content_type: str = "application/json",
+ **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """CreateSession provisions a sandbox and starts a Harness Runtime session.
+
+ Returns once the session row is allocated. Sandbox boot completes asynchronously.
+
+ Two mutually exclusive request forms are selected by Content-Type (same contract as
+ harness-api ``harness.swagger.json``\\ ):
+
+
+ * YAML (\\ ``application/x-yaml``\\ , ``application/yaml``\\ , ``text/yaml``\\ ,
+ ``text/x-yaml``\\ ): the environment
+ spec. Two environment-spec formats are accepted during the dual-format transition: the flat
+ format (primary) and the legacy ``agents.digitalocean.com/v1alpha1`` envelope (deprecated). A
+ top-level ``apiVersion`` key selects the legacy parser; its absence selects flat. Internally
+ persists a durable Environment Config, then creates the session.
+ * JSON (\\ ``application/json``\\ ): ``{name, config_id}`` loads the config, resolves its
+ credentials from
+ Secrets Manager at the version pinned when the config was created, and creates the session.
+
+ The OpenAPI ``requestBody`` schemas the JSON form for client generation (Autorest cannot emit a
+ multi–content-type body). The live API still accepts the YAML forms listed above.
+
+ Successful responses may include ``config_id`` on the session. ``X-Device-UUID`` (if present)
+ is
+ persisted on the session row. Query parameters ``openai_session_id`` and ``resume_on_topoff``
+ apply to
+ both forms; when both the JSON body field and ``?resume_on_topoff=`` are present, the query
+ parameter wins.
+
+ :param body: CreateSessionConfigRequest with ``application/json``. The live API also accepts a
+ raw environment
+ spec under YAML Content-Types (see operation description); those forms are omitted from
+ ``content``
+ so generated clients (pydo/autorest) can emit this operation. Required.
+ :type body: JSON
+ :keyword x_device_uuid: Optional hardware device id forwarded by doctl. Persisted on the
+ session row for lifecycle attribution. Values over 128 bytes are ignored. Default value is
+ None.
+ :paramtype x_device_uuid: str
+ :keyword openai_session_id: OpenAI Agents API session id (sess_…) for adapter: codex-agentapi.
+ doctl creates the OpenAI session before calling DO and passes the resulting id here;
+ harness-api persists it for correlation. Empty/omitted for every other agent kind. Default
+ value is None.
+ :paramtype openai_session_id: str
+ :keyword resume_on_topoff: Opt the new session in to automatic resumption when the team's
+ prepayment balance is restored. Defaults to false. Exists as a query parameter so the
+ environment spec (YAML body) form can carry it too. On the application/json form the body field
+ is idiomatic, but this parameter wins when both are present. Must be exactly one of
+ true/false/1/0; anything else is a 400. Default value is None.
+ :paramtype resume_on_topoff: bool
+ :keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
+ Default value is "application/json".
+ :paramtype content_type: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "config_id": "str", # Required.
+ "name": "str", # Session name, independent of the config name. Must satisfy
+ the existing environment-spec metadata.name rules and must not be UUID-shaped.
+ Required.
+ "resume_on_topoff": bool # Optional. Opt the new session in to automatic
+ resumption when the team's prepayment balance is restored. Defaults to false.
+ Session-scoped, not config-scoped: the referenced config never confers this, so
+ one shared config cannot enrol every session created from it. Omit to leave the
+ default (or to let the ?resume_on_topoff= query parameter supply it).
+ }
+
+ # response body for status code(s): 200
+ response == {
+ "session": {
+ "agent_kind": "AGENT_KIND_UNSPECIFIED", # Optional. Default value is
+ "AGENT_KIND_UNSPECIFIED". AgentKind identifies what runs inside the session
+ sandbox. CreateSession accepts CLAUDE_CODE, OPENCODE, CODEX_CLI, CURSOR_CLI,
+ OPENAI_CODEX, LANGGRAPH, and CREWAI (the supported set is overridable via
+ HARNESS_SUPPORTED_AGENT_KINDS); other values are rejected with 400.
+ AGENT_KIND_OPENAI_CODEX is the OpenAI sandbox-provider kind (DO runs codex
+ exec-server; the agent loop lives at OpenAI). AGENT_KIND_LANGGRAPH is the
+ LangGraph framework adapter. AGENT_KIND_CREWAI is the CrewAI Crew framework
+ adapter: like LANGGRAPH the template bakes no agent code, so spec.env must
+ supply FRAMEWORK_REPO and FRAMEWORK_REPO_SHA; a Crew kickoff is one-shot and
+ exposes no HITL surface. CREWAI is additionally gated per team and returns
+ 400 for teams it is not enabled for. Known values are:
+ "AGENT_KIND_UNSPECIFIED", "AGENT_KIND_CLAUDE_CODE", "AGENT_KIND_OPENCODE",
+ "AGENT_KIND_CODEX_CLI", "AGENT_KIND_CURSOR_CLI", "AGENT_KIND_NONE",
+ "AGENT_KIND_CUSTOM", "AGENT_KIND_HERMES", "AGENT_KIND_OPENAI_CODEX",
+ "AGENT_KIND_LANGGRAPH", and "AGENT_KIND_CREWAI".
+ "config_id": "str", # Optional. Durable Environment Config UUID the
+ session was created from (inline manifests persist a config too, named after
+ the session). Persisted and returned on create/get/list; absent only for
+ sessions created before config references were stored.
+ "created_at": "2020-02-20 00:00:00", # Optional. Session is the
+ user-facing record of a environment session + sandbox pair.
+ "fork_from_checkpoint_id": "str", # Optional. Lineage: harness-api
+ checkpoint id (cp_:code:``) the child booted from at fork time. Drives
+ OHP inherited-history replay on attach. Omitted/empty for root sessions and
+ legacy forks created before this field was persisted.
+ "fork_id": "str", # Optional. Lineage: branch label assigned when
+ this session was created by ForkSession (or rollback's internal fork).
+ Omitted/empty for root sessions.
+ "idle_timeout_seconds": 0, # Optional. This session's own idle-pause
+ timeout (manifest idle_timeout). Omitted when the session uses the
+ deployment-wide default.
+ "keep_warm": bool, # Optional. Session is exempt from idle
+ auto-pause (manifest keep_warm, or the agent-kind default: hermes sessions
+ keep warm). Pause requests against such a session are rejected with 409.
+ Omitted when false.
+ "last_event_at": "2020-02-20 00:00:00", # Optional. Timestamp of the
+ most recent event in this session's canonical stream. Drives the inactivity
+ policy that destroys idle sessions.
+ "name": "str", # Optional. User-assignable display name, unique per
+ team among non-terminal sessions. Usable in place of session_id by clients
+ (doctl / Console resolve it to the id via the ListSessions ?name= filter; the
+ {session_id} path stays UUID-only). Supplied via the environment-spec
+ metadata.name, or auto-generated
+ ("session-:code:``-:code:``") when omitted.
+ "openai_environment_id": "str", # Optional. OpenAI Agents API
+ environment id (env_"u2026), captured from the resolved CODEX_ENVIRONMENT_ID
+ guest env value. Populated only for AGENT_KIND_OPENAI_CODEX sessions.
+ Non-secret correlation metadata.
+ "openai_session_id": "str", # Optional. OpenAI Agents API session id
+ (sess_"u2026) this DO sandbox hosts. Populated only for
+ AGENT_KIND_OPENAI_CODEX sessions (empty otherwise). Non-secret correlation
+ metadata; a client (doctl agents attach) reads it to bridge to the OpenAI
+ session. See docs/design/openai-sandbox-provider.md.
+ "parent_session_id": "str", # Optional. Lineage: id of the session
+ this one was forked from. Omitted/empty for root (non-fork) sessions.
+ "pause_reason": "str", # Optional. Why this session is paused.
+ Present only when status is SESSION_STATUS_PAUSED; omitted otherwise. Known
+ values: manual (PauseSession RPC), idle (inactivity auto-pause), low_balance
+ (prepay gate). Clients should treat an unrecognized value as an opaque reason
+ string.
+ "repo_hint": "str", # Optional. Optional repository hint supplied at
+ session creation (first spec.workspace.repos entry of the manifest). Not
+ authoritative; the agent may change repos in-session.
+ "resume_on_topoff": bool, # Optional. Session consents to being
+ resumed automatically when the team's prepayment balance is restored after a
+ low-balance pause. Defaults to false at create time; may be toggled later via
+ PATCH /v2/agents/sessions/{session_id} (resume_on_topoff only). Only a
+ session paused with reason low_balance whose latest run did not complete is
+ ever resumed automatically - a session the customer paused themselves, or one
+ that idled out, stays paused regardless. Not an environment-spec field, and
+ forks do not inherit it. Omitted when false.
+ "sandbox_id": "str", # Optional. Sandbox identity for support /
+ debugging. Informational; omitted until a sandbox is allocated.
+ "session_id": "str", # Optional. Session is the user-facing record
+ of a environment session + sandbox pair.
+ "status": "SESSION_STATUS_UNSPECIFIED", # Optional. Default value is
+ "SESSION_STATUS_UNSPECIFIED". SessionStatus is the lifecycle state of the
+ sandbox + agent pair. SESSION_STATUS_ALL is a ListSessions status-filter
+ value only -- no session is ever actually in this status.
+ SESSION_STATUS_LOCKED is reserved for internal use and never appears in an
+ end-user-facing response. Known values are: "SESSION_STATUS_UNSPECIFIED",
+ "SESSION_STATUS_PROVISIONING", "SESSION_STATUS_READY",
+ "SESSION_STATUS_DETACHED", "SESSION_STATUS_DESTROYING",
+ "SESSION_STATUS_DESTROYED", "SESSION_STATUS_FAILED", "SESSION_STATUS_PAUSED",
+ "SESSION_STATUS_ALL", and "SESSION_STATUS_LOCKED".
+ "warnings": [
+ "str" # Optional. Non-fatal advisories computed from the
+ manifest at create time: one entry per populated
+ accepted-but-not-yet-enforced section (flat names: secrets, model, tools,
+ memory, budget, max_lifetime, mounts; legacy manifests get the
+ corresponding spec.* paths), a deprecation entry when a legacy-envelope
+ manifest or an adapter alias (codex-cli, cursor-cli) is used, and a
+ heuristic entry per credential-looking spec.env value. Populated on the
+ CreateSession response only.
+ ]
+ }
+ }
+ # response body for status code(s): 400, 402, 403, 404, 409, 413, 415, 501, 503
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+
+ @overload
+ async def create_session(
+ self,
+ body: IO[bytes],
+ *,
+ x_device_uuid: Optional[str] = None,
+ openai_session_id: Optional[str] = None,
+ resume_on_topoff: Optional[bool] = None,
+ content_type: str = "application/json",
+ **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """CreateSession provisions a sandbox and starts a Harness Runtime session.
+
+ Returns once the session row is allocated. Sandbox boot completes asynchronously.
+
+ Two mutually exclusive request forms are selected by Content-Type (same contract as
+ harness-api ``harness.swagger.json``\\ ):
+
+
+ * YAML (\\ ``application/x-yaml``\\ , ``application/yaml``\\ , ``text/yaml``\\ ,
+ ``text/x-yaml``\\ ): the environment
+ spec. Two environment-spec formats are accepted during the dual-format transition: the flat
+ format (primary) and the legacy ``agents.digitalocean.com/v1alpha1`` envelope (deprecated). A
+ top-level ``apiVersion`` key selects the legacy parser; its absence selects flat. Internally
+ persists a durable Environment Config, then creates the session.
+ * JSON (\\ ``application/json``\\ ): ``{name, config_id}`` loads the config, resolves its
+ credentials from
+ Secrets Manager at the version pinned when the config was created, and creates the session.
+
+ The OpenAPI ``requestBody`` schemas the JSON form for client generation (Autorest cannot emit a
+ multi–content-type body). The live API still accepts the YAML forms listed above.
+
+ Successful responses may include ``config_id`` on the session. ``X-Device-UUID`` (if present)
+ is
+ persisted on the session row. Query parameters ``openai_session_id`` and ``resume_on_topoff``
+ apply to
+ both forms; when both the JSON body field and ``?resume_on_topoff=`` are present, the query
+ parameter wins.
+
+ :param body: CreateSessionConfigRequest with ``application/json``. The live API also accepts a
+ raw environment
+ spec under YAML Content-Types (see operation description); those forms are omitted from
+ ``content``
+ so generated clients (pydo/autorest) can emit this operation. Required.
+ :type body: IO[bytes]
+ :keyword x_device_uuid: Optional hardware device id forwarded by doctl. Persisted on the
+ session row for lifecycle attribution. Values over 128 bytes are ignored. Default value is
+ None.
+ :paramtype x_device_uuid: str
+ :keyword openai_session_id: OpenAI Agents API session id (sess_…) for adapter: codex-agentapi.
+ doctl creates the OpenAI session before calling DO and passes the resulting id here;
+ harness-api persists it for correlation. Empty/omitted for every other agent kind. Default
+ value is None.
+ :paramtype openai_session_id: str
+ :keyword resume_on_topoff: Opt the new session in to automatic resumption when the team's
+ prepayment balance is restored. Defaults to false. Exists as a query parameter so the
+ environment spec (YAML body) form can carry it too. On the application/json form the body field
+ is idiomatic, but this parameter wins when both are present. Must be exactly one of
+ true/false/1/0; anything else is a 400. Default value is None.
+ :paramtype resume_on_topoff: bool
+ :keyword content_type: Body Parameter content-type. Content type parameter for binary body.
+ Default value is "application/json".
+ :paramtype content_type: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 200
+ response == {
+ "session": {
+ "agent_kind": "AGENT_KIND_UNSPECIFIED", # Optional. Default value is
+ "AGENT_KIND_UNSPECIFIED". AgentKind identifies what runs inside the session
+ sandbox. CreateSession accepts CLAUDE_CODE, OPENCODE, CODEX_CLI, CURSOR_CLI,
+ OPENAI_CODEX, LANGGRAPH, and CREWAI (the supported set is overridable via
+ HARNESS_SUPPORTED_AGENT_KINDS); other values are rejected with 400.
+ AGENT_KIND_OPENAI_CODEX is the OpenAI sandbox-provider kind (DO runs codex
+ exec-server; the agent loop lives at OpenAI). AGENT_KIND_LANGGRAPH is the
+ LangGraph framework adapter. AGENT_KIND_CREWAI is the CrewAI Crew framework
+ adapter: like LANGGRAPH the template bakes no agent code, so spec.env must
+ supply FRAMEWORK_REPO and FRAMEWORK_REPO_SHA; a Crew kickoff is one-shot and
+ exposes no HITL surface. CREWAI is additionally gated per team and returns
+ 400 for teams it is not enabled for. Known values are:
+ "AGENT_KIND_UNSPECIFIED", "AGENT_KIND_CLAUDE_CODE", "AGENT_KIND_OPENCODE",
+ "AGENT_KIND_CODEX_CLI", "AGENT_KIND_CURSOR_CLI", "AGENT_KIND_NONE",
+ "AGENT_KIND_CUSTOM", "AGENT_KIND_HERMES", "AGENT_KIND_OPENAI_CODEX",
+ "AGENT_KIND_LANGGRAPH", and "AGENT_KIND_CREWAI".
+ "config_id": "str", # Optional. Durable Environment Config UUID the
+ session was created from (inline manifests persist a config too, named after
+ the session). Persisted and returned on create/get/list; absent only for
+ sessions created before config references were stored.
+ "created_at": "2020-02-20 00:00:00", # Optional. Session is the
+ user-facing record of a environment session + sandbox pair.
+ "fork_from_checkpoint_id": "str", # Optional. Lineage: harness-api
+ checkpoint id (cp_:code:``) the child booted from at fork time. Drives
+ OHP inherited-history replay on attach. Omitted/empty for root sessions and
+ legacy forks created before this field was persisted.
+ "fork_id": "str", # Optional. Lineage: branch label assigned when
+ this session was created by ForkSession (or rollback's internal fork).
+ Omitted/empty for root sessions.
+ "idle_timeout_seconds": 0, # Optional. This session's own idle-pause
+ timeout (manifest idle_timeout). Omitted when the session uses the
+ deployment-wide default.
+ "keep_warm": bool, # Optional. Session is exempt from idle
+ auto-pause (manifest keep_warm, or the agent-kind default: hermes sessions
+ keep warm). Pause requests against such a session are rejected with 409.
+ Omitted when false.
+ "last_event_at": "2020-02-20 00:00:00", # Optional. Timestamp of the
+ most recent event in this session's canonical stream. Drives the inactivity
+ policy that destroys idle sessions.
+ "name": "str", # Optional. User-assignable display name, unique per
+ team among non-terminal sessions. Usable in place of session_id by clients
+ (doctl / Console resolve it to the id via the ListSessions ?name= filter; the
+ {session_id} path stays UUID-only). Supplied via the environment-spec
+ metadata.name, or auto-generated
+ ("session-:code:``-:code:``") when omitted.
+ "openai_environment_id": "str", # Optional. OpenAI Agents API
+ environment id (env_"u2026), captured from the resolved CODEX_ENVIRONMENT_ID
+ guest env value. Populated only for AGENT_KIND_OPENAI_CODEX sessions.
+ Non-secret correlation metadata.
+ "openai_session_id": "str", # Optional. OpenAI Agents API session id
+ (sess_"u2026) this DO sandbox hosts. Populated only for
+ AGENT_KIND_OPENAI_CODEX sessions (empty otherwise). Non-secret correlation
+ metadata; a client (doctl agents attach) reads it to bridge to the OpenAI
+ session. See docs/design/openai-sandbox-provider.md.
+ "parent_session_id": "str", # Optional. Lineage: id of the session
+ this one was forked from. Omitted/empty for root (non-fork) sessions.
+ "pause_reason": "str", # Optional. Why this session is paused.
+ Present only when status is SESSION_STATUS_PAUSED; omitted otherwise. Known
+ values: manual (PauseSession RPC), idle (inactivity auto-pause), low_balance
+ (prepay gate). Clients should treat an unrecognized value as an opaque reason
+ string.
+ "repo_hint": "str", # Optional. Optional repository hint supplied at
+ session creation (first spec.workspace.repos entry of the manifest). Not
+ authoritative; the agent may change repos in-session.
+ "resume_on_topoff": bool, # Optional. Session consents to being
+ resumed automatically when the team's prepayment balance is restored after a
+ low-balance pause. Defaults to false at create time; may be toggled later via
+ PATCH /v2/agents/sessions/{session_id} (resume_on_topoff only). Only a
+ session paused with reason low_balance whose latest run did not complete is
+ ever resumed automatically - a session the customer paused themselves, or one
+ that idled out, stays paused regardless. Not an environment-spec field, and
+ forks do not inherit it. Omitted when false.
+ "sandbox_id": "str", # Optional. Sandbox identity for support /
+ debugging. Informational; omitted until a sandbox is allocated.
+ "session_id": "str", # Optional. Session is the user-facing record
+ of a environment session + sandbox pair.
+ "status": "SESSION_STATUS_UNSPECIFIED", # Optional. Default value is
+ "SESSION_STATUS_UNSPECIFIED". SessionStatus is the lifecycle state of the
+ sandbox + agent pair. SESSION_STATUS_ALL is a ListSessions status-filter
+ value only -- no session is ever actually in this status.
+ SESSION_STATUS_LOCKED is reserved for internal use and never appears in an
+ end-user-facing response. Known values are: "SESSION_STATUS_UNSPECIFIED",
+ "SESSION_STATUS_PROVISIONING", "SESSION_STATUS_READY",
+ "SESSION_STATUS_DETACHED", "SESSION_STATUS_DESTROYING",
+ "SESSION_STATUS_DESTROYED", "SESSION_STATUS_FAILED", "SESSION_STATUS_PAUSED",
+ "SESSION_STATUS_ALL", and "SESSION_STATUS_LOCKED".
+ "warnings": [
+ "str" # Optional. Non-fatal advisories computed from the
+ manifest at create time: one entry per populated
+ accepted-but-not-yet-enforced section (flat names: secrets, model, tools,
+ memory, budget, max_lifetime, mounts; legacy manifests get the
+ corresponding spec.* paths), a deprecation entry when a legacy-envelope
+ manifest or an adapter alias (codex-cli, cursor-cli) is used, and a
+ heuristic entry per credential-looking spec.env value. Populated on the
+ CreateSession response only.
+ ]
+ }
+ }
+ # response body for status code(s): 400, 402, 403, 404, 409, 413, 415, 501, 503
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+
+ @distributed_trace_async
+ async def create_session(
+ self,
+ body: Union[JSON, IO[bytes]],
+ *,
+ x_device_uuid: Optional[str] = None,
+ openai_session_id: Optional[str] = None,
+ resume_on_topoff: Optional[bool] = None,
+ **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """CreateSession provisions a sandbox and starts a Harness Runtime session.
+
+ Returns once the session row is allocated. Sandbox boot completes asynchronously.
+
+ Two mutually exclusive request forms are selected by Content-Type (same contract as
+ harness-api ``harness.swagger.json``\\ ):
+
+
+ * YAML (\\ ``application/x-yaml``\\ , ``application/yaml``\\ , ``text/yaml``\\ ,
+ ``text/x-yaml``\\ ): the environment
+ spec. Two environment-spec formats are accepted during the dual-format transition: the flat
+ format (primary) and the legacy ``agents.digitalocean.com/v1alpha1`` envelope (deprecated). A
+ top-level ``apiVersion`` key selects the legacy parser; its absence selects flat. Internally
+ persists a durable Environment Config, then creates the session.
+ * JSON (\\ ``application/json``\\ ): ``{name, config_id}`` loads the config, resolves its
+ credentials from
+ Secrets Manager at the version pinned when the config was created, and creates the session.
+
+ The OpenAPI ``requestBody`` schemas the JSON form for client generation (Autorest cannot emit a
+ multi–content-type body). The live API still accepts the YAML forms listed above.
+
+ Successful responses may include ``config_id`` on the session. ``X-Device-UUID`` (if present)
+ is
+ persisted on the session row. Query parameters ``openai_session_id`` and ``resume_on_topoff``
+ apply to
+ both forms; when both the JSON body field and ``?resume_on_topoff=`` are present, the query
+ parameter wins.
+
+ :param body: CreateSessionConfigRequest with ``application/json``. The live API also accepts a
+ raw environment
+ spec under YAML Content-Types (see operation description); those forms are omitted from
+ ``content``
+ so generated clients (pydo/autorest) can emit this operation. Is either a JSON type or a
+ IO[bytes] type. Required.
+ :type body: JSON or IO[bytes]
+ :keyword x_device_uuid: Optional hardware device id forwarded by doctl. Persisted on the
+ session row for lifecycle attribution. Values over 128 bytes are ignored. Default value is
+ None.
+ :paramtype x_device_uuid: str
+ :keyword openai_session_id: OpenAI Agents API session id (sess_…) for adapter: codex-agentapi.
+ doctl creates the OpenAI session before calling DO and passes the resulting id here;
+ harness-api persists it for correlation. Empty/omitted for every other agent kind. Default
+ value is None.
+ :paramtype openai_session_id: str
+ :keyword resume_on_topoff: Opt the new session in to automatic resumption when the team's
+ prepayment balance is restored. Defaults to false. Exists as a query parameter so the
+ environment spec (YAML body) form can carry it too. On the application/json form the body field
+ is idiomatic, but this parameter wins when both are present. Must be exactly one of
+ true/false/1/0; anything else is a 400. Default value is None.
+ :paramtype resume_on_topoff: bool
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "config_id": "str", # Required.
+ "name": "str", # Session name, independent of the config name. Must satisfy
+ the existing environment-spec metadata.name rules and must not be UUID-shaped.
+ Required.
+ "resume_on_topoff": bool # Optional. Opt the new session in to automatic
+ resumption when the team's prepayment balance is restored. Defaults to false.
+ Session-scoped, not config-scoped: the referenced config never confers this, so
+ one shared config cannot enrol every session created from it. Omit to leave the
+ default (or to let the ?resume_on_topoff= query parameter supply it).
+ }
+
+ # response body for status code(s): 200
+ response == {
+ "session": {
+ "agent_kind": "AGENT_KIND_UNSPECIFIED", # Optional. Default value is
+ "AGENT_KIND_UNSPECIFIED". AgentKind identifies what runs inside the session
+ sandbox. CreateSession accepts CLAUDE_CODE, OPENCODE, CODEX_CLI, CURSOR_CLI,
+ OPENAI_CODEX, LANGGRAPH, and CREWAI (the supported set is overridable via
+ HARNESS_SUPPORTED_AGENT_KINDS); other values are rejected with 400.
+ AGENT_KIND_OPENAI_CODEX is the OpenAI sandbox-provider kind (DO runs codex
+ exec-server; the agent loop lives at OpenAI). AGENT_KIND_LANGGRAPH is the
+ LangGraph framework adapter. AGENT_KIND_CREWAI is the CrewAI Crew framework
+ adapter: like LANGGRAPH the template bakes no agent code, so spec.env must
+ supply FRAMEWORK_REPO and FRAMEWORK_REPO_SHA; a Crew kickoff is one-shot and
+ exposes no HITL surface. CREWAI is additionally gated per team and returns
+ 400 for teams it is not enabled for. Known values are:
+ "AGENT_KIND_UNSPECIFIED", "AGENT_KIND_CLAUDE_CODE", "AGENT_KIND_OPENCODE",
+ "AGENT_KIND_CODEX_CLI", "AGENT_KIND_CURSOR_CLI", "AGENT_KIND_NONE",
+ "AGENT_KIND_CUSTOM", "AGENT_KIND_HERMES", "AGENT_KIND_OPENAI_CODEX",
+ "AGENT_KIND_LANGGRAPH", and "AGENT_KIND_CREWAI".
+ "config_id": "str", # Optional. Durable Environment Config UUID the
+ session was created from (inline manifests persist a config too, named after
+ the session). Persisted and returned on create/get/list; absent only for
+ sessions created before config references were stored.
+ "created_at": "2020-02-20 00:00:00", # Optional. Session is the
+ user-facing record of a environment session + sandbox pair.
+ "fork_from_checkpoint_id": "str", # Optional. Lineage: harness-api
+ checkpoint id (cp_:code:``) the child booted from at fork time. Drives
+ OHP inherited-history replay on attach. Omitted/empty for root sessions and
+ legacy forks created before this field was persisted.
+ "fork_id": "str", # Optional. Lineage: branch label assigned when
+ this session was created by ForkSession (or rollback's internal fork).
+ Omitted/empty for root sessions.
+ "idle_timeout_seconds": 0, # Optional. This session's own idle-pause
+ timeout (manifest idle_timeout). Omitted when the session uses the
+ deployment-wide default.
+ "keep_warm": bool, # Optional. Session is exempt from idle
+ auto-pause (manifest keep_warm, or the agent-kind default: hermes sessions
+ keep warm). Pause requests against such a session are rejected with 409.
+ Omitted when false.
+ "last_event_at": "2020-02-20 00:00:00", # Optional. Timestamp of the
+ most recent event in this session's canonical stream. Drives the inactivity
+ policy that destroys idle sessions.
+ "name": "str", # Optional. User-assignable display name, unique per
+ team among non-terminal sessions. Usable in place of session_id by clients
+ (doctl / Console resolve it to the id via the ListSessions ?name= filter; the
+ {session_id} path stays UUID-only). Supplied via the environment-spec
+ metadata.name, or auto-generated
+ ("session-:code:``-:code:``") when omitted.
+ "openai_environment_id": "str", # Optional. OpenAI Agents API
+ environment id (env_"u2026), captured from the resolved CODEX_ENVIRONMENT_ID
+ guest env value. Populated only for AGENT_KIND_OPENAI_CODEX sessions.
+ Non-secret correlation metadata.
+ "openai_session_id": "str", # Optional. OpenAI Agents API session id
+ (sess_"u2026) this DO sandbox hosts. Populated only for
+ AGENT_KIND_OPENAI_CODEX sessions (empty otherwise). Non-secret correlation
+ metadata; a client (doctl agents attach) reads it to bridge to the OpenAI
+ session. See docs/design/openai-sandbox-provider.md.
+ "parent_session_id": "str", # Optional. Lineage: id of the session
+ this one was forked from. Omitted/empty for root (non-fork) sessions.
+ "pause_reason": "str", # Optional. Why this session is paused.
+ Present only when status is SESSION_STATUS_PAUSED; omitted otherwise. Known
+ values: manual (PauseSession RPC), idle (inactivity auto-pause), low_balance
+ (prepay gate). Clients should treat an unrecognized value as an opaque reason
+ string.
+ "repo_hint": "str", # Optional. Optional repository hint supplied at
+ session creation (first spec.workspace.repos entry of the manifest). Not
+ authoritative; the agent may change repos in-session.
+ "resume_on_topoff": bool, # Optional. Session consents to being
+ resumed automatically when the team's prepayment balance is restored after a
+ low-balance pause. Defaults to false at create time; may be toggled later via
+ PATCH /v2/agents/sessions/{session_id} (resume_on_topoff only). Only a
+ session paused with reason low_balance whose latest run did not complete is
+ ever resumed automatically - a session the customer paused themselves, or one
+ that idled out, stays paused regardless. Not an environment-spec field, and
+ forks do not inherit it. Omitted when false.
+ "sandbox_id": "str", # Optional. Sandbox identity for support /
+ debugging. Informational; omitted until a sandbox is allocated.
+ "session_id": "str", # Optional. Session is the user-facing record
+ of a environment session + sandbox pair.
+ "status": "SESSION_STATUS_UNSPECIFIED", # Optional. Default value is
+ "SESSION_STATUS_UNSPECIFIED". SessionStatus is the lifecycle state of the
+ sandbox + agent pair. SESSION_STATUS_ALL is a ListSessions status-filter
+ value only -- no session is ever actually in this status.
+ SESSION_STATUS_LOCKED is reserved for internal use and never appears in an
+ end-user-facing response. Known values are: "SESSION_STATUS_UNSPECIFIED",
+ "SESSION_STATUS_PROVISIONING", "SESSION_STATUS_READY",
+ "SESSION_STATUS_DETACHED", "SESSION_STATUS_DESTROYING",
+ "SESSION_STATUS_DESTROYED", "SESSION_STATUS_FAILED", "SESSION_STATUS_PAUSED",
+ "SESSION_STATUS_ALL", and "SESSION_STATUS_LOCKED".
+ "warnings": [
+ "str" # Optional. Non-fatal advisories computed from the
+ manifest at create time: one entry per populated
+ accepted-but-not-yet-enforced section (flat names: secrets, model, tools,
+ memory, budget, max_lifetime, mounts; legacy manifests get the
+ corresponding spec.* paths), a deprecation entry when a legacy-envelope
+ manifest or an adapter alias (codex-cli, cursor-cli) is used, and a
+ heuristic entry per credential-looking spec.env value. Populated on the
+ CreateSession response only.
+ ]
+ }
+ }
+ # response body for status code(s): 400, 402, 403, 404, 409, 413, 415, 501, 503
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
+ _params = kwargs.pop("params", {}) or {}
+
+ content_type: Optional[str] = kwargs.pop(
+ "content_type", _headers.pop("Content-Type", None)
+ )
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ content_type = content_type or "application/json"
+ _json = None
+ _content = None
+ if isinstance(body, (IOBase, bytes)):
+ _content = body
+ else:
+ _json = body
+
+ _request = build_harness_create_session_request(
+ x_device_uuid=x_device_uuid,
+ openai_session_id=openai_session_id,
+ resume_on_topoff=resume_on_topoff,
+ content_type=content_type,
+ json=_json,
+ content=_content,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [
+ 200,
+ 400,
+ 402,
+ 403,
+ 404,
+ 409,
+ 413,
+ 415,
+ 501,
+ 503,
+ ]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ if response.status_code == 200:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 400:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 402:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 403:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 409:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 413:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 415:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 501:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 503:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+ @distributed_trace_async
+ async def validate_session_policy(self, data: IO[bytes], **kwargs: Any) -> JSON:
+ # pylint: disable=line-too-long
+ """ValidatePolicy checks a manifest's tool-permission policy against the agent's capabilities
+ without creating a session.
+
+ Stateless preflight: parses the same environment spec as CreateSession and runs the identical
+ resolve + validate pipeline against the capability descriptor stamped on the selected
+ template's image (resolved per-request via the sandbox, not a separate registry). Returns
+ per-rule verdicts. Nothing is provisioned or persisted.
+
+ Each rule is validated against the descriptor for the (agent, version) the template resolves to
+ and gets a verdict: ``exact``\\ , ``degraded``\\ , ``unsupported``\\ , or ``unverified``.
+ ``ok`` is false when any strict rule is unsupported or unverified — i.e. CreateSession would
+ reject the policy for that agent. An empty ``spec.permissions`` returns ``ok: true`` with no
+ verdicts. Because it shares the create path's descriptor lookup, the verdicts match what
+ CreateSession would compute.
+
+ :param data: The same environment spec you would submit to CreateSession (YAML). Only
+ agent/template selection
+ and the permissions block are used. The live API also accepts ``application/yaml``\\ ,
+ ``text/yaml``\\ , and
+ ``text/x-yaml``\\ ; OpenAPI ``content`` lists a single media type so generated clients can
+ emit this
+ operation. Required.
+ :type data: IO[bytes]
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 200
+ response == {
+ "agent": "str", # Optional.
+ "defaultAction": "str", # Optional. Catch-all disposition AS SHIPPED (after
+ unverified allow"u2192ask downgrade). When defaultActionVerdict is degraded, this
+ remains the shipped value; see defaultActionRendered for what the agent will
+ actually enforce. Known values are: "allow", "ask", and "deny".
+ "defaultActionReason": "str", # Optional. Human-readable explanation when
+ defaultActionVerdict is degraded.
+ "defaultActionRendered": "str", # Optional. Disposition the agent will
+ actually enforce as the catch-all: equals defaultAction when exact; the
+ more-restrictive degrade target (usually ask) when degraded. Known values are:
+ "allow", "ask", and "deny".
+ "defaultActionVerdict": "str", # Optional. exact "u2014 agent can enforce
+ the catch-all as written; degraded "u2014 agent cannot enforce the requested
+ defaultAction (warn-only; shipped value unchanged); omitted when no descriptor
+ was available to classify against. Known values are: "exact", "degraded",
+ "unsupported", and "unverified".
+ "ok": bool, # Optional. False when any strict rule is unsupported or
+ unverified "u2014 i.e. CreateSession would reject this policy for this (agent,
+ version).
+ "verdicts": [
+ {
+ "reason": "str", # Optional. Human-readable explanation of
+ the verdict.
+ "rendered": "str", # Optional. The disposition the agent
+ will actually enforce: the requested action when exact/unverified, the
+ more-restrictive target when degraded, omitted when unsupported (cannot
+ render). Known values are: "allow", "ask", and "deny".
+ "rule": {
+ "action": "str", # Optional. Known values are:
+ "allow", "ask", and "deny".
+ "enforcement": "str", # Optional. Known values are:
+ "strict" and "best-effort".
+ "id": "str", # Optional. Stable rule id assigned
+ during resolution; correlates with the PolicyDenied event's matched
+ rule.
+ "match": {
+ "str": "str" # Optional. Dictionary of
+ :code:``.
+ },
+ "tool": "str" # Optional. A rule after resolution
+ ("u2229 tenant "u2229 platform), carrying a stable id for audit
+ correlation.
+ },
+ "suggestion": "str", # Optional. Optional actionable hint
+ (e.g. "set enforcement: best-effort, or target a capable agent").
+ "verdict": "str" # Optional. exact "u2014 enforced precisely
+ as written; degraded "u2014 renderable only in a more-restrictive form
+ (deny"u2192ask), warned; unsupported "u2014 cannot be enforced (strict
+ "u21d2 session reject); unverified "u2014 no descriptor available,
+ rendered conservatively but unproven. Known values are: "exact",
+ "degraded", "unsupported", and "unverified".
+ }
+ ],
+ "version": "str" # Optional.
+ }
+ # response body for status code(s): 400, 404
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = kwargs.pop("headers", {}) or {}
+ _params = kwargs.pop("params", {}) or {}
+
+ content_type: str = kwargs.pop("content_type")
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ _content = data
+ if not content_type:
+ raise TypeError(
+ "Missing required keyword-only argument: content_type. Known values are:"
+ + "'application/x-yaml'"
+ )
+
+ _request = build_harness_validate_session_policy_request(
+ content_type=content_type,
+ content=_content,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 400, 404]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ if response.status_code == 200:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 400:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+ @distributed_trace_async
+ async def list_session_sandbox_sizes(self, **kwargs: Any) -> JSON:
+ # pylint: disable=line-too-long
+ """ListSandboxSizes returns the customer-selectable sandbox (microVM) size catalog.
+
+ Read-only catalog the UI (and other clients) render as the size picker, instead of hardcoding
+ the list. The set is the single source of truth shared with create-time validation and the
+ default-size fallback, so every ``slug`` returned here is accepted by CreateSession as
+ spec.sandbox.sizeSlug. Sizes are returned smallest-to-largest. Static and safe to cache;
+ independent of team/session; no pagination.
+
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 200
+ response == {
+ "sizes": [
+ {
+ "memory_mb": 0, # Optional. Memory in MB (for display).
+ "price_per_hour_usd": 0.0, # Optional. Hourly on-demand
+ price in USD (for display).
+ "price_per_month_usd": 0.0, # Optional. Monthly on-demand
+ price in USD, assuming continuous usage (for display).
+ "slug": "str", # Optional. DO size slug; submit as
+ spec.sandbox.sizeSlug on CreateSession. e.g. "mars-2vcpu-4gb".
+ "vcpus": 0 # Optional. vCPU count (for display).
+ }
+ ]
+ }
+ # response body for status code(s): 404
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = kwargs.pop("headers", {}) or {}
+ _params = kwargs.pop("params", {}) or {}
+
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ _request = build_harness_list_session_sandbox_sizes_request(
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 404]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ if response.status_code == 200:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+ @distributed_trace_async
+ async def delete_session(
+ self, session_id: str, *, x_device_uuid: Optional[str] = None, **kwargs: Any
+ ) -> Optional[JSON]:
+ # pylint: disable=line-too-long
+ """DestroySession tears down the sandbox and marks the session DESTROYED.
+
+ Persistent workspace contents are retained per tenant policy. Returns 204 No Content on
+ success.
+
+ :param session_id: The session UUID. Required.
+ :type session_id: str
+ :keyword x_device_uuid: Optional hardware device id forwarded by doctl. Recorded on the session
+ row as the device that performed the destroy. Default value is None.
+ :paramtype x_device_uuid: str
+ :return: JSON object or None
+ :rtype: JSON or None
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 403, 404, 423
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = kwargs.pop("headers", {}) or {}
+ _params = kwargs.pop("params", {}) or {}
+
+ cls: ClsType[Optional[JSON]] = kwargs.pop("cls", None)
+
+ _request = build_harness_delete_session_request(
+ session_id=session_id,
+ x_device_uuid=x_device_uuid,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [204, 403, 404, 423]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ deserialized = None
+ response_headers = {}
+ if response.status_code == 204:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.status_code == 403:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 423:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, deserialized, response_headers) # type: ignore
+
+ return deserialized # type: ignore
+
+ @distributed_trace_async
+ async def get_session(self, session_id: str, **kwargs: Any) -> JSON:
+ # pylint: disable=line-too-long
+ """GetSession returns the current snapshot of a session.
+
+ GetSession returns the current snapshot of a session.
+
+ :param session_id: The session UUID. Required.
+ :type session_id: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 200
+ response == {
+ "session": {
+ "agent_kind": "AGENT_KIND_UNSPECIFIED", # Optional. Default value is
+ "AGENT_KIND_UNSPECIFIED". AgentKind identifies what runs inside the session
+ sandbox. CreateSession accepts CLAUDE_CODE, OPENCODE, CODEX_CLI, CURSOR_CLI,
+ OPENAI_CODEX, LANGGRAPH, and CREWAI (the supported set is overridable via
+ HARNESS_SUPPORTED_AGENT_KINDS); other values are rejected with 400.
+ AGENT_KIND_OPENAI_CODEX is the OpenAI sandbox-provider kind (DO runs codex
+ exec-server; the agent loop lives at OpenAI). AGENT_KIND_LANGGRAPH is the
+ LangGraph framework adapter. AGENT_KIND_CREWAI is the CrewAI Crew framework
+ adapter: like LANGGRAPH the template bakes no agent code, so spec.env must
+ supply FRAMEWORK_REPO and FRAMEWORK_REPO_SHA; a Crew kickoff is one-shot and
+ exposes no HITL surface. CREWAI is additionally gated per team and returns
+ 400 for teams it is not enabled for. Known values are:
+ "AGENT_KIND_UNSPECIFIED", "AGENT_KIND_CLAUDE_CODE", "AGENT_KIND_OPENCODE",
+ "AGENT_KIND_CODEX_CLI", "AGENT_KIND_CURSOR_CLI", "AGENT_KIND_NONE",
+ "AGENT_KIND_CUSTOM", "AGENT_KIND_HERMES", "AGENT_KIND_OPENAI_CODEX",
+ "AGENT_KIND_LANGGRAPH", and "AGENT_KIND_CREWAI".
+ "config_id": "str", # Optional. Durable Environment Config UUID the
+ session was created from (inline manifests persist a config too, named after
+ the session). Persisted and returned on create/get/list; absent only for
+ sessions created before config references were stored.
+ "created_at": "2020-02-20 00:00:00", # Optional. Session is the
+ user-facing record of a environment session + sandbox pair.
+ "fork_from_checkpoint_id": "str", # Optional. Lineage: harness-api
+ checkpoint id (cp_:code:``) the child booted from at fork time. Drives
+ OHP inherited-history replay on attach. Omitted/empty for root sessions and
+ legacy forks created before this field was persisted.
+ "fork_id": "str", # Optional. Lineage: branch label assigned when
+ this session was created by ForkSession (or rollback's internal fork).
+ Omitted/empty for root sessions.
+ "idle_timeout_seconds": 0, # Optional. This session's own idle-pause
+ timeout (manifest idle_timeout). Omitted when the session uses the
+ deployment-wide default.
+ "keep_warm": bool, # Optional. Session is exempt from idle
+ auto-pause (manifest keep_warm, or the agent-kind default: hermes sessions
+ keep warm). Pause requests against such a session are rejected with 409.
+ Omitted when false.
+ "last_event_at": "2020-02-20 00:00:00", # Optional. Timestamp of the
+ most recent event in this session's canonical stream. Drives the inactivity
+ policy that destroys idle sessions.
+ "name": "str", # Optional. User-assignable display name, unique per
+ team among non-terminal sessions. Usable in place of session_id by clients
+ (doctl / Console resolve it to the id via the ListSessions ?name= filter; the
+ {session_id} path stays UUID-only). Supplied via the environment-spec
+ metadata.name, or auto-generated
+ ("session-:code:``-:code:``") when omitted.
+ "openai_environment_id": "str", # Optional. OpenAI Agents API
+ environment id (env_"u2026), captured from the resolved CODEX_ENVIRONMENT_ID
+ guest env value. Populated only for AGENT_KIND_OPENAI_CODEX sessions.
+ Non-secret correlation metadata.
+ "openai_session_id": "str", # Optional. OpenAI Agents API session id
+ (sess_"u2026) this DO sandbox hosts. Populated only for
+ AGENT_KIND_OPENAI_CODEX sessions (empty otherwise). Non-secret correlation
+ metadata; a client (doctl agents attach) reads it to bridge to the OpenAI
+ session. See docs/design/openai-sandbox-provider.md.
+ "parent_session_id": "str", # Optional. Lineage: id of the session
+ this one was forked from. Omitted/empty for root (non-fork) sessions.
+ "pause_reason": "str", # Optional. Why this session is paused.
+ Present only when status is SESSION_STATUS_PAUSED; omitted otherwise. Known
+ values: manual (PauseSession RPC), idle (inactivity auto-pause), low_balance
+ (prepay gate). Clients should treat an unrecognized value as an opaque reason
+ string.
+ "repo_hint": "str", # Optional. Optional repository hint supplied at
+ session creation (first spec.workspace.repos entry of the manifest). Not
+ authoritative; the agent may change repos in-session.
+ "resume_on_topoff": bool, # Optional. Session consents to being
+ resumed automatically when the team's prepayment balance is restored after a
+ low-balance pause. Defaults to false at create time; may be toggled later via
+ PATCH /v2/agents/sessions/{session_id} (resume_on_topoff only). Only a
+ session paused with reason low_balance whose latest run did not complete is
+ ever resumed automatically - a session the customer paused themselves, or one
+ that idled out, stays paused regardless. Not an environment-spec field, and
+ forks do not inherit it. Omitted when false.
+ "sandbox_id": "str", # Optional. Sandbox identity for support /
+ debugging. Informational; omitted until a sandbox is allocated.
+ "session_id": "str", # Optional. Session is the user-facing record
+ of a environment session + sandbox pair.
+ "status": "SESSION_STATUS_UNSPECIFIED", # Optional. Default value is
+ "SESSION_STATUS_UNSPECIFIED". SessionStatus is the lifecycle state of the
+ sandbox + agent pair. SESSION_STATUS_ALL is a ListSessions status-filter
+ value only -- no session is ever actually in this status.
+ SESSION_STATUS_LOCKED is reserved for internal use and never appears in an
+ end-user-facing response. Known values are: "SESSION_STATUS_UNSPECIFIED",
+ "SESSION_STATUS_PROVISIONING", "SESSION_STATUS_READY",
+ "SESSION_STATUS_DETACHED", "SESSION_STATUS_DESTROYING",
+ "SESSION_STATUS_DESTROYED", "SESSION_STATUS_FAILED", "SESSION_STATUS_PAUSED",
+ "SESSION_STATUS_ALL", and "SESSION_STATUS_LOCKED".
+ "warnings": [
+ "str" # Optional. Non-fatal advisories computed from the
+ manifest at create time: one entry per populated
+ accepted-but-not-yet-enforced section (flat names: secrets, model, tools,
+ memory, budget, max_lifetime, mounts; legacy manifests get the
+ corresponding spec.* paths), a deprecation entry when a legacy-envelope
+ manifest or an adapter alias (codex-cli, cursor-cli) is used, and a
+ heuristic entry per credential-looking spec.env value. Populated on the
+ CreateSession response only.
+ ]
+ }
+ }
+ # response body for status code(s): 403, 404, 423
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = kwargs.pop("headers", {}) or {}
+ _params = kwargs.pop("params", {}) or {}
+
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ _request = build_harness_get_session_request(
+ session_id=session_id,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 403, 404, 423]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ if response.status_code == 200:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 403:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 423:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+ @overload
+ async def update_session(
+ self,
+ session_id: str,
+ body: JSON,
+ *,
+ content_type: str = "application/json",
+ **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """PatchSession updates session-scoped settings on an existing session.
+
+ Partial update of session-scoped settings (not the agent manifest / config). The body must
+ include at least one recognized patchable property; an empty object {} is 400. Only properties
+ listed on PatchSessionRequest are accepted — any other top-level JSON key is rejected with 400.
+ Omitted properties are left unchanged. Today the only patchable field is resume_on_topoff; more
+ session settings may be added over time. Terminal sessions (DESTROYED, FAILED) cannot be
+ patched.
+
+ :param session_id: The session UUID. Required.
+ :type session_id: str
+ :param body: PATCH body: allowlisted session-scoped settings. At least one property required.
+ Required.
+ :type body: JSON
+ :keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
+ Default value is "application/json".
+ :paramtype content_type: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "resume_on_topoff": bool # Optional. When present, sets whether this session
+ opts in to automatic resumption when the team's prepayment balance is restored
+ after a low-balance pause. Session-scoped consent, not config-scoped. Omitted
+ properties are not modified.
+ }
+
+ # response body for status code(s): 200
+ response == {
+ "session": {
+ "agent_kind": "AGENT_KIND_UNSPECIFIED", # Optional. Default value is
+ "AGENT_KIND_UNSPECIFIED". AgentKind identifies what runs inside the session
+ sandbox. CreateSession accepts CLAUDE_CODE, OPENCODE, CODEX_CLI, CURSOR_CLI,
+ OPENAI_CODEX, LANGGRAPH, and CREWAI (the supported set is overridable via
+ HARNESS_SUPPORTED_AGENT_KINDS); other values are rejected with 400.
+ AGENT_KIND_OPENAI_CODEX is the OpenAI sandbox-provider kind (DO runs codex
+ exec-server; the agent loop lives at OpenAI). AGENT_KIND_LANGGRAPH is the
+ LangGraph framework adapter. AGENT_KIND_CREWAI is the CrewAI Crew framework
+ adapter: like LANGGRAPH the template bakes no agent code, so spec.env must
+ supply FRAMEWORK_REPO and FRAMEWORK_REPO_SHA; a Crew kickoff is one-shot and
+ exposes no HITL surface. CREWAI is additionally gated per team and returns
+ 400 for teams it is not enabled for. Known values are:
+ "AGENT_KIND_UNSPECIFIED", "AGENT_KIND_CLAUDE_CODE", "AGENT_KIND_OPENCODE",
+ "AGENT_KIND_CODEX_CLI", "AGENT_KIND_CURSOR_CLI", "AGENT_KIND_NONE",
+ "AGENT_KIND_CUSTOM", "AGENT_KIND_HERMES", "AGENT_KIND_OPENAI_CODEX",
+ "AGENT_KIND_LANGGRAPH", and "AGENT_KIND_CREWAI".
+ "config_id": "str", # Optional. Durable Environment Config UUID the
+ session was created from (inline manifests persist a config too, named after
+ the session). Persisted and returned on create/get/list; absent only for
+ sessions created before config references were stored.
+ "created_at": "2020-02-20 00:00:00", # Optional. Session is the
+ user-facing record of a environment session + sandbox pair.
+ "fork_from_checkpoint_id": "str", # Optional. Lineage: harness-api
+ checkpoint id (cp_:code:``) the child booted from at fork time. Drives
+ OHP inherited-history replay on attach. Omitted/empty for root sessions and
+ legacy forks created before this field was persisted.
+ "fork_id": "str", # Optional. Lineage: branch label assigned when
+ this session was created by ForkSession (or rollback's internal fork).
+ Omitted/empty for root sessions.
+ "idle_timeout_seconds": 0, # Optional. This session's own idle-pause
+ timeout (manifest idle_timeout). Omitted when the session uses the
+ deployment-wide default.
+ "keep_warm": bool, # Optional. Session is exempt from idle
+ auto-pause (manifest keep_warm, or the agent-kind default: hermes sessions
+ keep warm). Pause requests against such a session are rejected with 409.
+ Omitted when false.
+ "last_event_at": "2020-02-20 00:00:00", # Optional. Timestamp of the
+ most recent event in this session's canonical stream. Drives the inactivity
+ policy that destroys idle sessions.
+ "name": "str", # Optional. User-assignable display name, unique per
+ team among non-terminal sessions. Usable in place of session_id by clients
+ (doctl / Console resolve it to the id via the ListSessions ?name= filter; the
+ {session_id} path stays UUID-only). Supplied via the environment-spec
+ metadata.name, or auto-generated
+ ("session-:code:``-:code:``") when omitted.
+ "openai_environment_id": "str", # Optional. OpenAI Agents API
+ environment id (env_"u2026), captured from the resolved CODEX_ENVIRONMENT_ID
+ guest env value. Populated only for AGENT_KIND_OPENAI_CODEX sessions.
+ Non-secret correlation metadata.
+ "openai_session_id": "str", # Optional. OpenAI Agents API session id
+ (sess_"u2026) this DO sandbox hosts. Populated only for
+ AGENT_KIND_OPENAI_CODEX sessions (empty otherwise). Non-secret correlation
+ metadata; a client (doctl agents attach) reads it to bridge to the OpenAI
+ session. See docs/design/openai-sandbox-provider.md.
+ "parent_session_id": "str", # Optional. Lineage: id of the session
+ this one was forked from. Omitted/empty for root (non-fork) sessions.
+ "pause_reason": "str", # Optional. Why this session is paused.
+ Present only when status is SESSION_STATUS_PAUSED; omitted otherwise. Known
+ values: manual (PauseSession RPC), idle (inactivity auto-pause), low_balance
+ (prepay gate). Clients should treat an unrecognized value as an opaque reason
+ string.
+ "repo_hint": "str", # Optional. Optional repository hint supplied at
+ session creation (first spec.workspace.repos entry of the manifest). Not
+ authoritative; the agent may change repos in-session.
+ "resume_on_topoff": bool, # Optional. Session consents to being
+ resumed automatically when the team's prepayment balance is restored after a
+ low-balance pause. Defaults to false at create time; may be toggled later via
+ PATCH /v2/agents/sessions/{session_id} (resume_on_topoff only). Only a
+ session paused with reason low_balance whose latest run did not complete is
+ ever resumed automatically - a session the customer paused themselves, or one
+ that idled out, stays paused regardless. Not an environment-spec field, and
+ forks do not inherit it. Omitted when false.
+ "sandbox_id": "str", # Optional. Sandbox identity for support /
+ debugging. Informational; omitted until a sandbox is allocated.
+ "session_id": "str", # Optional. Session is the user-facing record
+ of a environment session + sandbox pair.
+ "status": "SESSION_STATUS_UNSPECIFIED", # Optional. Default value is
+ "SESSION_STATUS_UNSPECIFIED". SessionStatus is the lifecycle state of the
+ sandbox + agent pair. SESSION_STATUS_ALL is a ListSessions status-filter
+ value only -- no session is ever actually in this status.
+ SESSION_STATUS_LOCKED is reserved for internal use and never appears in an
+ end-user-facing response. Known values are: "SESSION_STATUS_UNSPECIFIED",
+ "SESSION_STATUS_PROVISIONING", "SESSION_STATUS_READY",
+ "SESSION_STATUS_DETACHED", "SESSION_STATUS_DESTROYING",
+ "SESSION_STATUS_DESTROYED", "SESSION_STATUS_FAILED", "SESSION_STATUS_PAUSED",
+ "SESSION_STATUS_ALL", and "SESSION_STATUS_LOCKED".
+ "warnings": [
+ "str" # Optional. Non-fatal advisories computed from the
+ manifest at create time: one entry per populated
+ accepted-but-not-yet-enforced section (flat names: secrets, model, tools,
+ memory, budget, max_lifetime, mounts; legacy manifests get the
+ corresponding spec.* paths), a deprecation entry when a legacy-envelope
+ manifest or an adapter alias (codex-cli, cursor-cli) is used, and a
+ heuristic entry per credential-looking spec.env value. Populated on the
+ CreateSession response only.
+ ]
+ }
+ }
+ # response body for status code(s): 400, 403, 404, 409, 423
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+
+ @overload
+ async def update_session(
+ self,
+ session_id: str,
+ body: IO[bytes],
+ *,
+ content_type: str = "application/json",
+ **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """PatchSession updates session-scoped settings on an existing session.
+
+ Partial update of session-scoped settings (not the agent manifest / config). The body must
+ include at least one recognized patchable property; an empty object {} is 400. Only properties
+ listed on PatchSessionRequest are accepted — any other top-level JSON key is rejected with 400.
+ Omitted properties are left unchanged. Today the only patchable field is resume_on_topoff; more
+ session settings may be added over time. Terminal sessions (DESTROYED, FAILED) cannot be
+ patched.
+
+ :param session_id: The session UUID. Required.
+ :type session_id: str
+ :param body: PATCH body: allowlisted session-scoped settings. At least one property required.
+ Required.
+ :type body: IO[bytes]
+ :keyword content_type: Body Parameter content-type. Content type parameter for binary body.
+ Default value is "application/json".
+ :paramtype content_type: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 200
+ response == {
+ "session": {
+ "agent_kind": "AGENT_KIND_UNSPECIFIED", # Optional. Default value is
+ "AGENT_KIND_UNSPECIFIED". AgentKind identifies what runs inside the session
+ sandbox. CreateSession accepts CLAUDE_CODE, OPENCODE, CODEX_CLI, CURSOR_CLI,
+ OPENAI_CODEX, LANGGRAPH, and CREWAI (the supported set is overridable via
+ HARNESS_SUPPORTED_AGENT_KINDS); other values are rejected with 400.
+ AGENT_KIND_OPENAI_CODEX is the OpenAI sandbox-provider kind (DO runs codex
+ exec-server; the agent loop lives at OpenAI). AGENT_KIND_LANGGRAPH is the
+ LangGraph framework adapter. AGENT_KIND_CREWAI is the CrewAI Crew framework
+ adapter: like LANGGRAPH the template bakes no agent code, so spec.env must
+ supply FRAMEWORK_REPO and FRAMEWORK_REPO_SHA; a Crew kickoff is one-shot and
+ exposes no HITL surface. CREWAI is additionally gated per team and returns
+ 400 for teams it is not enabled for. Known values are:
+ "AGENT_KIND_UNSPECIFIED", "AGENT_KIND_CLAUDE_CODE", "AGENT_KIND_OPENCODE",
+ "AGENT_KIND_CODEX_CLI", "AGENT_KIND_CURSOR_CLI", "AGENT_KIND_NONE",
+ "AGENT_KIND_CUSTOM", "AGENT_KIND_HERMES", "AGENT_KIND_OPENAI_CODEX",
+ "AGENT_KIND_LANGGRAPH", and "AGENT_KIND_CREWAI".
+ "config_id": "str", # Optional. Durable Environment Config UUID the
+ session was created from (inline manifests persist a config too, named after
+ the session). Persisted and returned on create/get/list; absent only for
+ sessions created before config references were stored.
+ "created_at": "2020-02-20 00:00:00", # Optional. Session is the
+ user-facing record of a environment session + sandbox pair.
+ "fork_from_checkpoint_id": "str", # Optional. Lineage: harness-api
+ checkpoint id (cp_:code:``) the child booted from at fork time. Drives
+ OHP inherited-history replay on attach. Omitted/empty for root sessions and
+ legacy forks created before this field was persisted.
+ "fork_id": "str", # Optional. Lineage: branch label assigned when
+ this session was created by ForkSession (or rollback's internal fork).
+ Omitted/empty for root sessions.
+ "idle_timeout_seconds": 0, # Optional. This session's own idle-pause
+ timeout (manifest idle_timeout). Omitted when the session uses the
+ deployment-wide default.
+ "keep_warm": bool, # Optional. Session is exempt from idle
+ auto-pause (manifest keep_warm, or the agent-kind default: hermes sessions
+ keep warm). Pause requests against such a session are rejected with 409.
+ Omitted when false.
+ "last_event_at": "2020-02-20 00:00:00", # Optional. Timestamp of the
+ most recent event in this session's canonical stream. Drives the inactivity
+ policy that destroys idle sessions.
+ "name": "str", # Optional. User-assignable display name, unique per
+ team among non-terminal sessions. Usable in place of session_id by clients
+ (doctl / Console resolve it to the id via the ListSessions ?name= filter; the
+ {session_id} path stays UUID-only). Supplied via the environment-spec
+ metadata.name, or auto-generated
+ ("session-:code:``-:code:``") when omitted.
+ "openai_environment_id": "str", # Optional. OpenAI Agents API
+ environment id (env_"u2026), captured from the resolved CODEX_ENVIRONMENT_ID
+ guest env value. Populated only for AGENT_KIND_OPENAI_CODEX sessions.
+ Non-secret correlation metadata.
+ "openai_session_id": "str", # Optional. OpenAI Agents API session id
+ (sess_"u2026) this DO sandbox hosts. Populated only for
+ AGENT_KIND_OPENAI_CODEX sessions (empty otherwise). Non-secret correlation
+ metadata; a client (doctl agents attach) reads it to bridge to the OpenAI
+ session. See docs/design/openai-sandbox-provider.md.
+ "parent_session_id": "str", # Optional. Lineage: id of the session
+ this one was forked from. Omitted/empty for root (non-fork) sessions.
+ "pause_reason": "str", # Optional. Why this session is paused.
+ Present only when status is SESSION_STATUS_PAUSED; omitted otherwise. Known
+ values: manual (PauseSession RPC), idle (inactivity auto-pause), low_balance
+ (prepay gate). Clients should treat an unrecognized value as an opaque reason
+ string.
+ "repo_hint": "str", # Optional. Optional repository hint supplied at
+ session creation (first spec.workspace.repos entry of the manifest). Not
+ authoritative; the agent may change repos in-session.
+ "resume_on_topoff": bool, # Optional. Session consents to being
+ resumed automatically when the team's prepayment balance is restored after a
+ low-balance pause. Defaults to false at create time; may be toggled later via
+ PATCH /v2/agents/sessions/{session_id} (resume_on_topoff only). Only a
+ session paused with reason low_balance whose latest run did not complete is
+ ever resumed automatically - a session the customer paused themselves, or one
+ that idled out, stays paused regardless. Not an environment-spec field, and
+ forks do not inherit it. Omitted when false.
+ "sandbox_id": "str", # Optional. Sandbox identity for support /
+ debugging. Informational; omitted until a sandbox is allocated.
+ "session_id": "str", # Optional. Session is the user-facing record
+ of a environment session + sandbox pair.
+ "status": "SESSION_STATUS_UNSPECIFIED", # Optional. Default value is
+ "SESSION_STATUS_UNSPECIFIED". SessionStatus is the lifecycle state of the
+ sandbox + agent pair. SESSION_STATUS_ALL is a ListSessions status-filter
+ value only -- no session is ever actually in this status.
+ SESSION_STATUS_LOCKED is reserved for internal use and never appears in an
+ end-user-facing response. Known values are: "SESSION_STATUS_UNSPECIFIED",
+ "SESSION_STATUS_PROVISIONING", "SESSION_STATUS_READY",
+ "SESSION_STATUS_DETACHED", "SESSION_STATUS_DESTROYING",
+ "SESSION_STATUS_DESTROYED", "SESSION_STATUS_FAILED", "SESSION_STATUS_PAUSED",
+ "SESSION_STATUS_ALL", and "SESSION_STATUS_LOCKED".
+ "warnings": [
+ "str" # Optional. Non-fatal advisories computed from the
+ manifest at create time: one entry per populated
+ accepted-but-not-yet-enforced section (flat names: secrets, model, tools,
+ memory, budget, max_lifetime, mounts; legacy manifests get the
+ corresponding spec.* paths), a deprecation entry when a legacy-envelope
+ manifest or an adapter alias (codex-cli, cursor-cli) is used, and a
+ heuristic entry per credential-looking spec.env value. Populated on the
+ CreateSession response only.
+ ]
+ }
+ }
+ # response body for status code(s): 400, 403, 404, 409, 423
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+
+ @distributed_trace_async
+ async def update_session(
+ self, session_id: str, body: Union[JSON, IO[bytes]], **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """PatchSession updates session-scoped settings on an existing session.
+
+ Partial update of session-scoped settings (not the agent manifest / config). The body must
+ include at least one recognized patchable property; an empty object {} is 400. Only properties
+ listed on PatchSessionRequest are accepted — any other top-level JSON key is rejected with 400.
+ Omitted properties are left unchanged. Today the only patchable field is resume_on_topoff; more
+ session settings may be added over time. Terminal sessions (DESTROYED, FAILED) cannot be
+ patched.
+
+ :param session_id: The session UUID. Required.
+ :type session_id: str
+ :param body: PATCH body: allowlisted session-scoped settings. At least one property required.
+ Is either a JSON type or a IO[bytes] type. Required.
+ :type body: JSON or IO[bytes]
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "resume_on_topoff": bool # Optional. When present, sets whether this session
+ opts in to automatic resumption when the team's prepayment balance is restored
+ after a low-balance pause. Session-scoped consent, not config-scoped. Omitted
+ properties are not modified.
+ }
+
+ # response body for status code(s): 200
+ response == {
+ "session": {
+ "agent_kind": "AGENT_KIND_UNSPECIFIED", # Optional. Default value is
+ "AGENT_KIND_UNSPECIFIED". AgentKind identifies what runs inside the session
+ sandbox. CreateSession accepts CLAUDE_CODE, OPENCODE, CODEX_CLI, CURSOR_CLI,
+ OPENAI_CODEX, LANGGRAPH, and CREWAI (the supported set is overridable via
+ HARNESS_SUPPORTED_AGENT_KINDS); other values are rejected with 400.
+ AGENT_KIND_OPENAI_CODEX is the OpenAI sandbox-provider kind (DO runs codex
+ exec-server; the agent loop lives at OpenAI). AGENT_KIND_LANGGRAPH is the
+ LangGraph framework adapter. AGENT_KIND_CREWAI is the CrewAI Crew framework
+ adapter: like LANGGRAPH the template bakes no agent code, so spec.env must
+ supply FRAMEWORK_REPO and FRAMEWORK_REPO_SHA; a Crew kickoff is one-shot and
+ exposes no HITL surface. CREWAI is additionally gated per team and returns
+ 400 for teams it is not enabled for. Known values are:
+ "AGENT_KIND_UNSPECIFIED", "AGENT_KIND_CLAUDE_CODE", "AGENT_KIND_OPENCODE",
+ "AGENT_KIND_CODEX_CLI", "AGENT_KIND_CURSOR_CLI", "AGENT_KIND_NONE",
+ "AGENT_KIND_CUSTOM", "AGENT_KIND_HERMES", "AGENT_KIND_OPENAI_CODEX",
+ "AGENT_KIND_LANGGRAPH", and "AGENT_KIND_CREWAI".
+ "config_id": "str", # Optional. Durable Environment Config UUID the
+ session was created from (inline manifests persist a config too, named after
+ the session). Persisted and returned on create/get/list; absent only for
+ sessions created before config references were stored.
+ "created_at": "2020-02-20 00:00:00", # Optional. Session is the
+ user-facing record of a environment session + sandbox pair.
+ "fork_from_checkpoint_id": "str", # Optional. Lineage: harness-api
+ checkpoint id (cp_:code:``) the child booted from at fork time. Drives
+ OHP inherited-history replay on attach. Omitted/empty for root sessions and
+ legacy forks created before this field was persisted.
+ "fork_id": "str", # Optional. Lineage: branch label assigned when
+ this session was created by ForkSession (or rollback's internal fork).
+ Omitted/empty for root sessions.
+ "idle_timeout_seconds": 0, # Optional. This session's own idle-pause
+ timeout (manifest idle_timeout). Omitted when the session uses the
+ deployment-wide default.
+ "keep_warm": bool, # Optional. Session is exempt from idle
+ auto-pause (manifest keep_warm, or the agent-kind default: hermes sessions
+ keep warm). Pause requests against such a session are rejected with 409.
+ Omitted when false.
+ "last_event_at": "2020-02-20 00:00:00", # Optional. Timestamp of the
+ most recent event in this session's canonical stream. Drives the inactivity
+ policy that destroys idle sessions.
+ "name": "str", # Optional. User-assignable display name, unique per
+ team among non-terminal sessions. Usable in place of session_id by clients
+ (doctl / Console resolve it to the id via the ListSessions ?name= filter; the
+ {session_id} path stays UUID-only). Supplied via the environment-spec
+ metadata.name, or auto-generated
+ ("session-:code:``-:code:``") when omitted.
+ "openai_environment_id": "str", # Optional. OpenAI Agents API
+ environment id (env_"u2026), captured from the resolved CODEX_ENVIRONMENT_ID
+ guest env value. Populated only for AGENT_KIND_OPENAI_CODEX sessions.
+ Non-secret correlation metadata.
+ "openai_session_id": "str", # Optional. OpenAI Agents API session id
+ (sess_"u2026) this DO sandbox hosts. Populated only for
+ AGENT_KIND_OPENAI_CODEX sessions (empty otherwise). Non-secret correlation
+ metadata; a client (doctl agents attach) reads it to bridge to the OpenAI
+ session. See docs/design/openai-sandbox-provider.md.
+ "parent_session_id": "str", # Optional. Lineage: id of the session
+ this one was forked from. Omitted/empty for root (non-fork) sessions.
+ "pause_reason": "str", # Optional. Why this session is paused.
+ Present only when status is SESSION_STATUS_PAUSED; omitted otherwise. Known
+ values: manual (PauseSession RPC), idle (inactivity auto-pause), low_balance
+ (prepay gate). Clients should treat an unrecognized value as an opaque reason
+ string.
+ "repo_hint": "str", # Optional. Optional repository hint supplied at
+ session creation (first spec.workspace.repos entry of the manifest). Not
+ authoritative; the agent may change repos in-session.
+ "resume_on_topoff": bool, # Optional. Session consents to being
+ resumed automatically when the team's prepayment balance is restored after a
+ low-balance pause. Defaults to false at create time; may be toggled later via
+ PATCH /v2/agents/sessions/{session_id} (resume_on_topoff only). Only a
+ session paused with reason low_balance whose latest run did not complete is
+ ever resumed automatically - a session the customer paused themselves, or one
+ that idled out, stays paused regardless. Not an environment-spec field, and
+ forks do not inherit it. Omitted when false.
+ "sandbox_id": "str", # Optional. Sandbox identity for support /
+ debugging. Informational; omitted until a sandbox is allocated.
+ "session_id": "str", # Optional. Session is the user-facing record
+ of a environment session + sandbox pair.
+ "status": "SESSION_STATUS_UNSPECIFIED", # Optional. Default value is
+ "SESSION_STATUS_UNSPECIFIED". SessionStatus is the lifecycle state of the
+ sandbox + agent pair. SESSION_STATUS_ALL is a ListSessions status-filter
+ value only -- no session is ever actually in this status.
+ SESSION_STATUS_LOCKED is reserved for internal use and never appears in an
+ end-user-facing response. Known values are: "SESSION_STATUS_UNSPECIFIED",
+ "SESSION_STATUS_PROVISIONING", "SESSION_STATUS_READY",
+ "SESSION_STATUS_DETACHED", "SESSION_STATUS_DESTROYING",
+ "SESSION_STATUS_DESTROYED", "SESSION_STATUS_FAILED", "SESSION_STATUS_PAUSED",
+ "SESSION_STATUS_ALL", and "SESSION_STATUS_LOCKED".
+ "warnings": [
+ "str" # Optional. Non-fatal advisories computed from the
+ manifest at create time: one entry per populated
+ accepted-but-not-yet-enforced section (flat names: secrets, model, tools,
+ memory, budget, max_lifetime, mounts; legacy manifests get the
+ corresponding spec.* paths), a deprecation entry when a legacy-envelope
+ manifest or an adapter alias (codex-cli, cursor-cli) is used, and a
+ heuristic entry per credential-looking spec.env value. Populated on the
+ CreateSession response only.
+ ]
+ }
+ }
+ # response body for status code(s): 400, 403, 404, 409, 423
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
+ _params = kwargs.pop("params", {}) or {}
+
+ content_type: Optional[str] = kwargs.pop(
+ "content_type", _headers.pop("Content-Type", None)
+ )
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ content_type = content_type or "application/json"
+ _json = None
+ _content = None
+ if isinstance(body, (IOBase, bytes)):
+ _content = body
+ else:
+ _json = body
+
+ _request = build_harness_update_session_request(
+ session_id=session_id,
+ content_type=content_type,
+ json=_json,
+ content=_content,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 400, 403, 404, 409, 423]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ if response.status_code == 200:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 400:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 403:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 409:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 423:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+ @distributed_trace_async
+ async def list_session_checkpoints(
+ self,
+ session_id: str,
+ *,
+ page_size: Optional[int] = None,
+ page_token: Optional[str] = None,
+ **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """ListCheckpoints enumerates a session's checkpoints, newest first.
+
+ Keyset-paginated on an opaque cursor, like ListSessions.
+
+ :param session_id: The session UUID. Required.
+ :type session_id: str
+ :keyword page_size: Page size. Defaults to 50 when omitted or non-positive. Default value is
+ None.
+ :paramtype page_size: int
+ :keyword page_token: Opaque keyset cursor returned by the previous page. Empty starts from the
+ beginning. Default value is None.
+ :paramtype page_token: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 200
+ response == {
+ "checkpoints": [
+ {
+ "checkpoint_id": "str", # Optional. Public checkpoint id,
+ stable for the checkpoint's lifetime (e.g. cp_9f2c1a4b).
+ "created_at": "2020-02-20 00:00:00", # Optional. Newest
+ first.
+ "error_message": "str", # Optional. Client-safe failure
+ detail; set only when status is FAILED.
+ "event_id": "str", # Optional. Event-log cursor (ULID) of
+ the last event included in the cut; forks resume event replay from here.
+ "kind": "str", # Optional. How the checkpoint came to exist:
+ explicit - requested via CreateCheckpoint; implicit - minted
+ automatically by the platform (on run completion, or when ForkSession is
+ called without from_checkpoint_id). Known values are: "explicit" and
+ "implicit".
+ "label": "str", # Optional. Optional user-supplied label
+ from CreateCheckpoint; empty when omitted.
+ "session_id": "str", # Optional. Owning session.
+ "size_bytes": 0, # Optional. Size of the captured machine
+ state. 0 until the checkpoint reaches READY.
+ "status": "str" # Optional. Capture lifecycle: PENDING ->
+ READY | FAILED. Only READY checkpoints are forkable/restorable.
+ CreateCheckpoint blocks until terminal, so PENDING is only ever
+ observable via list/get while a capture is in flight. Known values are:
+ "PENDING", "READY", and "FAILED".
+ }
+ ],
+ "next_page_token": "str" # Optional. Opaque cursor for the next page. Empty
+ when there are no further pages.
+ }
+ # response body for status code(s): 400, 403, 404, 423
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = kwargs.pop("headers", {}) or {}
+ _params = kwargs.pop("params", {}) or {}
+
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ _request = build_harness_list_session_checkpoints_request(
+ session_id=session_id,
+ page_size=page_size,
+ page_token=page_token,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 400, 403, 404, 423]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ if response.status_code == 200:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 400:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 403:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 423:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+ @overload
+ async def create_session_checkpoint(
+ self,
+ session_id: str,
+ body: Optional[JSON] = None,
+ *,
+ content_type: str = "application/json",
+ **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """CreateCheckpoint captures the session's live sandbox state as a durable checkpoint.
+
+ Synchronous: blocks until the capture reaches READY and returns the terminal Checkpoint —
+ clients never see PENDING on this endpoint and need no poll loop. The checkpoint binds the
+ machine-state capture to the event-log cursor at the cut, so it can later seed forks (POST
+ .../fork) and rollback. Checkpoints are taken between turns; a session with an active turn in
+ flight returns 409.
+
+ :param session_id: The session UUID. Required.
+ :type session_id: str
+ :param body: Optional; an empty or omitted body creates an unlabeled checkpoint. Default value
+ is None.
+ :type body: JSON
+ :keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
+ Default value is "application/json".
+ :paramtype content_type: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "label": "str" # Optional. Optional human-readable label stored on the
+ checkpoint; "" if omitted.
+ }
+
+ # response body for status code(s): 200
+ response == {
+ "checkpoint": {
+ "checkpoint_id": "str", # Optional. Public checkpoint id, stable for
+ the checkpoint's lifetime (e.g. cp_9f2c1a4b).
+ "created_at": "2020-02-20 00:00:00", # Optional. Checkpoint is a
+ durable capture of a session's live sandbox machine state bound to the
+ event-log cursor at the cut. READY checkpoints seed forks (ForkSession) and
+ rollback. Internal fields (team_id, the substrate checkpoint id, event_seq)
+ are never serialized.
+ "error_message": "str", # Optional. Client-safe failure detail; set
+ only when status is FAILED.
+ "event_id": "str", # Optional. Event-log cursor (ULID) of the last
+ event included in the cut; forks resume event replay from here.
+ "kind": "str", # Optional. How the checkpoint came to exist:
+ explicit - requested via CreateCheckpoint; implicit - minted automatically by
+ the platform (on run completion, or when ForkSession is called without
+ from_checkpoint_id). Known values are: "explicit" and "implicit".
+ "label": "str", # Optional. Optional user-supplied label from
+ CreateCheckpoint; empty when omitted.
+ "session_id": "str", # Optional. Owning session.
+ "size_bytes": 0, # Optional. Size of the captured machine state. 0
+ until the checkpoint reaches READY.
+ "status": "str" # Optional. Capture lifecycle: PENDING -> READY |
+ FAILED. Only READY checkpoints are forkable/restorable. CreateCheckpoint
+ blocks until terminal, so PENDING is only ever observable via list/get while
+ a capture is in flight. Known values are: "PENDING", "READY", and "FAILED".
+ }
+ }
+ # response body for status code(s): 402, 403, 404, 409, 423, 501
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+
+ @overload
+ async def create_session_checkpoint(
+ self,
+ session_id: str,
+ body: Optional[IO[bytes]] = None,
+ *,
+ content_type: str = "application/json",
+ **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """CreateCheckpoint captures the session's live sandbox state as a durable checkpoint.
+
+ Synchronous: blocks until the capture reaches READY and returns the terminal Checkpoint —
+ clients never see PENDING on this endpoint and need no poll loop. The checkpoint binds the
+ machine-state capture to the event-log cursor at the cut, so it can later seed forks (POST
+ .../fork) and rollback. Checkpoints are taken between turns; a session with an active turn in
+ flight returns 409.
+
+ :param session_id: The session UUID. Required.
+ :type session_id: str
+ :param body: Optional; an empty or omitted body creates an unlabeled checkpoint. Default value
+ is None.
+ :type body: IO[bytes]
+ :keyword content_type: Body Parameter content-type. Content type parameter for binary body.
+ Default value is "application/json".
+ :paramtype content_type: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 200
+ response == {
+ "checkpoint": {
+ "checkpoint_id": "str", # Optional. Public checkpoint id, stable for
+ the checkpoint's lifetime (e.g. cp_9f2c1a4b).
+ "created_at": "2020-02-20 00:00:00", # Optional. Checkpoint is a
+ durable capture of a session's live sandbox machine state bound to the
+ event-log cursor at the cut. READY checkpoints seed forks (ForkSession) and
+ rollback. Internal fields (team_id, the substrate checkpoint id, event_seq)
+ are never serialized.
+ "error_message": "str", # Optional. Client-safe failure detail; set
+ only when status is FAILED.
+ "event_id": "str", # Optional. Event-log cursor (ULID) of the last
+ event included in the cut; forks resume event replay from here.
+ "kind": "str", # Optional. How the checkpoint came to exist:
+ explicit - requested via CreateCheckpoint; implicit - minted automatically by
+ the platform (on run completion, or when ForkSession is called without
+ from_checkpoint_id). Known values are: "explicit" and "implicit".
+ "label": "str", # Optional. Optional user-supplied label from
+ CreateCheckpoint; empty when omitted.
+ "session_id": "str", # Optional. Owning session.
+ "size_bytes": 0, # Optional. Size of the captured machine state. 0
+ until the checkpoint reaches READY.
+ "status": "str" # Optional. Capture lifecycle: PENDING -> READY |
+ FAILED. Only READY checkpoints are forkable/restorable. CreateCheckpoint
+ blocks until terminal, so PENDING is only ever observable via list/get while
+ a capture is in flight. Known values are: "PENDING", "READY", and "FAILED".
+ }
+ }
+ # response body for status code(s): 402, 403, 404, 409, 423, 501
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+
+ @distributed_trace_async
+ async def create_session_checkpoint(
+ self,
+ session_id: str,
+ body: Optional[Union[JSON, IO[bytes]]] = None,
+ **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """CreateCheckpoint captures the session's live sandbox state as a durable checkpoint.
+
+ Synchronous: blocks until the capture reaches READY and returns the terminal Checkpoint —
+ clients never see PENDING on this endpoint and need no poll loop. The checkpoint binds the
+ machine-state capture to the event-log cursor at the cut, so it can later seed forks (POST
+ .../fork) and rollback. Checkpoints are taken between turns; a session with an active turn in
+ flight returns 409.
+
+ :param session_id: The session UUID. Required.
+ :type session_id: str
+ :param body: Optional; an empty or omitted body creates an unlabeled checkpoint. Is either a
+ JSON type or a IO[bytes] type. Default value is None.
+ :type body: JSON or IO[bytes]
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "label": "str" # Optional. Optional human-readable label stored on the
+ checkpoint; "" if omitted.
+ }
+
+ # response body for status code(s): 200
+ response == {
+ "checkpoint": {
+ "checkpoint_id": "str", # Optional. Public checkpoint id, stable for
+ the checkpoint's lifetime (e.g. cp_9f2c1a4b).
+ "created_at": "2020-02-20 00:00:00", # Optional. Checkpoint is a
+ durable capture of a session's live sandbox machine state bound to the
+ event-log cursor at the cut. READY checkpoints seed forks (ForkSession) and
+ rollback. Internal fields (team_id, the substrate checkpoint id, event_seq)
+ are never serialized.
+ "error_message": "str", # Optional. Client-safe failure detail; set
+ only when status is FAILED.
+ "event_id": "str", # Optional. Event-log cursor (ULID) of the last
+ event included in the cut; forks resume event replay from here.
+ "kind": "str", # Optional. How the checkpoint came to exist:
+ explicit - requested via CreateCheckpoint; implicit - minted automatically by
+ the platform (on run completion, or when ForkSession is called without
+ from_checkpoint_id). Known values are: "explicit" and "implicit".
+ "label": "str", # Optional. Optional user-supplied label from
+ CreateCheckpoint; empty when omitted.
+ "session_id": "str", # Optional. Owning session.
+ "size_bytes": 0, # Optional. Size of the captured machine state. 0
+ until the checkpoint reaches READY.
+ "status": "str" # Optional. Capture lifecycle: PENDING -> READY |
+ FAILED. Only READY checkpoints are forkable/restorable. CreateCheckpoint
+ blocks until terminal, so PENDING is only ever observable via list/get while
+ a capture is in flight. Known values are: "PENDING", "READY", and "FAILED".
+ }
+ }
+ # response body for status code(s): 402, 403, 404, 409, 423, 501
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
+ _params = kwargs.pop("params", {}) or {}
+
+ content_type: Optional[str] = kwargs.pop(
+ "content_type", _headers.pop("Content-Type", None)
+ )
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ content_type = content_type or "application/json"
+ _json = None
+ _content = None
+ if isinstance(body, (IOBase, bytes)):
+ _content = body
+ else:
+ if body is not None:
+ _json = body
+ else:
+ _json = None
+
+ _request = build_harness_create_session_checkpoint_request(
+ session_id=session_id,
+ content_type=content_type,
+ json=_json,
+ content=_content,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 402, 403, 404, 409, 423, 501]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ if response.status_code == 200:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 402:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 403:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 409:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 423:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 501:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+ @distributed_trace_async
+ async def get_session_checkpoint(
+ self, session_id: str, checkpoint_id: str, **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """GetCheckpoint returns the current snapshot of a checkpoint.
+
+ GetCheckpoint returns the current snapshot of a checkpoint.
+
+ :param session_id: The session UUID. Required.
+ :type session_id: str
+ :param checkpoint_id: The checkpoint id. Required.
+ :type checkpoint_id: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 200
+ response == {
+ "checkpoint": {
+ "checkpoint_id": "str", # Optional. Public checkpoint id, stable for
+ the checkpoint's lifetime (e.g. cp_9f2c1a4b).
+ "created_at": "2020-02-20 00:00:00", # Optional. Checkpoint is a
+ durable capture of a session's live sandbox machine state bound to the
+ event-log cursor at the cut. READY checkpoints seed forks (ForkSession) and
+ rollback. Internal fields (team_id, the substrate checkpoint id, event_seq)
+ are never serialized.
+ "error_message": "str", # Optional. Client-safe failure detail; set
+ only when status is FAILED.
+ "event_id": "str", # Optional. Event-log cursor (ULID) of the last
+ event included in the cut; forks resume event replay from here.
+ "kind": "str", # Optional. How the checkpoint came to exist:
+ explicit - requested via CreateCheckpoint; implicit - minted automatically by
+ the platform (on run completion, or when ForkSession is called without
+ from_checkpoint_id). Known values are: "explicit" and "implicit".
+ "label": "str", # Optional. Optional user-supplied label from
+ CreateCheckpoint; empty when omitted.
+ "session_id": "str", # Optional. Owning session.
+ "size_bytes": 0, # Optional. Size of the captured machine state. 0
+ until the checkpoint reaches READY.
+ "status": "str" # Optional. Capture lifecycle: PENDING -> READY |
+ FAILED. Only READY checkpoints are forkable/restorable. CreateCheckpoint
+ blocks until terminal, so PENDING is only ever observable via list/get while
+ a capture is in flight. Known values are: "PENDING", "READY", and "FAILED".
+ }
+ }
+ # response body for status code(s): 403, 404, 423
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = kwargs.pop("headers", {}) or {}
+ _params = kwargs.pop("params", {}) or {}
+
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ _request = build_harness_get_session_checkpoint_request(
+ session_id=session_id,
+ checkpoint_id=checkpoint_id,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 403, 404, 423]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ if response.status_code == 200:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 403:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 423:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+ @distributed_trace_async
+ async def delete_session_checkpoint(
+ self, session_id: str, checkpoint_id: str, **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """DeleteCheckpoint removes a checkpoint and its underlying machine-state capture.
+
+ Idempotent: deleting an already-gone checkpoint still returns 200. Removes the DB row and the
+ substrate checkpoint.
+
+ :param session_id: The session UUID. Required.
+ :type session_id: str
+ :param checkpoint_id: The checkpoint id. Required.
+ :type checkpoint_id: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 200
+ response == {
+ "checkpoint_id": "str", # Optional. Echo of the requested checkpoint id.
+ "deleted": bool # Optional. Always true on 200 (delete is idempotent).
+ }
+ # response body for status code(s): 403, 404, 423
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = kwargs.pop("headers", {}) or {}
+ _params = kwargs.pop("params", {}) or {}
+
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ _request = build_harness_delete_session_checkpoint_request(
+ session_id=session_id,
+ checkpoint_id=checkpoint_id,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 403, 404, 423]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ if response.status_code == 200:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 403:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 423:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+ @distributed_trace_async
+ async def revert_session_checkpoint(
+ self, session_id: str, checkpoint_id: str, **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """RollbackToCheckpoint rewinds a session to a checkpoint.
+
+ In-place restore: boots a fresh sandbox from the checkpoint and atomically swaps the session's
+ sandbox pointer to it, so the session keeps its same session_id; the old sandbox is then torn
+ down.
+
+ :param session_id: The session UUID. Required.
+ :type session_id: str
+ :param checkpoint_id: The checkpoint id. Required.
+ :type checkpoint_id: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 200
+ response == {
+ "session": {
+ "agent_kind": "AGENT_KIND_UNSPECIFIED", # Optional. Default value is
+ "AGENT_KIND_UNSPECIFIED". AgentKind identifies what runs inside the session
+ sandbox. CreateSession accepts CLAUDE_CODE, OPENCODE, CODEX_CLI, CURSOR_CLI,
+ OPENAI_CODEX, LANGGRAPH, and CREWAI (the supported set is overridable via
+ HARNESS_SUPPORTED_AGENT_KINDS); other values are rejected with 400.
+ AGENT_KIND_OPENAI_CODEX is the OpenAI sandbox-provider kind (DO runs codex
+ exec-server; the agent loop lives at OpenAI). AGENT_KIND_LANGGRAPH is the
+ LangGraph framework adapter. AGENT_KIND_CREWAI is the CrewAI Crew framework
+ adapter: like LANGGRAPH the template bakes no agent code, so spec.env must
+ supply FRAMEWORK_REPO and FRAMEWORK_REPO_SHA; a Crew kickoff is one-shot and
+ exposes no HITL surface. CREWAI is additionally gated per team and returns
+ 400 for teams it is not enabled for. Known values are:
+ "AGENT_KIND_UNSPECIFIED", "AGENT_KIND_CLAUDE_CODE", "AGENT_KIND_OPENCODE",
+ "AGENT_KIND_CODEX_CLI", "AGENT_KIND_CURSOR_CLI", "AGENT_KIND_NONE",
+ "AGENT_KIND_CUSTOM", "AGENT_KIND_HERMES", "AGENT_KIND_OPENAI_CODEX",
+ "AGENT_KIND_LANGGRAPH", and "AGENT_KIND_CREWAI".
+ "config_id": "str", # Optional. Durable Environment Config UUID the
+ session was created from (inline manifests persist a config too, named after
+ the session). Persisted and returned on create/get/list; absent only for
+ sessions created before config references were stored.
+ "created_at": "2020-02-20 00:00:00", # Optional. Session is the
+ user-facing record of a environment session + sandbox pair.
+ "fork_from_checkpoint_id": "str", # Optional. Lineage: harness-api
+ checkpoint id (cp_:code:``) the child booted from at fork time. Drives
+ OHP inherited-history replay on attach. Omitted/empty for root sessions and
+ legacy forks created before this field was persisted.
+ "fork_id": "str", # Optional. Lineage: branch label assigned when
+ this session was created by ForkSession (or rollback's internal fork).
+ Omitted/empty for root sessions.
+ "idle_timeout_seconds": 0, # Optional. This session's own idle-pause
+ timeout (manifest idle_timeout). Omitted when the session uses the
+ deployment-wide default.
+ "keep_warm": bool, # Optional. Session is exempt from idle
+ auto-pause (manifest keep_warm, or the agent-kind default: hermes sessions
+ keep warm). Pause requests against such a session are rejected with 409.
+ Omitted when false.
+ "last_event_at": "2020-02-20 00:00:00", # Optional. Timestamp of the
+ most recent event in this session's canonical stream. Drives the inactivity
+ policy that destroys idle sessions.
+ "name": "str", # Optional. User-assignable display name, unique per
+ team among non-terminal sessions. Usable in place of session_id by clients
+ (doctl / Console resolve it to the id via the ListSessions ?name= filter; the
+ {session_id} path stays UUID-only). Supplied via the environment-spec
+ metadata.name, or auto-generated
+ ("session-:code:``-:code:``") when omitted.
+ "openai_environment_id": "str", # Optional. OpenAI Agents API
+ environment id (env_"u2026), captured from the resolved CODEX_ENVIRONMENT_ID
+ guest env value. Populated only for AGENT_KIND_OPENAI_CODEX sessions.
+ Non-secret correlation metadata.
+ "openai_session_id": "str", # Optional. OpenAI Agents API session id
+ (sess_"u2026) this DO sandbox hosts. Populated only for
+ AGENT_KIND_OPENAI_CODEX sessions (empty otherwise). Non-secret correlation
+ metadata; a client (doctl agents attach) reads it to bridge to the OpenAI
+ session. See docs/design/openai-sandbox-provider.md.
+ "parent_session_id": "str", # Optional. Lineage: id of the session
+ this one was forked from. Omitted/empty for root (non-fork) sessions.
+ "pause_reason": "str", # Optional. Why this session is paused.
+ Present only when status is SESSION_STATUS_PAUSED; omitted otherwise. Known
+ values: manual (PauseSession RPC), idle (inactivity auto-pause), low_balance
+ (prepay gate). Clients should treat an unrecognized value as an opaque reason
+ string.
+ "repo_hint": "str", # Optional. Optional repository hint supplied at
+ session creation (first spec.workspace.repos entry of the manifest). Not
+ authoritative; the agent may change repos in-session.
+ "resume_on_topoff": bool, # Optional. Session consents to being
+ resumed automatically when the team's prepayment balance is restored after a
+ low-balance pause. Defaults to false at create time; may be toggled later via
+ PATCH /v2/agents/sessions/{session_id} (resume_on_topoff only). Only a
+ session paused with reason low_balance whose latest run did not complete is
+ ever resumed automatically - a session the customer paused themselves, or one
+ that idled out, stays paused regardless. Not an environment-spec field, and
+ forks do not inherit it. Omitted when false.
+ "sandbox_id": "str", # Optional. Sandbox identity for support /
+ debugging. Informational; omitted until a sandbox is allocated.
+ "session_id": "str", # Optional. Session is the user-facing record
+ of a environment session + sandbox pair.
+ "status": "SESSION_STATUS_UNSPECIFIED", # Optional. Default value is
+ "SESSION_STATUS_UNSPECIFIED". SessionStatus is the lifecycle state of the
+ sandbox + agent pair. SESSION_STATUS_ALL is a ListSessions status-filter
+ value only -- no session is ever actually in this status.
+ SESSION_STATUS_LOCKED is reserved for internal use and never appears in an
+ end-user-facing response. Known values are: "SESSION_STATUS_UNSPECIFIED",
+ "SESSION_STATUS_PROVISIONING", "SESSION_STATUS_READY",
+ "SESSION_STATUS_DETACHED", "SESSION_STATUS_DESTROYING",
+ "SESSION_STATUS_DESTROYED", "SESSION_STATUS_FAILED", "SESSION_STATUS_PAUSED",
+ "SESSION_STATUS_ALL", and "SESSION_STATUS_LOCKED".
+ "warnings": [
+ "str" # Optional. Non-fatal advisories computed from the
+ manifest at create time: one entry per populated
+ accepted-but-not-yet-enforced section (flat names: secrets, model, tools,
+ memory, budget, max_lifetime, mounts; legacy manifests get the
+ corresponding spec.* paths), a deprecation entry when a legacy-envelope
+ manifest or an adapter alias (codex-cli, cursor-cli) is used, and a
+ heuristic entry per credential-looking spec.env value. Populated on the
+ CreateSession response only.
+ ]
+ }
+ }
+ # response body for status code(s): 402, 403, 404, 409, 423, 501
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = kwargs.pop("headers", {}) or {}
+ _params = kwargs.pop("params", {}) or {}
+
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ _request = build_harness_revert_session_checkpoint_request(
+ session_id=session_id,
+ checkpoint_id=checkpoint_id,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 402, 403, 404, 409, 423, 501]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ if response.status_code == 200:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 402:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 403:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 409:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 423:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 501:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+ @overload
+ async def create_session_fork(
+ self,
+ session_id: str,
+ body: Optional[JSON] = None,
+ *,
+ content_type: str = "application/json",
+ **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """ForkSession creates child sessions from a checkpoint of this session.
+
+ Each child boots a fresh sandbox from the checkpoint's machine-state capture and is drivable
+ exactly like any other session (input, HITL), with parent_session_id and fork_id set for
+ lineage. When from_checkpoint_id is omitted, an implicit checkpoint of the session "now" is
+ captured first and the children fork from that. All-or-nothing: on failure nothing is left
+ running.
+
+ :param session_id: The session UUID. Required.
+ :type session_id: str
+ :param body: Optional; an empty or omitted body forks a single child from an implicit
+ checkpoint of "now". Default value is None.
+ :type body: JSON
+ :keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
+ Default value is "application/json".
+ :paramtype content_type: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "count": 1, # Optional. Default value is 1. Number of child sessions to
+ create, 1-4. Defaults to 1 when omitted; a value outside 1-4 is rejected with
+ 400.
+ "from_checkpoint_id": "str" # Optional. Checkpoint to fork from; must be
+ READY. Omitted/empty means capture an implicit checkpoint of the session "now"
+ first and fork from that.
+ }
+
+ # response body for status code(s): 200
+ response == {
+ "sessions": [
+ {
+ "agent_kind": "AGENT_KIND_UNSPECIFIED", # Optional. Default
+ value is "AGENT_KIND_UNSPECIFIED". AgentKind identifies what runs inside
+ the session sandbox. CreateSession accepts CLAUDE_CODE, OPENCODE,
+ CODEX_CLI, CURSOR_CLI, OPENAI_CODEX, LANGGRAPH, and CREWAI (the supported
+ set is overridable via HARNESS_SUPPORTED_AGENT_KINDS); other values are
+ rejected with 400. AGENT_KIND_OPENAI_CODEX is the OpenAI sandbox-provider
+ kind (DO runs codex exec-server; the agent loop lives at OpenAI).
+ AGENT_KIND_LANGGRAPH is the LangGraph framework adapter.
+ AGENT_KIND_CREWAI is the CrewAI Crew framework adapter: like LANGGRAPH
+ the template bakes no agent code, so spec.env must supply FRAMEWORK_REPO
+ and FRAMEWORK_REPO_SHA; a Crew kickoff is one-shot and exposes no HITL
+ surface. CREWAI is additionally gated per team and returns 400 for teams
+ it is not enabled for. Known values are: "AGENT_KIND_UNSPECIFIED",
+ "AGENT_KIND_CLAUDE_CODE", "AGENT_KIND_OPENCODE", "AGENT_KIND_CODEX_CLI",
+ "AGENT_KIND_CURSOR_CLI", "AGENT_KIND_NONE", "AGENT_KIND_CUSTOM",
+ "AGENT_KIND_HERMES", "AGENT_KIND_OPENAI_CODEX", "AGENT_KIND_LANGGRAPH",
+ and "AGENT_KIND_CREWAI".
+ "config_id": "str", # Optional. Durable Environment Config
+ UUID the session was created from (inline manifests persist a config too,
+ named after the session). Persisted and returned on create/get/list;
+ absent only for sessions created before config references were stored.
+ "created_at": "2020-02-20 00:00:00", # Optional. The created
+ child sessions, each a full Session with parent_session_id and fork_id
+ set (PROVISIONING -> READY) and drivable exactly like any other session.
+ "fork_from_checkpoint_id": "str", # Optional. Lineage:
+ harness-api checkpoint id (cp_:code:``) the child booted from at
+ fork time. Drives OHP inherited-history replay on attach. Omitted/empty
+ for root sessions and legacy forks created before this field was
+ persisted.
+ "fork_id": "str", # Optional. Lineage: branch label assigned
+ when this session was created by ForkSession (or rollback's internal
+ fork). Omitted/empty for root sessions.
+ "idle_timeout_seconds": 0, # Optional. This session's own
+ idle-pause timeout (manifest idle_timeout). Omitted when the session uses
+ the deployment-wide default.
+ "keep_warm": bool, # Optional. Session is exempt from idle
+ auto-pause (manifest keep_warm, or the agent-kind default: hermes
+ sessions keep warm). Pause requests against such a session are rejected
+ with 409. Omitted when false.
+ "last_event_at": "2020-02-20 00:00:00", # Optional.
+ Timestamp of the most recent event in this session's canonical stream.
+ Drives the inactivity policy that destroys idle sessions.
+ "name": "str", # Optional. User-assignable display name,
+ unique per team among non-terminal sessions. Usable in place of
+ session_id by clients (doctl / Console resolve it to the id via the
+ ListSessions ?name= filter; the {session_id} path stays UUID-only).
+ Supplied via the environment-spec metadata.name, or auto-generated
+ ("session-:code:``-:code:``") when omitted.
+ "openai_environment_id": "str", # Optional. OpenAI Agents
+ API environment id (env_"u2026), captured from the resolved
+ CODEX_ENVIRONMENT_ID guest env value. Populated only for
+ AGENT_KIND_OPENAI_CODEX sessions. Non-secret correlation metadata.
+ "openai_session_id": "str", # Optional. OpenAI Agents API
+ session id (sess_"u2026) this DO sandbox hosts. Populated only for
+ AGENT_KIND_OPENAI_CODEX sessions (empty otherwise). Non-secret
+ correlation metadata; a client (doctl agents attach) reads it to bridge
+ to the OpenAI session. See docs/design/openai-sandbox-provider.md.
+ "parent_session_id": "str", # Optional. Lineage: id of the
+ session this one was forked from. Omitted/empty for root (non-fork)
+ sessions.
+ "pause_reason": "str", # Optional. Why this session is
+ paused. Present only when status is SESSION_STATUS_PAUSED; omitted
+ otherwise. Known values: manual (PauseSession RPC), idle (inactivity
+ auto-pause), low_balance (prepay gate). Clients should treat an
+ unrecognized value as an opaque reason string.
+ "repo_hint": "str", # Optional. Optional repository hint
+ supplied at session creation (first spec.workspace.repos entry of the
+ manifest). Not authoritative; the agent may change repos in-session.
+ "resume_on_topoff": bool, # Optional. Session consents to
+ being resumed automatically when the team's prepayment balance is
+ restored after a low-balance pause. Defaults to false at create time; may
+ be toggled later via PATCH /v2/agents/sessions/{session_id}
+ (resume_on_topoff only). Only a session paused with reason low_balance
+ whose latest run did not complete is ever resumed automatically - a
+ session the customer paused themselves, or one that idled out, stays
+ paused regardless. Not an environment-spec field, and forks do not
+ inherit it. Omitted when false.
+ "sandbox_id": "str", # Optional. Sandbox identity for
+ support / debugging. Informational; omitted until a sandbox is allocated.
+ "session_id": "str", # Optional. The created child sessions,
+ each a full Session with parent_session_id and fork_id set (PROVISIONING
+ -> READY) and drivable exactly like any other session.
+ "status": "SESSION_STATUS_UNSPECIFIED", # Optional. Default
+ value is "SESSION_STATUS_UNSPECIFIED". SessionStatus is the lifecycle
+ state of the sandbox + agent pair. SESSION_STATUS_ALL is a ListSessions
+ status-filter value only -- no session is ever actually in this status.
+ SESSION_STATUS_LOCKED is reserved for internal use and never appears in
+ an end-user-facing response. Known values are:
+ "SESSION_STATUS_UNSPECIFIED", "SESSION_STATUS_PROVISIONING",
+ "SESSION_STATUS_READY", "SESSION_STATUS_DETACHED",
+ "SESSION_STATUS_DESTROYING", "SESSION_STATUS_DESTROYED",
+ "SESSION_STATUS_FAILED", "SESSION_STATUS_PAUSED", "SESSION_STATUS_ALL",
+ and "SESSION_STATUS_LOCKED".
+ "warnings": [
+ "str" # Optional. Non-fatal advisories computed from
+ the manifest at create time: one entry per populated
+ accepted-but-not-yet-enforced section (flat names: secrets, model,
+ tools, memory, budget, max_lifetime, mounts; legacy manifests get the
+ corresponding spec.* paths), a deprecation entry when a
+ legacy-envelope manifest or an adapter alias (codex-cli, cursor-cli)
+ is used, and a heuristic entry per credential-looking spec.env value.
+ Populated on the CreateSession response only.
+ ]
+ }
+ ]
+ }
+ # response body for status code(s): 402, 403, 404, 409, 423, 501
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+
+ @overload
+ async def create_session_fork(
+ self,
+ session_id: str,
+ body: Optional[IO[bytes]] = None,
+ *,
+ content_type: str = "application/json",
+ **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """ForkSession creates child sessions from a checkpoint of this session.
+
+ Each child boots a fresh sandbox from the checkpoint's machine-state capture and is drivable
+ exactly like any other session (input, HITL), with parent_session_id and fork_id set for
+ lineage. When from_checkpoint_id is omitted, an implicit checkpoint of the session "now" is
+ captured first and the children fork from that. All-or-nothing: on failure nothing is left
+ running.
+
+ :param session_id: The session UUID. Required.
+ :type session_id: str
+ :param body: Optional; an empty or omitted body forks a single child from an implicit
+ checkpoint of "now". Default value is None.
+ :type body: IO[bytes]
+ :keyword content_type: Body Parameter content-type. Content type parameter for binary body.
+ Default value is "application/json".
+ :paramtype content_type: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 200
+ response == {
+ "sessions": [
+ {
+ "agent_kind": "AGENT_KIND_UNSPECIFIED", # Optional. Default
+ value is "AGENT_KIND_UNSPECIFIED". AgentKind identifies what runs inside
+ the session sandbox. CreateSession accepts CLAUDE_CODE, OPENCODE,
+ CODEX_CLI, CURSOR_CLI, OPENAI_CODEX, LANGGRAPH, and CREWAI (the supported
+ set is overridable via HARNESS_SUPPORTED_AGENT_KINDS); other values are
+ rejected with 400. AGENT_KIND_OPENAI_CODEX is the OpenAI sandbox-provider
+ kind (DO runs codex exec-server; the agent loop lives at OpenAI).
+ AGENT_KIND_LANGGRAPH is the LangGraph framework adapter.
+ AGENT_KIND_CREWAI is the CrewAI Crew framework adapter: like LANGGRAPH
+ the template bakes no agent code, so spec.env must supply FRAMEWORK_REPO
+ and FRAMEWORK_REPO_SHA; a Crew kickoff is one-shot and exposes no HITL
+ surface. CREWAI is additionally gated per team and returns 400 for teams
+ it is not enabled for. Known values are: "AGENT_KIND_UNSPECIFIED",
+ "AGENT_KIND_CLAUDE_CODE", "AGENT_KIND_OPENCODE", "AGENT_KIND_CODEX_CLI",
+ "AGENT_KIND_CURSOR_CLI", "AGENT_KIND_NONE", "AGENT_KIND_CUSTOM",
+ "AGENT_KIND_HERMES", "AGENT_KIND_OPENAI_CODEX", "AGENT_KIND_LANGGRAPH",
+ and "AGENT_KIND_CREWAI".
+ "config_id": "str", # Optional. Durable Environment Config
+ UUID the session was created from (inline manifests persist a config too,
+ named after the session). Persisted and returned on create/get/list;
+ absent only for sessions created before config references were stored.
+ "created_at": "2020-02-20 00:00:00", # Optional. The created
+ child sessions, each a full Session with parent_session_id and fork_id
+ set (PROVISIONING -> READY) and drivable exactly like any other session.
+ "fork_from_checkpoint_id": "str", # Optional. Lineage:
+ harness-api checkpoint id (cp_:code:``) the child booted from at
+ fork time. Drives OHP inherited-history replay on attach. Omitted/empty
+ for root sessions and legacy forks created before this field was
+ persisted.
+ "fork_id": "str", # Optional. Lineage: branch label assigned
+ when this session was created by ForkSession (or rollback's internal
+ fork). Omitted/empty for root sessions.
+ "idle_timeout_seconds": 0, # Optional. This session's own
+ idle-pause timeout (manifest idle_timeout). Omitted when the session uses
+ the deployment-wide default.
+ "keep_warm": bool, # Optional. Session is exempt from idle
+ auto-pause (manifest keep_warm, or the agent-kind default: hermes
+ sessions keep warm). Pause requests against such a session are rejected
+ with 409. Omitted when false.
+ "last_event_at": "2020-02-20 00:00:00", # Optional.
+ Timestamp of the most recent event in this session's canonical stream.
+ Drives the inactivity policy that destroys idle sessions.
+ "name": "str", # Optional. User-assignable display name,
+ unique per team among non-terminal sessions. Usable in place of
+ session_id by clients (doctl / Console resolve it to the id via the
+ ListSessions ?name= filter; the {session_id} path stays UUID-only).
+ Supplied via the environment-spec metadata.name, or auto-generated
+ ("session-:code:``-:code:``") when omitted.
+ "openai_environment_id": "str", # Optional. OpenAI Agents
+ API environment id (env_"u2026), captured from the resolved
+ CODEX_ENVIRONMENT_ID guest env value. Populated only for
+ AGENT_KIND_OPENAI_CODEX sessions. Non-secret correlation metadata.
+ "openai_session_id": "str", # Optional. OpenAI Agents API
+ session id (sess_"u2026) this DO sandbox hosts. Populated only for
+ AGENT_KIND_OPENAI_CODEX sessions (empty otherwise). Non-secret
+ correlation metadata; a client (doctl agents attach) reads it to bridge
+ to the OpenAI session. See docs/design/openai-sandbox-provider.md.
+ "parent_session_id": "str", # Optional. Lineage: id of the
+ session this one was forked from. Omitted/empty for root (non-fork)
+ sessions.
+ "pause_reason": "str", # Optional. Why this session is
+ paused. Present only when status is SESSION_STATUS_PAUSED; omitted
+ otherwise. Known values: manual (PauseSession RPC), idle (inactivity
+ auto-pause), low_balance (prepay gate). Clients should treat an
+ unrecognized value as an opaque reason string.
+ "repo_hint": "str", # Optional. Optional repository hint
+ supplied at session creation (first spec.workspace.repos entry of the
+ manifest). Not authoritative; the agent may change repos in-session.
+ "resume_on_topoff": bool, # Optional. Session consents to
+ being resumed automatically when the team's prepayment balance is
+ restored after a low-balance pause. Defaults to false at create time; may
+ be toggled later via PATCH /v2/agents/sessions/{session_id}
+ (resume_on_topoff only). Only a session paused with reason low_balance
+ whose latest run did not complete is ever resumed automatically - a
+ session the customer paused themselves, or one that idled out, stays
+ paused regardless. Not an environment-spec field, and forks do not
+ inherit it. Omitted when false.
+ "sandbox_id": "str", # Optional. Sandbox identity for
+ support / debugging. Informational; omitted until a sandbox is allocated.
+ "session_id": "str", # Optional. The created child sessions,
+ each a full Session with parent_session_id and fork_id set (PROVISIONING
+ -> READY) and drivable exactly like any other session.
+ "status": "SESSION_STATUS_UNSPECIFIED", # Optional. Default
+ value is "SESSION_STATUS_UNSPECIFIED". SessionStatus is the lifecycle
+ state of the sandbox + agent pair. SESSION_STATUS_ALL is a ListSessions
+ status-filter value only -- no session is ever actually in this status.
+ SESSION_STATUS_LOCKED is reserved for internal use and never appears in
+ an end-user-facing response. Known values are:
+ "SESSION_STATUS_UNSPECIFIED", "SESSION_STATUS_PROVISIONING",
+ "SESSION_STATUS_READY", "SESSION_STATUS_DETACHED",
+ "SESSION_STATUS_DESTROYING", "SESSION_STATUS_DESTROYED",
+ "SESSION_STATUS_FAILED", "SESSION_STATUS_PAUSED", "SESSION_STATUS_ALL",
+ and "SESSION_STATUS_LOCKED".
+ "warnings": [
+ "str" # Optional. Non-fatal advisories computed from
+ the manifest at create time: one entry per populated
+ accepted-but-not-yet-enforced section (flat names: secrets, model,
+ tools, memory, budget, max_lifetime, mounts; legacy manifests get the
+ corresponding spec.* paths), a deprecation entry when a
+ legacy-envelope manifest or an adapter alias (codex-cli, cursor-cli)
+ is used, and a heuristic entry per credential-looking spec.env value.
+ Populated on the CreateSession response only.
+ ]
+ }
+ ]
+ }
+ # response body for status code(s): 402, 403, 404, 409, 423, 501
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+
+ @distributed_trace_async
+ async def create_session_fork(
+ self,
+ session_id: str,
+ body: Optional[Union[JSON, IO[bytes]]] = None,
+ **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """ForkSession creates child sessions from a checkpoint of this session.
+
+ Each child boots a fresh sandbox from the checkpoint's machine-state capture and is drivable
+ exactly like any other session (input, HITL), with parent_session_id and fork_id set for
+ lineage. When from_checkpoint_id is omitted, an implicit checkpoint of the session "now" is
+ captured first and the children fork from that. All-or-nothing: on failure nothing is left
+ running.
+
+ :param session_id: The session UUID. Required.
+ :type session_id: str
+ :param body: Optional; an empty or omitted body forks a single child from an implicit
+ checkpoint of "now". Is either a JSON type or a IO[bytes] type. Default value is None.
+ :type body: JSON or IO[bytes]
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "count": 1, # Optional. Default value is 1. Number of child sessions to
+ create, 1-4. Defaults to 1 when omitted; a value outside 1-4 is rejected with
+ 400.
+ "from_checkpoint_id": "str" # Optional. Checkpoint to fork from; must be
+ READY. Omitted/empty means capture an implicit checkpoint of the session "now"
+ first and fork from that.
+ }
+
+ # response body for status code(s): 200
+ response == {
+ "sessions": [
+ {
+ "agent_kind": "AGENT_KIND_UNSPECIFIED", # Optional. Default
+ value is "AGENT_KIND_UNSPECIFIED". AgentKind identifies what runs inside
+ the session sandbox. CreateSession accepts CLAUDE_CODE, OPENCODE,
+ CODEX_CLI, CURSOR_CLI, OPENAI_CODEX, LANGGRAPH, and CREWAI (the supported
+ set is overridable via HARNESS_SUPPORTED_AGENT_KINDS); other values are
+ rejected with 400. AGENT_KIND_OPENAI_CODEX is the OpenAI sandbox-provider
+ kind (DO runs codex exec-server; the agent loop lives at OpenAI).
+ AGENT_KIND_LANGGRAPH is the LangGraph framework adapter.
+ AGENT_KIND_CREWAI is the CrewAI Crew framework adapter: like LANGGRAPH
+ the template bakes no agent code, so spec.env must supply FRAMEWORK_REPO
+ and FRAMEWORK_REPO_SHA; a Crew kickoff is one-shot and exposes no HITL
+ surface. CREWAI is additionally gated per team and returns 400 for teams
+ it is not enabled for. Known values are: "AGENT_KIND_UNSPECIFIED",
+ "AGENT_KIND_CLAUDE_CODE", "AGENT_KIND_OPENCODE", "AGENT_KIND_CODEX_CLI",
+ "AGENT_KIND_CURSOR_CLI", "AGENT_KIND_NONE", "AGENT_KIND_CUSTOM",
+ "AGENT_KIND_HERMES", "AGENT_KIND_OPENAI_CODEX", "AGENT_KIND_LANGGRAPH",
+ and "AGENT_KIND_CREWAI".
+ "config_id": "str", # Optional. Durable Environment Config
+ UUID the session was created from (inline manifests persist a config too,
+ named after the session). Persisted and returned on create/get/list;
+ absent only for sessions created before config references were stored.
+ "created_at": "2020-02-20 00:00:00", # Optional. The created
+ child sessions, each a full Session with parent_session_id and fork_id
+ set (PROVISIONING -> READY) and drivable exactly like any other session.
+ "fork_from_checkpoint_id": "str", # Optional. Lineage:
+ harness-api checkpoint id (cp_:code:``) the child booted from at
+ fork time. Drives OHP inherited-history replay on attach. Omitted/empty
+ for root sessions and legacy forks created before this field was
+ persisted.
+ "fork_id": "str", # Optional. Lineage: branch label assigned
+ when this session was created by ForkSession (or rollback's internal
+ fork). Omitted/empty for root sessions.
+ "idle_timeout_seconds": 0, # Optional. This session's own
+ idle-pause timeout (manifest idle_timeout). Omitted when the session uses
+ the deployment-wide default.
+ "keep_warm": bool, # Optional. Session is exempt from idle
+ auto-pause (manifest keep_warm, or the agent-kind default: hermes
+ sessions keep warm). Pause requests against such a session are rejected
+ with 409. Omitted when false.
+ "last_event_at": "2020-02-20 00:00:00", # Optional.
+ Timestamp of the most recent event in this session's canonical stream.
+ Drives the inactivity policy that destroys idle sessions.
+ "name": "str", # Optional. User-assignable display name,
+ unique per team among non-terminal sessions. Usable in place of
+ session_id by clients (doctl / Console resolve it to the id via the
+ ListSessions ?name= filter; the {session_id} path stays UUID-only).
+ Supplied via the environment-spec metadata.name, or auto-generated
+ ("session-:code:``-:code:``") when omitted.
+ "openai_environment_id": "str", # Optional. OpenAI Agents
+ API environment id (env_"u2026), captured from the resolved
+ CODEX_ENVIRONMENT_ID guest env value. Populated only for
+ AGENT_KIND_OPENAI_CODEX sessions. Non-secret correlation metadata.
+ "openai_session_id": "str", # Optional. OpenAI Agents API
+ session id (sess_"u2026) this DO sandbox hosts. Populated only for
+ AGENT_KIND_OPENAI_CODEX sessions (empty otherwise). Non-secret
+ correlation metadata; a client (doctl agents attach) reads it to bridge
+ to the OpenAI session. See docs/design/openai-sandbox-provider.md.
+ "parent_session_id": "str", # Optional. Lineage: id of the
+ session this one was forked from. Omitted/empty for root (non-fork)
+ sessions.
+ "pause_reason": "str", # Optional. Why this session is
+ paused. Present only when status is SESSION_STATUS_PAUSED; omitted
+ otherwise. Known values: manual (PauseSession RPC), idle (inactivity
+ auto-pause), low_balance (prepay gate). Clients should treat an
+ unrecognized value as an opaque reason string.
+ "repo_hint": "str", # Optional. Optional repository hint
+ supplied at session creation (first spec.workspace.repos entry of the
+ manifest). Not authoritative; the agent may change repos in-session.
+ "resume_on_topoff": bool, # Optional. Session consents to
+ being resumed automatically when the team's prepayment balance is
+ restored after a low-balance pause. Defaults to false at create time; may
+ be toggled later via PATCH /v2/agents/sessions/{session_id}
+ (resume_on_topoff only). Only a session paused with reason low_balance
+ whose latest run did not complete is ever resumed automatically - a
+ session the customer paused themselves, or one that idled out, stays
+ paused regardless. Not an environment-spec field, and forks do not
+ inherit it. Omitted when false.
+ "sandbox_id": "str", # Optional. Sandbox identity for
+ support / debugging. Informational; omitted until a sandbox is allocated.
+ "session_id": "str", # Optional. The created child sessions,
+ each a full Session with parent_session_id and fork_id set (PROVISIONING
+ -> READY) and drivable exactly like any other session.
+ "status": "SESSION_STATUS_UNSPECIFIED", # Optional. Default
+ value is "SESSION_STATUS_UNSPECIFIED". SessionStatus is the lifecycle
+ state of the sandbox + agent pair. SESSION_STATUS_ALL is a ListSessions
+ status-filter value only -- no session is ever actually in this status.
+ SESSION_STATUS_LOCKED is reserved for internal use and never appears in
+ an end-user-facing response. Known values are:
+ "SESSION_STATUS_UNSPECIFIED", "SESSION_STATUS_PROVISIONING",
+ "SESSION_STATUS_READY", "SESSION_STATUS_DETACHED",
+ "SESSION_STATUS_DESTROYING", "SESSION_STATUS_DESTROYED",
+ "SESSION_STATUS_FAILED", "SESSION_STATUS_PAUSED", "SESSION_STATUS_ALL",
+ and "SESSION_STATUS_LOCKED".
+ "warnings": [
+ "str" # Optional. Non-fatal advisories computed from
+ the manifest at create time: one entry per populated
+ accepted-but-not-yet-enforced section (flat names: secrets, model,
+ tools, memory, budget, max_lifetime, mounts; legacy manifests get the
+ corresponding spec.* paths), a deprecation entry when a
+ legacy-envelope manifest or an adapter alias (codex-cli, cursor-cli)
+ is used, and a heuristic entry per credential-looking spec.env value.
+ Populated on the CreateSession response only.
+ ]
+ }
+ ]
+ }
+ # response body for status code(s): 402, 403, 404, 409, 423, 501
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
+ _params = kwargs.pop("params", {}) or {}
+
+ content_type: Optional[str] = kwargs.pop(
+ "content_type", _headers.pop("Content-Type", None)
+ )
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ content_type = content_type or "application/json"
+ _json = None
+ _content = None
+ if isinstance(body, (IOBase, bytes)):
+ _content = body
+ else:
+ if body is not None:
+ _json = body
+ else:
+ _json = None
+
+ _request = build_harness_create_session_fork_request(
+ session_id=session_id,
+ content_type=content_type,
+ json=_json,
+ content=_content,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 402, 403, 404, 409, 423, 501]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ if response.status_code == 200:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 402:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 403:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 409:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 423:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 501:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+ @overload
+ async def post_session_hitl(
+ self,
+ session_id: str,
+ request_id_parameter: str,
+ body: JSON,
+ *,
+ x_device_uuid: Optional[str] = None,
+ content_type: str = "application/json",
+ **kwargs: Any
+ ) -> Optional[JSON]:
+ # pylint: disable=line-too-long
+ """ResolveHITL records the user's decision on a pending HITL request.
+
+ harness-api forwards the decision into the owning microVM via the inbound
+ runtime.v1.OHR.ResolveHITL RPC (dialed through the guest-fronting proxy), which unblocks the
+ gated agent action. The resolution is also echoed to all attached clients as a HITLResolved
+ event on StreamSession. Returns 204 No Content on success.
+
+ :param session_id: The session UUID. Required.
+ :type session_id: str
+ :param request_id_parameter: The HITL request identifier. Required.
+ :type request_id_parameter: str
+ :param body: Required.
+ :type body: JSON
+ :keyword x_device_uuid: Optional hardware device id forwarded by doctl. Recorded on the
+ resulting HITL decision. Default value is None.
+ :paramtype x_device_uuid: str
+ :keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
+ Default value is "application/json".
+ :paramtype content_type: str
+ :return: JSON object or None
+ :rtype: JSON or None
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "outcome": "HITL_OUTCOME_UNSPECIFIED", # Default value is
+ "HITL_OUTCOME_UNSPECIFIED". HITLOutcome is the user's decision on a HITL request.
+ DEFER backs off this attempt without treating it as a rejection. Known values
+ are: "HITL_OUTCOME_UNSPECIFIED", "HITL_OUTCOME_APPROVE", "HITL_OUTCOME_REJECT",
+ and "HITL_OUTCOME_DEFER".
+ "reason": "str", # Optional. Optional free-text reason. Captured in the
+ audit trail; not interpreted.
+ "source": "RESOLUTION_SOURCE_UNSPECIFIED" # Optional. Default value is
+ "RESOLUTION_SOURCE_UNSPECIFIED". How a HITL resolution was triggered. Defaults to
+ RESOLUTION_SOURCE_OUT_OF_BAND when omitted. Known values are:
+ "RESOLUTION_SOURCE_UNSPECIFIED", "RESOLUTION_SOURCE_INLINE_KEYSTROKE", and
+ "RESOLUTION_SOURCE_OUT_OF_BAND".
+ }
+
+ # response body for status code(s): 400, 402, 403, 404, 423
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+
+ @overload
+ async def post_session_hitl(
+ self,
+ session_id: str,
+ request_id_parameter: str,
+ body: IO[bytes],
+ *,
+ x_device_uuid: Optional[str] = None,
+ content_type: str = "application/json",
+ **kwargs: Any
+ ) -> Optional[JSON]:
+ # pylint: disable=line-too-long
+ """ResolveHITL records the user's decision on a pending HITL request.
+
+ harness-api forwards the decision into the owning microVM via the inbound
+ runtime.v1.OHR.ResolveHITL RPC (dialed through the guest-fronting proxy), which unblocks the
+ gated agent action. The resolution is also echoed to all attached clients as a HITLResolved
+ event on StreamSession. Returns 204 No Content on success.
+
+ :param session_id: The session UUID. Required.
+ :type session_id: str
+ :param request_id_parameter: The HITL request identifier. Required.
+ :type request_id_parameter: str
+ :param body: Required.
+ :type body: IO[bytes]
+ :keyword x_device_uuid: Optional hardware device id forwarded by doctl. Recorded on the
+ resulting HITL decision. Default value is None.
+ :paramtype x_device_uuid: str
+ :keyword content_type: Body Parameter content-type. Content type parameter for binary body.
+ Default value is "application/json".
+ :paramtype content_type: str
+ :return: JSON object or None
+ :rtype: JSON or None
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 400, 402, 403, 404, 423
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+
+ @distributed_trace_async
+ async def post_session_hitl(
+ self,
+ session_id: str,
+ request_id_parameter: str,
+ body: Union[JSON, IO[bytes]],
+ *,
+ x_device_uuid: Optional[str] = None,
+ **kwargs: Any
+ ) -> Optional[JSON]:
+ # pylint: disable=line-too-long
+ """ResolveHITL records the user's decision on a pending HITL request.
+
+ harness-api forwards the decision into the owning microVM via the inbound
+ runtime.v1.OHR.ResolveHITL RPC (dialed through the guest-fronting proxy), which unblocks the
+ gated agent action. The resolution is also echoed to all attached clients as a HITLResolved
+ event on StreamSession. Returns 204 No Content on success.
+
+ :param session_id: The session UUID. Required.
+ :type session_id: str
+ :param request_id_parameter: The HITL request identifier. Required.
+ :type request_id_parameter: str
+ :param body: Is either a JSON type or a IO[bytes] type. Required.
+ :type body: JSON or IO[bytes]
+ :keyword x_device_uuid: Optional hardware device id forwarded by doctl. Recorded on the
+ resulting HITL decision. Default value is None.
+ :paramtype x_device_uuid: str
+ :return: JSON object or None
+ :rtype: JSON or None
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "outcome": "HITL_OUTCOME_UNSPECIFIED", # Default value is
+ "HITL_OUTCOME_UNSPECIFIED". HITLOutcome is the user's decision on a HITL request.
+ DEFER backs off this attempt without treating it as a rejection. Known values
+ are: "HITL_OUTCOME_UNSPECIFIED", "HITL_OUTCOME_APPROVE", "HITL_OUTCOME_REJECT",
+ and "HITL_OUTCOME_DEFER".
+ "reason": "str", # Optional. Optional free-text reason. Captured in the
+ audit trail; not interpreted.
+ "source": "RESOLUTION_SOURCE_UNSPECIFIED" # Optional. Default value is
+ "RESOLUTION_SOURCE_UNSPECIFIED". How a HITL resolution was triggered. Defaults to
+ RESOLUTION_SOURCE_OUT_OF_BAND when omitted. Known values are:
+ "RESOLUTION_SOURCE_UNSPECIFIED", "RESOLUTION_SOURCE_INLINE_KEYSTROKE", and
+ "RESOLUTION_SOURCE_OUT_OF_BAND".
+ }
+
+ # response body for status code(s): 400, 402, 403, 404, 423
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
+ _params = kwargs.pop("params", {}) or {}
+
+ content_type: Optional[str] = kwargs.pop(
+ "content_type", _headers.pop("Content-Type", None)
+ )
+ cls: ClsType[Optional[JSON]] = kwargs.pop("cls", None)
+
+ content_type = content_type or "application/json"
+ _json = None
+ _content = None
+ if isinstance(body, (IOBase, bytes)):
+ _content = body
+ else:
+ _json = body
+
+ _request = build_harness_post_session_hitl_request(
+ session_id=session_id,
+ request_id_parameter=request_id_parameter,
+ x_device_uuid=x_device_uuid,
+ content_type=content_type,
+ json=_json,
+ content=_content,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [204, 400, 402, 403, 404, 423]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ deserialized = None
+ response_headers = {}
+ if response.status_code == 204:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.status_code == 400:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 402:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 403:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 423:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, deserialized, response_headers) # type: ignore
+
+ return deserialized # type: ignore
+
+ @overload
+ async def create_session_input(
+ self,
+ session_id: str,
+ body: JSON,
+ *,
+ content_type: str = "application/json",
+ **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """SendInput delivers a user chat message into the session.
+
+ The agent observes it on its next turn and emits subsequent events via StreamSession. The input
+ is forwarded to the owning microVM's OHR inbound surface, which attributes it to a run and
+ returns the run id.
+
+ :param session_id: The session UUID. Required.
+ :type session_id: str
+ :param body: Required.
+ :type body: JSON
+ :keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
+ Default value is "application/json".
+ :paramtype content_type: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "text": "str" # The user message to deliver into the session. Required and
+ non-empty. Required.
+ }
+
+ # response body for status code(s): 200
+ response == {
+ "run_id": "str" # Optional. The run id the input was attributed to. Clients
+ can correlate against the run.started event on the stream. May be empty if OHR
+ returned no run id.
+ }
+ # response body for status code(s): 400, 402, 403, 404, 409, 423
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+
+ @overload
+ async def create_session_input(
+ self,
+ session_id: str,
+ body: IO[bytes],
+ *,
+ content_type: str = "application/json",
+ **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """SendInput delivers a user chat message into the session.
+
+ The agent observes it on its next turn and emits subsequent events via StreamSession. The input
+ is forwarded to the owning microVM's OHR inbound surface, which attributes it to a run and
+ returns the run id.
+
+ :param session_id: The session UUID. Required.
+ :type session_id: str
+ :param body: Required.
+ :type body: IO[bytes]
+ :keyword content_type: Body Parameter content-type. Content type parameter for binary body.
+ Default value is "application/json".
+ :paramtype content_type: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 200
+ response == {
+ "run_id": "str" # Optional. The run id the input was attributed to. Clients
+ can correlate against the run.started event on the stream. May be empty if OHR
+ returned no run id.
+ }
+ # response body for status code(s): 400, 402, 403, 404, 409, 423
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+
+ @distributed_trace_async
+ async def create_session_input(
+ self, session_id: str, body: Union[JSON, IO[bytes]], **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """SendInput delivers a user chat message into the session.
+
+ The agent observes it on its next turn and emits subsequent events via StreamSession. The input
+ is forwarded to the owning microVM's OHR inbound surface, which attributes it to a run and
+ returns the run id.
+
+ :param session_id: The session UUID. Required.
+ :type session_id: str
+ :param body: Is either a JSON type or a IO[bytes] type. Required.
+ :type body: JSON or IO[bytes]
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "text": "str" # The user message to deliver into the session. Required and
+ non-empty. Required.
+ }
+
+ # response body for status code(s): 200
+ response == {
+ "run_id": "str" # Optional. The run id the input was attributed to. Clients
+ can correlate against the run.started event on the stream. May be empty if OHR
+ returned no run id.
+ }
+ # response body for status code(s): 400, 402, 403, 404, 409, 423
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
+ _params = kwargs.pop("params", {}) or {}
+
+ content_type: Optional[str] = kwargs.pop(
+ "content_type", _headers.pop("Content-Type", None)
+ )
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ content_type = content_type or "application/json"
+ _json = None
+ _content = None
+ if isinstance(body, (IOBase, bytes)):
+ _content = body
+ else:
+ _json = body
+
+ _request = build_harness_create_session_input_request(
+ session_id=session_id,
+ content_type=content_type,
+ json=_json,
+ content=_content,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 400, 402, 403, 404, 409, 423]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ if response.status_code == 200:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 400:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 402:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 403:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 409:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 423:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+ @distributed_trace_async
+ async def post_session_pause(
+ self, session_id: str, *, x_device_uuid: Optional[str] = None, **kwargs: Any
+ ) -> Optional[JSON]:
+ # pylint: disable=line-too-long
+ """PauseSession freezes the session's microVM sandbox.
+
+ Supported on microvm-substrate sessions only; dewdrop/docker sessions return 501 Not
+ Implemented. Paused sessions count against quota. Clients learn state via
+ GetSession/ListSessions; no live session.updated event is emitted.
+
+ :param session_id: The session UUID. Required.
+ :type session_id: str
+ :keyword x_device_uuid: Optional hardware device id forwarded by doctl. Recorded for audit.
+ Default value is None.
+ :paramtype x_device_uuid: str
+ :return: JSON object or None
+ :rtype: JSON or None
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 402, 403, 404, 409, 423, 501
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = kwargs.pop("headers", {}) or {}
+ _params = kwargs.pop("params", {}) or {}
+
+ cls: ClsType[Optional[JSON]] = kwargs.pop("cls", None)
+
+ _request = build_harness_post_session_pause_request(
+ session_id=session_id,
+ x_device_uuid=x_device_uuid,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [204, 402, 403, 404, 409, 423, 501]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ deserialized = None
+ response_headers = {}
+ if response.status_code == 204:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.status_code == 402:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 403:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 409:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 423:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 501:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, deserialized, response_headers) # type: ignore
+
+ return deserialized # type: ignore
+
+ @distributed_trace_async
+ async def post_session_resume(
+ self, session_id: str, *, x_device_uuid: Optional[str] = None, **kwargs: Any
+ ) -> Optional[JSON]:
+ # pylint: disable=line-too-long
+ """ResumeSession explicitly thaws a PAUSED session's microVM sandbox.
+
+ Only valid for microvm-substrate sessions; dewdrop/docker sessions return 501 Not Implemented.
+ Implicit resume also occurs when SendInput or ResolveHITL is called on a paused session.
+ Returns synchronously once the sandbox is ready.
+
+ :param session_id: The session UUID. Required.
+ :type session_id: str
+ :keyword x_device_uuid: Optional hardware device id forwarded by doctl. Recorded for audit.
+ Default value is None.
+ :paramtype x_device_uuid: str
+ :return: JSON object or None
+ :rtype: JSON or None
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 402, 403, 404, 409, 423, 501
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = kwargs.pop("headers", {}) or {}
+ _params = kwargs.pop("params", {}) or {}
+
+ cls: ClsType[Optional[JSON]] = kwargs.pop("cls", None)
+
+ _request = build_harness_post_session_resume_request(
+ session_id=session_id,
+ x_device_uuid=x_device_uuid,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [204, 402, 403, 404, 409, 423, 501]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ deserialized = None
+ response_headers = {}
+ if response.status_code == 204:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.status_code == 402:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 403:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 409:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 423:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 501:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, deserialized, response_headers) # type: ignore
+
+ return deserialized # type: ignore
+
+ @overload
+ async def post_session_sandbox_exec(
+ self,
+ session_id: str,
+ body: JSON,
+ *,
+ content_type: str = "application/json",
+ **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """ExecInSandbox runs a one-shot command inside the session's sandbox.
+
+ Runs ``argv`` directly in the guest (no shell). Stdout/stderr are buffered and capped at 1 MiB
+ each;
+ truncation is indicated via response headers when present. A non-zero exit code is still HTTP
+ 200.
+
+ :param session_id: The session UUID. Required.
+ :type session_id: str
+ :param body: Command to run inside the sandbox. Required.
+ :type body: JSON
+ :keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
+ Default value is "application/json".
+ :paramtype content_type: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "argv": [
+ "str" # Program and arguments. Required and non-empty; run directly,
+ with no shell interpretation. Required.
+ ],
+ "stdin": bytes("bytes", encoding="utf-8"), # Optional. Optional base64 stdin
+ payload, delivered in full and then closed so the process sees EOF. One-shot only
+ "u2014 there is no streaming stdin on this endpoint.
+ "timeout_seconds": 0, # Optional. Optional timeout. Clamped server-side
+ (default 60, maximum 240) regardless of the value sent.
+ "workdir": "str" # Optional. Working directory inside the sandbox. Empty
+ uses the sandbox default (/workspace); not restricted to the workspace root.
+ }
+
+ # response body for status code(s): 200
+ response == {
+ "duration_ms": 0, # Optional. Wall-clock duration the guest reported for the
+ command.
+ "exit_code": 0, # Optional. The guest process's exit code. Non-zero is still
+ a 200 response.
+ "stderr": "str", # Optional. Buffered stderr, capped at 1 MiB. Check
+ X-Exec-Stderr-Truncated for drops.
+ "stdout": "str" # Optional. Buffered stdout, capped at 1 MiB. Check
+ X-Exec-Stdout-Truncated for drops.
+ }
+ # response body for status code(s): 400, 402, 403, 404, 409, 423
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+
+ @overload
+ async def post_session_sandbox_exec(
+ self,
+ session_id: str,
+ body: IO[bytes],
+ *,
+ content_type: str = "application/json",
+ **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """ExecInSandbox runs a one-shot command inside the session's sandbox.
+
+ Runs ``argv`` directly in the guest (no shell). Stdout/stderr are buffered and capped at 1 MiB
+ each;
+ truncation is indicated via response headers when present. A non-zero exit code is still HTTP
+ 200.
+
+ :param session_id: The session UUID. Required.
+ :type session_id: str
+ :param body: Command to run inside the sandbox. Required.
+ :type body: IO[bytes]
+ :keyword content_type: Body Parameter content-type. Content type parameter for binary body.
+ Default value is "application/json".
+ :paramtype content_type: str
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # response body for status code(s): 200
+ response == {
+ "duration_ms": 0, # Optional. Wall-clock duration the guest reported for the
+ command.
+ "exit_code": 0, # Optional. The guest process's exit code. Non-zero is still
+ a 200 response.
+ "stderr": "str", # Optional. Buffered stderr, capped at 1 MiB. Check
+ X-Exec-Stderr-Truncated for drops.
+ "stdout": "str" # Optional. Buffered stdout, capped at 1 MiB. Check
+ X-Exec-Stdout-Truncated for drops.
+ }
+ # response body for status code(s): 400, 402, 403, 404, 409, 423
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+
+ @distributed_trace_async
+ async def post_session_sandbox_exec(
+ self, session_id: str, body: Union[JSON, IO[bytes]], **kwargs: Any
+ ) -> JSON:
+ # pylint: disable=line-too-long
+ """ExecInSandbox runs a one-shot command inside the session's sandbox.
+
+ Runs ``argv`` directly in the guest (no shell). Stdout/stderr are buffered and capped at 1 MiB
+ each;
+ truncation is indicated via response headers when present. A non-zero exit code is still HTTP
+ 200.
+
+ :param session_id: The session UUID. Required.
+ :type session_id: str
+ :param body: Command to run inside the sandbox. Is either a JSON type or a IO[bytes] type.
+ Required.
+ :type body: JSON or IO[bytes]
+ :return: JSON object
+ :rtype: JSON
+ :raises ~azure.core.exceptions.HttpResponseError:
+
+ Example:
+ .. code-block:: python
+
+ # JSON input template you can fill out and use as your body input.
+ body = {
+ "argv": [
+ "str" # Program and arguments. Required and non-empty; run directly,
+ with no shell interpretation. Required.
+ ],
+ "stdin": bytes("bytes", encoding="utf-8"), # Optional. Optional base64 stdin
+ payload, delivered in full and then closed so the process sees EOF. One-shot only
+ "u2014 there is no streaming stdin on this endpoint.
+ "timeout_seconds": 0, # Optional. Optional timeout. Clamped server-side
+ (default 60, maximum 240) regardless of the value sent.
+ "workdir": "str" # Optional. Working directory inside the sandbox. Empty
+ uses the sandbox default (/workspace); not restricted to the workspace root.
+ }
+
+ # response body for status code(s): 200
+ response == {
+ "duration_ms": 0, # Optional. Wall-clock duration the guest reported for the
+ command.
+ "exit_code": 0, # Optional. The guest process's exit code. Non-zero is still
+ a 200 response.
+ "stderr": "str", # Optional. Buffered stderr, capped at 1 MiB. Check
+ X-Exec-Stderr-Truncated for drops.
+ "stdout": "str" # Optional. Buffered stdout, capped at 1 MiB. Check
+ X-Exec-Stdout-Truncated for drops.
+ }
+ # response body for status code(s): 400, 402, 403, 404, 409, 423
+ response == {
+ "id": "str", # A short identifier corresponding to the HTTP status code
+ returned. For example, the ID for a response returning a 404 status code would
+ be "not_found.". Required.
+ "message": "str", # A message providing additional information about the
+ error, including details to help resolve it when possible. Required.
+ "request_id": "str" # Optional. Optionally, some endpoints may include a
+ request ID that should be provided when reporting bugs or opening support
+ tickets to help identify the issue.
+ }
+ """
+ error_map: MutableMapping[int, Type[HttpResponseError]] = {
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
+ 401: cast(
+ Type[HttpResponseError],
+ lambda response: ClientAuthenticationError(response=response),
+ ),
+ 429: HttpResponseError,
+ 500: HttpResponseError,
+ }
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
+ _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
+ _params = kwargs.pop("params", {}) or {}
+
+ content_type: Optional[str] = kwargs.pop(
+ "content_type", _headers.pop("Content-Type", None)
+ )
+ cls: ClsType[JSON] = kwargs.pop("cls", None)
+
+ content_type = content_type or "application/json"
+ _json = None
+ _content = None
+ if isinstance(body, (IOBase, bytes)):
+ _content = body
+ else:
+ _json = body
+
+ _request = build_harness_post_session_sandbox_exec_request(
+ session_id=session_id,
+ content_type=content_type,
+ json=_json,
+ content=_content,
+ headers=_headers,
+ params=_params,
+ )
+ _request.url = self._client.format_url(_request.url)
+
+ _stream = False
+ pipeline_response: PipelineResponse = (
+ await self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
+ )
+ )
+
+ response = pipeline_response.http_response
+
+ if response.status_code not in [200, 400, 402, 403, 404, 409, 423]:
+ if _stream:
+ await response.read() # Load the body in memory and close the socket
+ map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
+ raise HttpResponseError(response=response)
+
+ response_headers = {}
+ if response.status_code == 200:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 400:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 402:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 403:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 404:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 409:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if response.status_code == 423:
+ response_headers["ratelimit-limit"] = self._deserialize(
+ "int", response.headers.get("ratelimit-limit")
+ )
+ response_headers["ratelimit-remaining"] = self._deserialize(
+ "int", response.headers.get("ratelimit-remaining")
+ )
+ response_headers["ratelimit-reset"] = self._deserialize(
+ "int", response.headers.get("ratelimit-reset")
+ )
+
+ if response.content:
+ deserialized = response.json()
+ else:
+ deserialized = None
+
+ if cls:
+ return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore
+
+ return cast(JSON, deserialized) # type: ignore
+
+ @distributed_trace_async
+ async def get_session_workspace_download(
+ self,
+ session_id: str,
+ *,
+ path: str,
+ as_archive: Optional[bool] = None,
+ **kwargs: Any
+ ) -> Union[AsyncIterator[bytes], JSON]:
+ # pylint: disable=line-too-long
+ """Download a file or tar archive from the session's sandbox workspace.
+
+ Streams the workspace payload back as ``application/octet-stream`` using chunked transfer
+ encoding, followed by a fixed integrity footer.
+
+ Response body layout: ```` + ``