Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions examples/mistral/workflows/async_workflow_execute.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/env python

import asyncio
import os

from mistralai.client import Mistral

WORKFLOW_NAME = "example-hello-world-workflow"


async def main():
api_key = os.environ["MISTRAL_API_KEY"]

client = Mistral(api_key=api_key)

# Execute workflow and wait for result using wait_for_result parameter
response = await client.workflows.execute_workflow_async(
workflow_identifier=WORKFLOW_NAME,
input={"document_title": "hello world"},
wait_for_result=True,
timeout_seconds=60.0,
)

print(f"Workflow: {response.workflow_name}")
print(f"Execution ID: {response.execution_id}")
print(f"Result: {response.result}")


if __name__ == "__main__":
asyncio.run(main())
37 changes: 37 additions & 0 deletions examples/mistral/workflows/async_workflow_execute_and_wait.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/usr/bin/env python

import asyncio
import os

from mistralai.client import Mistral

WORKFLOW_NAME = "example-hello-world-workflow"


async def main():
api_key = os.environ["MISTRAL_API_KEY"]

client = Mistral(api_key=api_key)

# Example 1: Using API sync mode (server-side waiting)
result = await client.workflows.execute_workflow_and_wait_async(
workflow_identifier=WORKFLOW_NAME,
input={"document_title": "hello world"},
use_api_sync=True,
timeout_seconds=60.0,
)
print(f"Result (API sync): {result}")

# Example 2: Using polling mode (client-side waiting)
result = await client.workflows.execute_workflow_and_wait_async(
workflow_identifier=WORKFLOW_NAME,
input={"document_title": "hello world"},
use_api_sync=False,
polling_interval=5,
max_attempts=12, # 12 attempts * 5 seconds = 60 seconds max
)
print(f"Result (polling): {result}")


if __name__ == "__main__":
asyncio.run(main())
29 changes: 29 additions & 0 deletions examples/mistral/workflows/workflow_execute.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env python

import os

from mistralai.client import Mistral

WORKFLOW_NAME = "example-hello-world-workflow"


def main():
api_key = os.environ["MISTRAL_API_KEY"]

client = Mistral(api_key=api_key)

# Execute workflow and wait for result using wait_for_result parameter
response = client.workflows.execute_workflow(
workflow_identifier=WORKFLOW_NAME,
input={"document_title": "hello world"},
wait_for_result=True,
timeout_seconds=60.0,
)

print(f"Workflow: {response.workflow_name}")
print(f"Execution ID: {response.execution_id}")
print(f"Result: {response.result}")


if __name__ == "__main__":
main()
36 changes: 36 additions & 0 deletions examples/mistral/workflows/workflow_execute_and_wait.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/usr/bin/env python

import os

from mistralai.client import Mistral

WORKFLOW_NAME = "example-hello-world-workflow"


def main():
api_key = os.environ["MISTRAL_API_KEY"]

client = Mistral(api_key=api_key)

# Example 1: Using API sync mode (server-side waiting)
result = client.workflows.execute_workflow_and_wait(
workflow_identifier=WORKFLOW_NAME,
input={"document_title": "hello world"},
use_api_sync=True,
timeout_seconds=60.0,
)
print(f"Result (API sync): {result}")

# Example 2: Using polling mode (client-side waiting)
result = client.workflows.execute_workflow_and_wait(
workflow_identifier=WORKFLOW_NAME,
input={"document_title": "hello world"},
use_api_sync=False,
polling_interval=5,
max_attempts=12, # 12 attempts * 5 seconds = 60 seconds max
)
print(f"Result (polling): {result}")


if __name__ == "__main__":
main()
4 changes: 4 additions & 0 deletions scripts/run_examples.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ exclude_files=(
"examples/mistral/audio/async_realtime_transcription_microphone.py"
"examples/mistral/audio/async_realtime_transcription_stream.py"
"examples/mistral/audio/async_realtime_transcription_dual_delay_microphone.py"
"examples/mistral/workflows/workflow_execute_and_wait.py"
"examples/mistral/workflows/async_workflow_execute_and_wait.py"
"examples/mistral/workflows/workflow_execute.py"
"examples/mistral/workflows/async_workflow_execute.py"
)

# Files that require extra dependencies (agents, mcp, audio, etc.)
Expand Down
4 changes: 2 additions & 2 deletions src/mistralai/client/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
import importlib.metadata

__title__: str = "mistralai"
__version__: str = "2.2.2"
__version__: str = "2.2.3"
__openapi_doc_version__: str = "1.0.0"
__gen_version__: str = "2.862.0"
__user_agent__: str = "speakeasy-sdk/python 2.2.2 2.862.0 1.0.0 mistralai"
__user_agent__: str = "speakeasy-sdk/python 2.2.3 2.862.0 1.0.0 mistralai"

try:
if __package__ is not None:
Expand Down
205 changes: 205 additions & 0 deletions src/mistralai/client/workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
from typing import Any, Awaitable, Dict, List, Mapping, Optional, Union
from typing_extensions import deprecated

# region imports
import asyncio
import time
# endregion imports


class Workflows(BaseSDK):
executions: Executions
Expand Down Expand Up @@ -49,6 +54,206 @@ def _init_sdks(self):
self.sdk_configuration, parent_ref=self.parent_ref
)

# region sdk-class-body
def execute_workflow_and_wait(
self,
workflow_identifier: str,
input: OptionalNullable[Dict[str, Any]] = UNSET,
execution_id: OptionalNullable[str] = UNSET,
deployment_name: OptionalNullable[str] = UNSET,
custom_tracing_attributes: OptionalNullable[Dict[str, str]] = UNSET,
polling_interval: int = 5,
max_attempts: Optional[int] = None,
use_api_sync: bool = False,
timeout_seconds: OptionalNullable[float] = UNSET,
) -> Any:
"""Execute a workflow and wait for its completion.

Args:
workflow_identifier: The workflow name or ID.
input: Input parameters for the workflow
execution_id: Optional custom execution ID
deployment_name: Name of the deployment to route this execution to
custom_tracing_attributes: Custom tracing attributes
polling_interval: Seconds between status checks when polling
max_attempts: Maximum number of polling attempts when polling (None for unlimited)
use_api_sync: Whether to use the API's built-in sync execution capability
timeout_seconds: Maximum time to wait in seconds when using API sync

Returns:
The workflow result directly

Raises:
TimeoutError: If max_attempts is reached and workflow is still running
RuntimeError: If workflow fails or terminates abnormally
"""
if use_api_sync:
# Use the API's built-in synchronous execution
response = self.execute_workflow(
workflow_identifier=workflow_identifier,
input=input,
execution_id=execution_id,
wait_for_result=True,
timeout_seconds=timeout_seconds,
custom_tracing_attributes=custom_tracing_attributes,
deployment_name=deployment_name,
)
return response.result
# Use polling method
execution = self.execute_workflow(
workflow_identifier=workflow_identifier,
input=input,
execution_id=execution_id,
custom_tracing_attributes=custom_tracing_attributes,
deployment_name=deployment_name,
)

# Wait for completion
final_execution = self._wait_for_workflow_completion(
execution.execution_id, polling_interval, max_attempts
)

return final_execution.result

def _wait_for_workflow_completion(
self,
execution_id: str,
polling_interval: int = 5,
max_attempts: Optional[int] = None,
) -> models.WorkflowExecutionResponse:
"""Wait for a workflow to complete by polling its status.

Args:
execution_id: Execution ID of the workflow
polling_interval: Seconds between status checks
max_attempts: Maximum number of polling attempts (None for unlimited)

Returns:
WorkflowExecutionResponse with the final execution details

Raises:
TimeoutError: If max_attempts is reached and workflow is still running
RuntimeError: If workflow fails or terminates abnormally
"""
attempts = 0
while True:
response = self.executions.get_workflow_execution(execution_id=execution_id)

if response.status != "RUNNING":
if response.status == "COMPLETED":
return response
raise RuntimeError(f"Workflow failed with status: {response.status}")

attempts += 1
if max_attempts is not None and attempts >= max_attempts:
raise TimeoutError(
f"Workflow is still running after {max_attempts} polling attempts"
)

time.sleep(polling_interval)

async def execute_workflow_and_wait_async(
self,
workflow_identifier: str,
input: OptionalNullable[Dict[str, Any]] = UNSET,
execution_id: OptionalNullable[str] = UNSET,
deployment_name: OptionalNullable[str] = UNSET,
custom_tracing_attributes: OptionalNullable[Dict[str, str]] = UNSET,
polling_interval: int = 5,
max_attempts: Optional[int] = None,
use_api_sync: bool = False,
timeout_seconds: OptionalNullable[float] = UNSET,
) -> Any:
"""Execute a workflow and wait for its completion (async version).

Args:
workflow_identifier: The workflow name or ID.
input: Input parameters for the workflow
execution_id: Optional custom execution ID
deployment_name: Name of the deployment to route this execution to
custom_tracing_attributes: Custom tracing attributes
polling_interval: Seconds between status checks when polling
max_attempts: Maximum number of polling attempts when polling (None for unlimited)
use_api_sync: Whether to use the API's built-in sync execution capability
timeout_seconds: Maximum time to wait in seconds when using API sync

Returns:
The workflow result directly

Raises:
TimeoutError: If max_attempts is reached and workflow is still running
RuntimeError: If workflow fails or terminates abnormally
"""
if use_api_sync:
# Use the API's built-in synchronous execution
response = await self.execute_workflow_async(
workflow_identifier=workflow_identifier,
input=input,
execution_id=execution_id,
wait_for_result=True,
timeout_seconds=timeout_seconds,
custom_tracing_attributes=custom_tracing_attributes,
deployment_name=deployment_name,
)
return response.result

# Use polling method
execution = await self.execute_workflow_async(
workflow_identifier=workflow_identifier,
input=input,
execution_id=execution_id,
custom_tracing_attributes=custom_tracing_attributes,
deployment_name=deployment_name,
)

# Wait for completion
final_execution = await self._wait_for_workflow_completion_async(
execution.execution_id, polling_interval, max_attempts
)

return final_execution.result

async def _wait_for_workflow_completion_async(
self,
execution_id: str,
polling_interval: int = 5,
max_attempts: Optional[int] = None,
) -> models.WorkflowExecutionResponse:
"""Wait for a workflow to complete by polling its status (async version).

Args:
execution_id: Execution ID of the workflow
polling_interval: Seconds between status checks
max_attempts: Maximum number of polling attempts (None for unlimited)

Returns:
WorkflowExecutionResponse with the final execution details

Raises:
TimeoutError: If max_attempts is reached and workflow is still running
RuntimeError: If workflow fails or terminates abnormally
"""
attempts = 0
while True:
response = await self.executions.get_workflow_execution_async(
execution_id=execution_id
)

if response.status != "RUNNING":
if response.status == "COMPLETED":
return response
raise RuntimeError(f"Workflow failed with status: {response.status}")

attempts += 1
if max_attempts is not None and attempts >= max_attempts:
raise TimeoutError(
f"Workflow is still running after {max_attempts} polling attempts"
)

await asyncio.sleep(polling_interval)

# endregion sdk-class-body

def get_workflows(
self,
*,
Expand Down