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
1 change: 1 addition & 0 deletions docs/wayflowcore/source/core/api/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ API Reference
Agents <agent>
Agent Server <agentserver>
Embedding Models <embeddingmodels>
Retries <retries>
Context Providers <contextproviders>
Execution Interrupts <interrupts>
PromptTemplates <prompttemplate>
Expand Down
15 changes: 15 additions & 0 deletions docs/wayflowcore/source/core/api/retries.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Retries
=======

This page presents the API related to retry configuration for remote components in WayFlow.

Retry Policy
------------

.. _retrypolicy:
.. autoclass:: wayflowcore.retrypolicy.RetryPolicy

Retry Jitter
------------

.. autoclass:: wayflowcore.retrypolicy.RetryJitter
7 changes: 7 additions & 0 deletions docs/wayflowcore/source/core/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ WayFlow |current_version|
New features
^^^^^^^^^^^^

* **Configurable retry policies for remote components**

Added the ``RetryPolicy`` object to configure retries, backoff,
and request timeouts for components doing remote calls.

For usage details, see :doc:`the new retry configuration guide <howtoguides/howto_retry_configuration>`.

* **Custom TLS certificates for OpenAI-compatible models:**

:ref:`OpenAICompatibleModel <openaicompatiblemodel>` and :ref:`OpenAICompatibleEmbeddingModel <openaicompatibleembeddingmodel>`
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Copyright © 2026 Oracle and/or its affiliates.
#
# This software is under the Apache License 2.0
# (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License
# (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option.

# isort:skip_file
# fmt: off
# mypy: ignore-errors
# docs-title: Code Example - How to Configure Retries on Remote Components

# .. start-##_Create_a_retry_policy
from wayflowcore.retrypolicy import RetryPolicy

retry_policy = RetryPolicy(
max_attempts=3,
request_timeout=20.0,
initial_retry_delay=1.0,
max_retry_delay=8.0,
backoff_factor=2.0,
jitter="full_and_equal_for_throttle",
)
# .. end-##_Create_a_retry_policy

# .. start-##_Configure_a_remote_LLM
from wayflowcore.models import OpenAICompatibleModel

llm = OpenAICompatibleModel(
model_id="my-model",
base_url="https://example.com",
retry_policy=retry_policy,
)
# .. end-##_Configure_a_remote_LLM

# .. start-##_Configure_remote_steps_and_tools
from wayflowcore.steps import ApiCallStep
from wayflowcore.tools import RemoteTool

api_step = ApiCallStep(
name="fetch_order_step",
url="https://example.com/orders",
method="POST",
retry_policy=retry_policy,
)

remote_tool = RemoteTool(
name="fetch_order",
description="Fetch an order from a remote API.",
url="https://example.com/orders/{{ order_id }}",
method="GET",
retry_policy=retry_policy,
)
# .. end-##_Configure_remote_steps_and_tools

# .. start-##_Configure_remote_agents_and_MCP_transports
from wayflowcore.a2a.a2aagent import A2AAgent, A2AConnectionConfig
from wayflowcore.mcp import StreamableHTTPTransport
from wayflowcore.models.ociclientconfig import OCIClientConfigWithInstancePrincipal
from wayflowcore.ociagent import OciAgent

a2a_agent = A2AAgent(
agent_url="https://example.com/a2a",
connection_config=A2AConnectionConfig(verify=False, retry_policy=retry_policy),
)

oci_agent = OciAgent(
agent_endpoint_id="ocid1.agentendpoint.oc1..example",
client_config=OCIClientConfigWithInstancePrincipal(service_endpoint="https://example.com"),
retry_policy=retry_policy,
)

transport = StreamableHTTPTransport(
url="https://example.com/mcp",
retry_policy=retry_policy,
)
# .. end-##_Configure_remote_agents_and_MCP_transports

# .. start-##_Export_config_to_Agent_Spec
from wayflowcore.agentspec import AgentSpecExporter

serialized_assistant = AgentSpecExporter().to_json(oci_agent)
# .. end-##_Export_config_to_Agent_Spec

# .. start-##_Load_Agent_Spec_config
from wayflowcore.agentspec import AgentSpecLoader

loaded_agent: OciAgent = AgentSpecLoader().load_json(serialized_assistant)
# .. end-##_Load_Agent_Spec_config
11 changes: 6 additions & 5 deletions docs/wayflowcore/source/core/code_examples/usecase_prbot.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ def local_get_pr_diff_tool(repo_dirpath: str) -> str:
Retrieves code diff with a git command given the
path to the repository root folder.
"""
import subprocess
import subprocess # nosec: documentation example invoking git locally

result = subprocess.run(
["git", "diff", "HEAD"],
capture_output=True,
cwd=repo_dirpath,
text=True,
)
) # nosec: documentation example invoking git locally
return result.stdout.strip()
# .. end-##_Define_the_tool_that_retrieves_the_PR_diff

Expand Down Expand Up @@ -177,10 +177,11 @@ def local_get_pr_diff_tool(repo_dirpath: str) -> str: # docs-skiprow
# .. end-##_Create_the_flow_that_retrieves_the_diff_of_a_PR

# .. start-##_Alternative_step_that_retrieves_the_PR_diff_through_an_API_call
from wayflowcore.retrypolicy import RetryPolicy
from wayflowcore.steps import ApiCallStep

# IO Variable Names
USER_PROVIDED_TOKEN_IO = "$user_provided_token"
USER_PROVIDED_TOKEN_IO = "$user_provided_token" # nosec: placeholder IO variable name
REPO_WORKSPACE_IO = "$repo_workspace"
REPO_SLUG_IO = "$repo_slug"
PULL_REQUEST_ID_IO = "$pull_request_id"
Expand All @@ -191,7 +192,7 @@ def local_get_pr_diff_tool(repo_dirpath: str) -> str: # docs-skiprow
method="GET",
headers={"Authorization": "Bearer {{token}}"},
ignore_bad_http_requests=False,
num_retry_on_bad_http_request=3,
retry_policy=RetryPolicy(max_attempts=2),
store_response=True,
input_mapping={
"token": USER_PROVIDED_TOKEN_IO,
Expand Down Expand Up @@ -548,7 +549,7 @@ def flatten_information(
),
headers={"Accept": "application/json", "Authorization": "Bearer {{token}}"},
ignore_bad_http_requests=False,
num_retry_on_bad_http_request=3,
retry_policy=RetryPolicy(max_attempts=2),
store_response=True,
input_mapping={
"token": USER_PROVIDED_TOKEN_IO,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"component_type": "OciAgent",
"id": "d3ec0b4c-ab23-4555-82e8-3dda8a831fb2",
"name": "oci_agent_5008210d__auto",
"description": "",
"metadata": {
"__metadata_info__": {}
},
"inputs": [],
"outputs": [],
"agent_endpoint_id": "ocid1.agentendpoint.oc1..example",
"client_config": {
"component_type": "OciClientConfigWithInstancePrincipal",
"id": "45384ec0-c3c7-4d55-a37e-f8e28d8027e5",
"name": "oci_client_config",
"description": null,
"metadata": {},
"service_endpoint": "https://example.com",
"auth_type": "INSTANCE_PRINCIPAL"
},
"retry_policy": {
"max_attempts": 3,
"request_timeout": 20.0,
"initial_retry_delay": 1.0,
"max_retry_delay": 8.0,
"backoff_factor": 2.0,
"jitter": "full_and_equal_for_throttle",
"service_error_retry_on_any_5xx": true,
"recoverable_statuses": {
"409": [],
"429": []
}
},
"agentspec_version": "26.2.0"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
component_type: OciAgent
id: d3ec0b4c-ab23-4555-82e8-3dda8a831fb2
name: oci_agent_5008210d__auto
description: ''
metadata:
__metadata_info__: {}
inputs: []
outputs: []
agent_endpoint_id: ocid1.agentendpoint.oc1..example
client_config:
component_type: OciClientConfigWithInstancePrincipal
id: 45384ec0-c3c7-4d55-a37e-f8e28d8027e5
name: oci_client_config
description: null
metadata: {}
service_endpoint: https://example.com
auth_type: INSTANCE_PRINCIPAL
retry_policy:
max_attempts: 3
request_timeout: 20.0
initial_retry_delay: 1.0
max_retry_delay: 8.0
backoff_factor: 2.0
jitter: full_and_equal_for_throttle
service_error_retry_on_any_5xx: true
recoverable_statuses:
'409': []
'429': []
agentspec_version: 26.2.0
120 changes: 120 additions & 0 deletions docs/wayflowcore/source/core/howtoguides/howto_retry_configuration.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
.. _top-howtoretryconfiguration:

======================================================
How to Configure Retries on LLMs and Remote Components
======================================================

.. |python-icon| image:: ../../_static/icons/python-icon.svg
:width: 40px
:height: 40px

.. grid:: 2

.. grid-item-card:: |python-icon| Download Python Script
:link: ../end_to_end_code_examples/howto_retry_configuration.py
:link-alt: Retry configuration how-to script

Python script/notebook for this guide.

.. admonition:: Prerequisites

This guide assumes familiarity with:

- :doc:`LLM configuration <llm_from_different_providers>`
- :doc:`Using agents <agents>`
- :doc:`Doing remote API calls <howto_remote_tool_expired_token>`

WayFlow remote components now share the same :ref:`RetryPolicy <retrypolicy>` object.
You can use it to configure retry timing and per-attempt request timeouts consistently across
:ref:`LLMs <llmmodel>`, :ref:`embedding models <embeddingmodel>`,
:ref:`ApiCallStep <apicallstep>`, :ref:`RemoteTool <remotetool>`,
remote MCP transports such as :ref:`StreamableHTTPTransport <streamablehttptransport>`,
:ref:`OciAgent <ociagent>`, and :ref:`A2AAgent <a2aagent>`.


Create a Retry Policy
=====================

Start by defining a ``RetryPolicy`` with the retry behavior you want to reuse.

.. literalinclude:: ../code_examples/howto_retry_configuration.py
:language: python
:start-after: .. start-##_Create_a_retry_policy
:end-before: .. end-##_Create_a_retry_policy


Apply the Policy to Remote Components
=====================================

You can then pass the same retry policy to any supported remote component.

.. literalinclude:: ../code_examples/howto_retry_configuration.py
:language: python
:start-after: .. start-##_Configure_a_remote_LLM
:end-before: .. end-##_Configure_a_remote_LLM

.. literalinclude:: ../code_examples/howto_retry_configuration.py
:language: python
:start-after: .. start-##_Configure_remote_steps_and_tools
:end-before: .. end-##_Configure_remote_steps_and_tools

.. literalinclude:: ../code_examples/howto_retry_configuration.py
:language: python
:start-after: .. start-##_Configure_remote_agents_and_MCP_transports
:end-before: .. end-##_Configure_remote_agents_and_MCP_transports

WayFlow applies ``request_timeout`` per attempt. Retries are limited to transient failures such
as configured recoverable status codes, eligible ``5xx`` responses, and connection errors.
Authentication failures, validation failures, and TLS/certificate verification failures are not retried.


Agent Spec Exporting/Loading
============================

You can export a configuration that includes the retry policy to Agent Spec using the ``AgentSpecExporter``.

.. literalinclude:: ../code_examples/howto_retry_configuration.py
:language: python
:start-after: .. start-##_Export_config_to_Agent_Spec
:end-before: .. end-##_Export_config_to_Agent_Spec

Here is what the **Agent Spec representation will look like ↓**

.. collapse:: Click here to see the assistant configuration.

.. tabs::

.. tab:: JSON

.. literalinclude:: ../config_examples/howto_retry_configuration.json
:language: json

.. tab:: YAML

.. literalinclude:: ../config_examples/howto_retry_configuration.yaml
:language: yaml

You can then load the configuration back with the ``AgentSpecLoader``.

.. literalinclude:: ../code_examples/howto_retry_configuration.py
:language: python
:start-after: .. start-##_Load_Agent_Spec_config
:end-before: .. end-##_Load_Agent_Spec_config


Next steps
==========

Now that you have learned how to configure retries on remote components, you may proceed to
:doc:`How to Use OCI Generative AI Agents <howto_ociagent>` or
:doc:`How to Connect to A2A Agents <howto_a2aagent>`.


Full code
=========

Click on the card at the :ref:`top of this page <top-howtoretryconfiguration>` to download the full code for this guide or copy the code below.

.. literalinclude:: ../end_to_end_code_examples/howto_retry_configuration.py
:language: python
:linenos:
1 change: 1 addition & 0 deletions docs/wayflowcore/source/core/howtoguides/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ These how-to guides demonstrate how to use the main features to create and custo

Install and Use Ollama <installing_ollama>
Specify the Generation Configuration when Using LLMs <generation_config>
Configure Retries on LLMs and Remote Components <howto_retry_configuration>
Use LLM from Different LLM Sources and Providers <llm_from_different_providers>
Handle long context with agents <howto_long_context>

Expand Down
2 changes: 2 additions & 0 deletions wayflowcore/src/wayflowcore/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from .conversation import Conversation
from .flow import Flow
from .messagelist import Message, MessageList, MessageType
from .retrypolicy import RetryPolicy
from .steps.step import Step
from .swarm import Swarm
from .tools import Tool, tool
Expand All @@ -21,6 +22,7 @@
"Message",
"MessageList",
"MessageType",
"RetryPolicy",
"Step",
"Swarm",
"tool",
Expand Down
Loading