22
33from __future__ import annotations
44
5+ import time
56import httpx
67
78from .routes import (
@@ -612,6 +613,93 @@ def update_status(
612613 cast_to = AgentUpdateStatusResponse ,
613614 )
614615
616+ def wait_until_ready (
617+ self ,
618+ uuid : str ,
619+ * ,
620+ timeout : float = 300.0 ,
621+ poll_interval : float = 5.0 ,
622+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
623+ # The extra values given here take precedence over values defined on the client or passed to this method.
624+ extra_headers : Headers | None = None ,
625+ extra_query : Query | None = None ,
626+ extra_body : Body | None = None ,
627+ ) -> AgentRetrieveResponse :
628+ """Wait for an agent to be ready (deployment status is STATUS_RUNNING).
629+
630+ This method polls the agent status until it reaches STATUS_RUNNING or a terminal
631+ error state. It handles timeout and deployment failures automatically.
632+
633+ Args:
634+ uuid: The unique identifier of the agent to wait for
635+
636+ timeout: Maximum time to wait in seconds (default: 300 seconds / 5 minutes)
637+
638+ poll_interval: Time to wait between status checks in seconds (default: 5 seconds)
639+
640+ extra_headers: Send extra headers
641+
642+ extra_query: Add additional query parameters to the request
643+
644+ extra_body: Add additional JSON properties to the request
645+
646+ Returns:
647+ AgentRetrieveResponse: The agent response when it reaches STATUS_RUNNING
648+
649+ Raises:
650+ AgentDeploymentError: If the agent deployment fails (STATUS_FAILED,
651+ STATUS_UNDEPLOYMENT_FAILED, or STATUS_DELETED)
652+ AgentDeploymentTimeoutError: If the agent doesn't reach STATUS_RUNNING
653+ within the timeout period
654+ ValueError: If uuid is empty
655+ """
656+ from ..._exceptions import AgentDeploymentError , AgentDeploymentTimeoutError
657+
658+ if not uuid :
659+ raise ValueError (f"Expected a non-empty value for `uuid` but received { uuid !r} " )
660+
661+ start_time = time .time ()
662+
663+ while True :
664+ agent_response = self .retrieve (
665+ uuid ,
666+ extra_headers = extra_headers ,
667+ extra_query = extra_query ,
668+ extra_body = extra_body ,
669+ )
670+
671+ # Check if agent and deployment exist
672+ if agent_response .agent and agent_response .agent .deployment :
673+ status = agent_response .agent .deployment .status
674+
675+ # Success case
676+ if status == "STATUS_RUNNING" :
677+ return agent_response
678+
679+ # Failure cases
680+ if status in ("STATUS_FAILED" , "STATUS_UNDEPLOYMENT_FAILED" , "STATUS_DELETED" ):
681+ raise AgentDeploymentError (
682+ f"Agent deployment failed with status: { status } " ,
683+ status = status or "UNKNOWN" ,
684+ )
685+
686+ # Check timeout
687+ elapsed_time = time .time () - start_time
688+ if elapsed_time >= timeout :
689+ current_status = (
690+ agent_response .agent .deployment .status
691+ if agent_response .agent and agent_response .agent .deployment
692+ else "UNKNOWN"
693+ )
694+ raise AgentDeploymentTimeoutError (
695+ f"Agent did not reach STATUS_RUNNING within { timeout } seconds. "
696+ f"Current status: { current_status } " ,
697+ agent_id = uuid ,
698+ )
699+
700+ # Wait before polling again
701+ time .sleep (poll_interval )
702+
615703
616704class AsyncAgentsResource (AsyncAPIResource ):
617705 @cached_property
@@ -1108,6 +1196,94 @@ async def update_status(
11081196 cast_to = AgentUpdateStatusResponse ,
11091197 )
11101198
1199+ async def wait_until_ready (
1200+ self ,
1201+ uuid : str ,
1202+ * ,
1203+ timeout : float = 300.0 ,
1204+ poll_interval : float = 5.0 ,
1205+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
1206+ # The extra values given here take precedence over values defined on the client or passed to this method.
1207+ extra_headers : Headers | None = None ,
1208+ extra_query : Query | None = None ,
1209+ extra_body : Body | None = None ,
1210+ ) -> AgentRetrieveResponse :
1211+ """Wait for an agent to be ready (deployment status is STATUS_RUNNING).
1212+
1213+ This method polls the agent status until it reaches STATUS_RUNNING or a terminal
1214+ error state. It handles timeout and deployment failures automatically.
1215+
1216+ Args:
1217+ uuid: The unique identifier of the agent to wait for
1218+
1219+ timeout: Maximum time to wait in seconds (default: 300 seconds / 5 minutes)
1220+
1221+ poll_interval: Time to wait between status checks in seconds (default: 5 seconds)
1222+
1223+ extra_headers: Send extra headers
1224+
1225+ extra_query: Add additional query parameters to the request
1226+
1227+ extra_body: Add additional JSON properties to the request
1228+
1229+ Returns:
1230+ AgentRetrieveResponse: The agent response when it reaches STATUS_RUNNING
1231+
1232+ Raises:
1233+ AgentDeploymentError: If the agent deployment fails (STATUS_FAILED,
1234+ STATUS_UNDEPLOYMENT_FAILED, or STATUS_DELETED)
1235+ AgentDeploymentTimeoutError: If the agent doesn't reach STATUS_RUNNING
1236+ within the timeout period
1237+ ValueError: If uuid is empty
1238+ """
1239+ import asyncio
1240+ from ..._exceptions import AgentDeploymentError , AgentDeploymentTimeoutError
1241+
1242+ if not uuid :
1243+ raise ValueError (f"Expected a non-empty value for `uuid` but received { uuid !r} " )
1244+
1245+ start_time = time .time ()
1246+
1247+ while True :
1248+ agent_response = await self .retrieve (
1249+ uuid ,
1250+ extra_headers = extra_headers ,
1251+ extra_query = extra_query ,
1252+ extra_body = extra_body ,
1253+ )
1254+
1255+ # Check if agent and deployment exist
1256+ if agent_response .agent and agent_response .agent .deployment :
1257+ status = agent_response .agent .deployment .status
1258+
1259+ # Success case
1260+ if status == "STATUS_RUNNING" :
1261+ return agent_response
1262+
1263+ # Failure cases
1264+ if status in ("STATUS_FAILED" , "STATUS_UNDEPLOYMENT_FAILED" , "STATUS_DELETED" ):
1265+ raise AgentDeploymentError (
1266+ f"Agent deployment failed with status: { status } " ,
1267+ status = status or "UNKNOWN" ,
1268+ )
1269+
1270+ # Check timeout
1271+ elapsed_time = time .time () - start_time
1272+ if elapsed_time >= timeout :
1273+ current_status = (
1274+ agent_response .agent .deployment .status
1275+ if agent_response .agent and agent_response .agent .deployment
1276+ else "UNKNOWN"
1277+ )
1278+ raise AgentDeploymentTimeoutError (
1279+ f"Agent did not reach STATUS_RUNNING within { timeout } seconds. "
1280+ f"Current status: { current_status } " ,
1281+ agent_id = uuid ,
1282+ )
1283+
1284+ # Wait before polling again
1285+ await asyncio .sleep (poll_interval )
1286+
11111287
11121288class AgentsResourceWithRawResponse :
11131289 def __init__ (self , agents : AgentsResource ) -> None :
@@ -1134,6 +1310,9 @@ def __init__(self, agents: AgentsResource) -> None:
11341310 self .update_status = to_raw_response_wrapper (
11351311 agents .update_status ,
11361312 )
1313+ self .wait_until_ready = to_raw_response_wrapper (
1314+ agents .wait_until_ready ,
1315+ )
11371316
11381317 @cached_property
11391318 def api_keys (self ) -> APIKeysResourceWithRawResponse :
@@ -1201,6 +1380,9 @@ def __init__(self, agents: AsyncAgentsResource) -> None:
12011380 self .update_status = async_to_raw_response_wrapper (
12021381 agents .update_status ,
12031382 )
1383+ self .wait_until_ready = async_to_raw_response_wrapper (
1384+ agents .wait_until_ready ,
1385+ )
12041386
12051387 @cached_property
12061388 def api_keys (self ) -> AsyncAPIKeysResourceWithRawResponse :
@@ -1268,6 +1450,9 @@ def __init__(self, agents: AgentsResource) -> None:
12681450 self .update_status = to_streamed_response_wrapper (
12691451 agents .update_status ,
12701452 )
1453+ self .wait_until_ready = to_streamed_response_wrapper (
1454+ agents .wait_until_ready ,
1455+ )
12711456
12721457 @cached_property
12731458 def api_keys (self ) -> APIKeysResourceWithStreamingResponse :
@@ -1335,6 +1520,9 @@ def __init__(self, agents: AsyncAgentsResource) -> None:
13351520 self .update_status = async_to_streamed_response_wrapper (
13361521 agents .update_status ,
13371522 )
1523+ self .wait_until_ready = async_to_streamed_response_wrapper (
1524+ agents .wait_until_ready ,
1525+ )
13381526
13391527 @cached_property
13401528 def api_keys (self ) -> AsyncAPIKeysResourceWithStreamingResponse :
0 commit comments