├── VERSION ├── wayflowcore ├── src │ └── wayflowcore │ │ ├── py.typed │ │ ├── a2a │ │ └── __init__.py │ │ ├── _utils │ │ ├── __init__.py │ │ ├── print.py │ │ ├── dataclass_utils.py │ │ ├── singleton.py │ │ └── io_utils.py │ │ ├── executors │ │ ├── __init__.py │ │ ├── _events │ │ │ └── __init__.py │ │ ├── interrupts │ │ │ └── __init__.py │ │ ├── _ociagentconversation.py │ │ ├── _executor.py │ │ └── _a2aagentconversation.py │ │ ├── tracing │ │ ├── __init__.py │ │ ├── opentelemetry │ │ │ └── __init__.py │ │ └── spanexporter.py │ │ ├── agentserver │ │ ├── openairesponses │ │ │ ├── models │ │ │ │ └── __init__.py │ │ │ ├── routes │ │ │ │ └── __init__.py │ │ │ └── services │ │ │ │ ├── __init__.py │ │ │ │ └── service.py │ │ ├── __init__.py │ │ └── app.py │ │ ├── agentconversation.py │ │ ├── flowconversation.py │ │ ├── agentspec │ │ ├── components │ │ │ ├── datastores │ │ │ │ ├── entity.py │ │ │ │ ├── datastore.py │ │ │ │ ├── relational_datastore.py │ │ │ │ ├── nodes │ │ │ │ │ └── __init__.py │ │ │ │ ├── inmemory_datastore.py │ │ │ │ └── __init__.py │ │ │ ├── tools.py │ │ │ └── _utils.py │ │ └── __init__.py │ │ ├── steps │ │ ├── variablesteps │ │ │ └── __init__.py │ │ ├── textextractionstep │ │ │ └── __init__.py │ │ └── datastoresteps │ │ │ └── __init__.py │ │ ├── models │ │ ├── openaiapitype.py │ │ ├── _openaihelpers │ │ │ └── __init__.py │ │ └── __init__.py │ │ ├── serialization │ │ ├── __init__.py │ │ └── stepserialization.py │ │ ├── events │ │ └── __init__.py │ │ ├── warnings.py │ │ ├── embeddingmodels │ │ ├── __init__.py │ │ ├── vllmmodel.py │ │ ├── ollamamodel.py │ │ └── embeddingmodel.py │ │ ├── __init__.py │ │ ├── tools │ │ ├── __init__.py │ │ └── toolbox.py │ │ ├── contextproviders │ │ ├── __init__.py │ │ └── constantcontextprovider.py │ │ ├── mcp │ │ └── __init__.py │ │ ├── templates │ │ ├── __init__.py │ │ └── nativetemplates.py │ │ ├── cli │ │ └── __init__.py │ │ ├── datastore │ │ └── __init__.py │ │ ├── _metadata.py │ │ ├── evaluation │ │ ├── __init__.py │ │ └── conversationscorer.py │ │ ├── component.py │ │ ├── LICENSE_UPL.txt │ │ ├── idgeneration.py │ │ └── stepdescription.py ├── tests_fuzz │ └── TIMEOUT ├── MANIFEST.in ├── tests │ ├── configs │ │ └── test_data │ │ │ ├── image.png │ │ │ ├── oracle_logo.png │ │ │ └── oracle_logo.jpeg │ ├── __init__.py │ ├── a2a │ │ └── __init__.py │ ├── agentspec │ │ ├── __init__.py │ │ ├── configs │ │ │ ├── a2aagent_1.yaml │ │ │ ├── ociagent_1.yaml │ │ │ ├── agent_5.yaml │ │ │ ├── agent_4.yaml │ │ │ ├── mcp_agent.yaml │ │ │ ├── agent_1.yaml │ │ │ └── legacy │ │ │ │ └── mcp_agent.yaml │ │ ├── test_import_package.py │ │ ├── test_extended_map_node.py │ │ ├── test_plugin_datastore_nodes.py │ │ ├── test_startnode.py │ │ ├── test_plugins.py │ │ ├── test_template_node.py │ │ ├── test_partial_serde.py │ │ └── test_mapnode.py │ ├── datastores │ │ ├── __init__.py │ │ └── entities.json │ ├── events │ │ └── __init__.py │ ├── mcptools │ │ └── __init__.py │ ├── models │ │ └── __init__.py │ ├── planner │ │ └── __init__.py │ ├── security │ │ ├── __init__.py │ │ └── check_undefined_logger.py │ ├── tracing │ │ ├── __init__.py │ │ ├── spans │ │ │ ├── __init__.py │ │ │ └── conftest.py │ │ └── opentelemetry │ │ │ ├── __init__.py │ │ │ ├── conftest.py │ │ │ └── otel_server_utils.py │ ├── agentserver │ │ ├── __init__.py │ │ └── agent_registry.py │ ├── integration │ │ ├── __init__.py │ │ ├── steps │ │ │ ├── __init__.py │ │ │ ├── test_constant_values_step.py │ │ │ └── test_steps.py │ │ └── tools │ │ │ └── __init__.py │ ├── serialization │ │ └── __init__.py │ ├── tools │ │ └── __init__.py │ ├── test_version.py │ ├── run_tests.sh │ ├── _utils │ │ ├── test_singleton.py │ │ └── faker.py │ ├── test_assistantexecutionstate.py │ ├── testhelpers │ │ ├── __init__.py │ │ └── humanproxy.py │ └── test_idgenerator.py ├── constraints │ ├── constraints.txt │ └── constraints_dev.txt ├── pyproject.toml ├── install-dev.sh ├── install.sh ├── nosec_ignore.csv ├── tox.ini ├── dev_scripts │ └── openai-models-gen │ │ └── generate_apis.sh ├── requirements-dev.txt └── testing_scripts │ └── run_repl_from_serialized_graph.py ├── .gitlab ├── CHANGELOG.md ├── merge_request_templates │ └── default.md ├── jobs │ ├── schedule_regression.yml │ ├── schedule_mergegate.yml │ └── templates │ │ ├── get_merge_request_id.yml │ │ └── get_private_branch.yml └── README.md ├── docs └── wayflowcore │ ├── source │ ├── _static │ │ ├── favicon.png │ │ ├── img │ │ │ ├── examples.svg │ │ │ ├── flexibility.svg │ │ │ └── extensibility.svg │ │ ├── icons │ │ │ ├── github-icon.svg │ │ │ └── python-icon.svg │ │ └── announcement.js │ ├── core │ │ ├── api │ │ │ ├── component.rst │ │ │ ├── warnings.rst │ │ │ ├── a2a.rst │ │ │ ├── variables.rst │ │ │ ├── contextproviders.rst │ │ │ ├── agentserver.rst │ │ │ ├── embeddingmodels.rst │ │ │ ├── index.rst │ │ │ ├── interrupts.rst │ │ │ ├── serialization.rst │ │ │ ├── conversation.rst │ │ │ ├── prompttemplate.rst │ │ │ ├── events.rst │ │ │ ├── agent.rst │ │ │ ├── evaluation.rst │ │ │ └── tracing.rst │ │ ├── _static │ │ │ ├── usecases │ │ │ │ └── agentix.zip │ │ │ ├── howto │ │ │ │ ├── example_document.pdf │ │ │ │ ├── assistant_evaluator.png │ │ │ │ ├── conversation_evaluator.png │ │ │ │ └── example_document.md │ │ │ └── ollama │ │ │ │ ├── ollama_frontpage.png │ │ │ │ ├── ollama_extract1_2.png │ │ │ │ ├── ollama_extract2_2.png │ │ │ │ ├── ollama_in_terminal.png │ │ │ │ ├── ollama_install1_3.png │ │ │ │ ├── ollama_install2_3.png │ │ │ │ └── ollama_install3_3.png │ │ ├── config_examples │ │ │ ├── howto_imagecontent.yaml │ │ │ ├── howto_ociagent.yaml │ │ │ ├── howto_serialize_conversations.yaml │ │ │ ├── howto_a2aagent.yaml │ │ │ ├── howto_io_descriptors.yaml │ │ │ ├── howto_imagecontent.json │ │ │ ├── howto_ociagent.json │ │ │ ├── howto_serialize_conversations.json │ │ │ ├── howto_io_descriptors.json │ │ │ ├── howto_a2aagent.json │ │ │ ├── howto_async.yaml │ │ │ ├── tutorial_agent.yaml │ │ │ ├── howto_async.json │ │ │ └── tutorial_agent.json │ │ ├── misc │ │ │ └── type_casting_rules.rst │ │ ├── code_examples │ │ │ ├── quickstart.py │ │ │ ├── howto_a2aagent.py │ │ │ ├── example_ociuserauthentication.py │ │ │ └── howto_tool_from_flow.py │ │ ├── _components │ │ │ └── llm_config_tabs.rst │ │ ├── rfcs-template.rst │ │ └── howtoguides │ │ │ └── create_a_tool_from_a_flow.rst │ ├── _templates │ │ ├── core.html │ │ ├── layout.html │ │ └── landing-page.html │ └── _ext │ │ └── __init__.py │ ├── requirements-docs.txt │ ├── run_all_code_examples.sh │ ├── Makefile │ ├── make.bat │ └── README ├── .gitlab-ci.yml ├── install-all-dev.sh ├── pyproject.toml ├── clean-install-dev.sh ├── requirements-dev.txt ├── SECURITY.md └── LICENSE-UPL.txt /VERSION: -------------------------------------------------------------------------------- 1 | 26.1.0.dev0 2 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/py.typed: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /wayflowcore/tests_fuzz/TIMEOUT: -------------------------------------------------------------------------------- 1 | 30m 2 | -------------------------------------------------------------------------------- /wayflowcore/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include src/wayflowcore/LICENSE-APACHE.txt 2 | include src/wayflowcore/LICENSE-UPL.txt 3 | -------------------------------------------------------------------------------- /.gitlab/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [1.0.0] - 2025-07-15 4 | ### Added 5 | - Initial version of the GitLab CI Integration. 6 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/_static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/wayflow/HEAD/docs/wayflowcore/source/_static/favicon.png -------------------------------------------------------------------------------- /wayflowcore/tests/configs/test_data/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/wayflow/HEAD/wayflowcore/tests/configs/test_data/image.png -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/api/component.rst: -------------------------------------------------------------------------------- 1 | Component 2 | ========= 3 | 4 | .. _component: 5 | .. autoclass:: wayflowcore.component.Component 6 | -------------------------------------------------------------------------------- /wayflowcore/tests/configs/test_data/oracle_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/wayflow/HEAD/wayflowcore/tests/configs/test_data/oracle_logo.png -------------------------------------------------------------------------------- /wayflowcore/tests/configs/test_data/oracle_logo.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/wayflow/HEAD/wayflowcore/tests/configs/test_data/oracle_logo.jpeg -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/_static/usecases/agentix.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/wayflow/HEAD/docs/wayflowcore/source/core/_static/usecases/agentix.zip -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/_static/howto/example_document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/wayflow/HEAD/docs/wayflowcore/source/core/_static/howto/example_document.pdf -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/_static/ollama/ollama_frontpage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/wayflow/HEAD/docs/wayflowcore/source/core/_static/ollama/ollama_frontpage.png -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/_static/howto/assistant_evaluator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/wayflow/HEAD/docs/wayflowcore/source/core/_static/howto/assistant_evaluator.png -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/_static/ollama/ollama_extract1_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/wayflow/HEAD/docs/wayflowcore/source/core/_static/ollama/ollama_extract1_2.png -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/_static/ollama/ollama_extract2_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/wayflow/HEAD/docs/wayflowcore/source/core/_static/ollama/ollama_extract2_2.png -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/_static/ollama/ollama_in_terminal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/wayflow/HEAD/docs/wayflowcore/source/core/_static/ollama/ollama_in_terminal.png -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/_static/ollama/ollama_install1_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/wayflow/HEAD/docs/wayflowcore/source/core/_static/ollama/ollama_install1_3.png -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/_static/ollama/ollama_install2_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/wayflow/HEAD/docs/wayflowcore/source/core/_static/ollama/ollama_install2_3.png -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/_static/ollama/ollama_install3_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/wayflow/HEAD/docs/wayflowcore/source/core/_static/ollama/ollama_install3_3.png -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/_static/howto/conversation_evaluator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/wayflow/HEAD/docs/wayflowcore/source/core/_static/howto/conversation_evaluator.png -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/api/warnings.rst: -------------------------------------------------------------------------------- 1 | Warnings 2 | ======== 3 | 4 | This page presents all warning classes in WayFlow. 5 | 6 | .. _securitywarning: 7 | .. autoclass:: wayflowcore.warnings.SecurityWarning 8 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/_templates/core.html: -------------------------------------------------------------------------------- 1 | {% extends "!layout.html" %} 2 | 3 | {%- block css %} 4 | {{ super() }} 5 | 6 | {% endblock %} 7 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/api/a2a.rst: -------------------------------------------------------------------------------- 1 | A2A related classes 2 | =================== 3 | 4 | .. autoclass:: wayflowcore.a2a.a2aagent.A2AConnectionConfig 5 | 6 | .. autoclass:: wayflowcore.a2a.a2aagent.A2ASessionParameters 7 | 8 | A2A Agent 9 | --------- 10 | 11 | refer :ref:`A2AAgent ` 12 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | image : $GITLAB_CI_CD_IMAGE 2 | include: 3 | - local: '.gitlab/jobs/templates/get_private_branch.yml' 4 | - local: '.gitlab/jobs/templates/get_merge_request_id.yml' 5 | - local: '.gitlab/jobs/schedule_mergegate.yml' 6 | - local: '.gitlab/jobs/schedule_regression.yml' 7 | 8 | stages: 9 | - trigger -------------------------------------------------------------------------------- /wayflowcore/constraints/constraints.txt: -------------------------------------------------------------------------------- 1 | deprecated==1.2.18 2 | jinja2==3.1.6 3 | jq==1.8.0 4 | json_repair==0.30.0 5 | numpy==1.26.4 6 | pandas==2.2.3 7 | PyYAML==6.0.3 8 | pydantic==2.11.3 9 | httpx==0.28.1 10 | mcp==1.17.0 11 | pyagentspec==25.4.1 12 | opentelemetry-api==1.36.0 13 | opentelemetry-sdk==1.36.0 14 | -------------------------------------------------------------------------------- /wayflowcore/tests/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | -------------------------------------------------------------------------------- /wayflowcore/tests/a2a/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/_ext/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | -------------------------------------------------------------------------------- /wayflowcore/tests/agentspec/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | -------------------------------------------------------------------------------- /wayflowcore/tests/datastores/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | -------------------------------------------------------------------------------- /wayflowcore/tests/events/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | -------------------------------------------------------------------------------- /wayflowcore/tests/mcptools/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | -------------------------------------------------------------------------------- /wayflowcore/tests/models/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | -------------------------------------------------------------------------------- /wayflowcore/tests/planner/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | -------------------------------------------------------------------------------- /wayflowcore/tests/security/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | -------------------------------------------------------------------------------- /wayflowcore/tests/tracing/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/a2a/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | -------------------------------------------------------------------------------- /wayflowcore/tests/agentserver/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | -------------------------------------------------------------------------------- /wayflowcore/tests/integration/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | -------------------------------------------------------------------------------- /wayflowcore/tests/serialization/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | -------------------------------------------------------------------------------- /wayflowcore/tests/tools/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2024, 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | -------------------------------------------------------------------------------- /wayflowcore/tests/tracing/spans/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/_utils/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/executors/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/tracing/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | -------------------------------------------------------------------------------- /wayflowcore/tests/integration/steps/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | -------------------------------------------------------------------------------- /wayflowcore/tests/integration/tools/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | -------------------------------------------------------------------------------- /wayflowcore/tests/tracing/opentelemetry/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/executors/_events/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | -------------------------------------------------------------------------------- /wayflowcore/constraints/constraints_dev.txt: -------------------------------------------------------------------------------- 1 | deprecated==1.2.18 2 | jinja2==3.1.6 3 | jq==1.8.0 4 | json_repair==0.30.0 5 | numpy==1.26.4 6 | pandas==2.2.3 7 | PyYAML==6.0.3 8 | pydantic==2.11.3 9 | httpx==0.28.1 10 | mcp==1.17.0 11 | pyagentspec==26.1.0.dev4 # Main branch of pyagentspec 12 | opentelemetry-api==1.36.0 13 | opentelemetry-sdk==1.36.0 14 | -------------------------------------------------------------------------------- /wayflowcore/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = [ 3 | "setuptools<72.0.0", 4 | "wheel", 5 | # setuptools-scm lets us include all necessary files (e.g. .pyx files) in the source 6 | # distribution (sdist) without needing a MANIFEST.in file. 7 | "setuptools-scm == 7.1.0", 8 | ] 9 | build-backend = "setuptools.build_meta" 10 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/agentserver/openairesponses/models/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/_templates/layout.html: -------------------------------------------------------------------------------- 1 | {% if (pagename is defined and pagename is not none and 'index' == pagename) %} 2 | {% extends "landing-page.html" %} 3 | {% else %} 4 | {% extends "!layout.html" %} 5 | {% endif %} 6 | 7 | {% block scripts %} 8 | {{ super() }} 9 | 10 | {% endblock %} 11 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/agentconversation.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from wayflowcore.executors._agentconversation import * # fmt: off 8 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/flowconversation.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | 8 | from wayflowcore.executors._flowconversation import * # fmt: off 9 | -------------------------------------------------------------------------------- /.gitlab/merge_request_templates/default.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/_static/img/examples.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /wayflowcore/install-dev.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright (C) 2024, 2025 Oracle and/or its affiliates. 4 | # 5 | # This software is under the Apache License 2.0 6 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 7 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 8 | 9 | source ../_installation_tools.sh 10 | 11 | upgrade_pip_or_uv 12 | 13 | install_requirements_dev 14 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/agentserver/openairesponses/routes/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from .api import create_openai_responses_api_routes 8 | 9 | __all__ = ["create_openai_responses_api_routes"] 10 | -------------------------------------------------------------------------------- /wayflowcore/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright (C) 2024, 2025 Oracle and/or its affiliates. 4 | # 5 | # This software is under the Apache License 2.0 6 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 7 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 8 | 9 | source ../_installation_tools.sh 10 | 11 | upgrade_pip_or_uv 12 | 13 | install_with_pip_or_uv -e .[oci] -c constraints/constraints.txt 14 | -------------------------------------------------------------------------------- /install-all-dev.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright (c) 2024, 2025 Oracle and/or its affiliates. 4 | # 5 | # This software is under the Apache License 2.0 6 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 7 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 8 | 9 | source ./_installation_tools.sh 10 | 11 | upgrade_pip_or_uv 12 | 13 | install_requirements_dev 14 | 15 | install_dev_python_package wayflowcore 16 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/agentspec/components/datastores/entity.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from pyagentspec.property import Property 8 | 9 | # Entity is just an alias for ObjectProperty 10 | PluginEntity = Property 11 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/agentspec/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from .agentspecexporter import AgentSpecExporter 8 | from .runtimeloader import AgentSpecLoader 9 | 10 | __all__ = [ 11 | "AgentSpecExporter", 12 | "AgentSpecLoader", 13 | ] 14 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/tracing/opentelemetry/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from .spanprocessor import OtelBatchSpanProcessor, OtelSimpleSpanProcessor 8 | 9 | __all__ = [ 10 | "OtelSimpleSpanProcessor", 11 | "OtelBatchSpanProcessor", 12 | ] 13 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/api/variables.rst: -------------------------------------------------------------------------------- 1 | Variables 2 | ========= 3 | 4 | This page presents all APIs and classes related to variables in WayFlow. 5 | 6 | .. _variable: 7 | .. autoclass:: wayflowcore.variable.Variable 8 | 9 | .. _variablewriteoperation: 10 | .. autoclass:: wayflowcore.variable.VariableWriteOperation 11 | 12 | .. autoclass:: wayflowcore.steps.variablesteps.variablereadstep.VariableReadStep 13 | :noindex: 14 | 15 | .. autoclass:: wayflowcore.steps.variablesteps.variablewritestep.VariableWriteStep 16 | :noindex: 17 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/steps/variablesteps/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from .variablereadstep import VariableReadStep 8 | from .variablewritestep import VariableWriteStep 9 | 10 | __all__ = [ 11 | "VariableReadStep", 12 | "VariableWriteStep", 13 | ] 14 | -------------------------------------------------------------------------------- /docs/wayflowcore/requirements-docs.txt: -------------------------------------------------------------------------------- 1 | sphinx==6.1 2 | sphinx-substitution-extensions==2022.2.16 3 | sphinx-tabs==3.4.5 4 | sphinx-copybutton==0.5.2 5 | pydata-sphinx-theme==0.16.1 6 | sphinx-argparse==0.5.2 7 | # These are added as newer versions require sphinx>5.0, and pip doesn't resolve to older versions correctly 8 | sphinxcontrib-applehelp<1.0.8 9 | sphinxcontrib-devhelp<1.0.6 10 | sphinxcontrib-htmlhelp<2.0.5 11 | sphinxcontrib.serializinghtml<1.1.10 12 | sphinxcontrib.qthelp<1.0.7 13 | sphinx_toolbox<=3.8.0 14 | 15 | -e ../../wayflowcore[oci] 16 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/api/contextproviders.rst: -------------------------------------------------------------------------------- 1 | Context Providers 2 | ================= 3 | 4 | Base classes 5 | ------------ 6 | 7 | .. _contextprovider: 8 | .. autoclass:: wayflowcore.contextproviders.contextprovider.ContextProvider 9 | 10 | Available Context Providers 11 | --------------------------- 12 | 13 | .. _toolcontextprovider: 14 | .. autoclass:: wayflowcore.contextproviders.toolcontextprovider.ToolContextProvider 15 | 16 | .. _flowcontextprovider: 17 | .. autoclass:: wayflowcore.contextproviders.flowcontextprovider.FlowContextProvider 18 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/agentserver/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from .server import A2AServer, OpenAIResponsesServer 8 | from .serverstorageconfig import ServerStorageConfig 9 | 10 | __all__ = [ 11 | "A2AServer", 12 | "OpenAIResponsesServer", 13 | "ServerStorageConfig", 14 | ] 15 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/steps/textextractionstep/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from .extractvaluefromjsonstep import ExtractValueFromJsonStep 8 | from .regexextractionstep import RegexExtractionStep 9 | 10 | __all__ = [ 11 | "ExtractValueFromJsonStep", 12 | "RegexExtractionStep", 13 | ] 14 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/agentserver/openairesponses/services/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from .service import OpenAIResponsesService 8 | from .wayflowservice import WayFlowOpenAIResponsesService 9 | 10 | __all__ = [ 11 | "OpenAIResponsesService", 12 | "WayFlowOpenAIResponsesService", 13 | ] 14 | -------------------------------------------------------------------------------- /docs/wayflowcore/run_all_code_examples.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright (C) 2024, 2025 Oracle and/or its affiliates. 4 | # 5 | # This software is under the Apache License 2.0 6 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 7 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 8 | 9 | set -e # we should crash this bash script as soon as a python script crashes 10 | 11 | find source/core/code_examples -type f -name '*.py' | while read file; do 12 | echo "Running code example: $file" 13 | python $file 14 | done 15 | -------------------------------------------------------------------------------- /wayflowcore/nosec_ignore.csv: -------------------------------------------------------------------------------- 1 | nosec_statement_id,code,ignore_explanation 2 | nosec0001,B105,the reported issue by pybandit that variables should not be named token is hard to comply with in this context as the variable refers to the usage report of a LLM that is counted in number of tokens 3 | nosec0002,B105,the reported issue by pybandit that variables should not be named token is hard to comply with in this context as the variable refers to the token-based authentication method for the OCI service 4 | nosec0003,B110,finalizers must not raise; we ignore normal cleanup errors during shutdown/garbage collection on purpose 5 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/_utils/print.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | 8 | class bcolors: 9 | HEADER = "\033[95m" 10 | OKBLUE = "\033[94m" 11 | OKCYAN = "\033[96m" 12 | OKGREEN = "\033[92m" 13 | WARNING = "\033[93m" 14 | FAIL = "\033[91m" 15 | ENDC = "\033[0m" 16 | BOLD = "\033[1m" 17 | UNDERLINE = "\033[4m" 18 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/models/openaiapitype.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from enum import Enum 8 | 9 | 10 | class OpenAIAPIType(str, Enum): 11 | """ 12 | Enumeration of OpenAI API Types. 13 | 14 | chat_completions: Chat Completions API 15 | responses: Responses API 16 | """ 17 | 18 | CHAT_COMPLETIONS = "chat_completions" 19 | RESPONSES = "responses" 20 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/config_examples/howto_imagecontent.yaml: -------------------------------------------------------------------------------- 1 | component_type: Agent 2 | id: 2fc0cb26-98db-4a53-869b-61587a784b1a 3 | name: agent_df87a3d8 4 | description: '' 5 | metadata: 6 | __metadata_info__: 7 | name: agent_df87a3d8 8 | description: '' 9 | inputs: [] 10 | outputs: [] 11 | llm_config: 12 | component_type: VllmConfig 13 | id: 16d7437d-b510-4599-b1d4-51e8418043c4 14 | name: GEMMA_MODEL_ID 15 | description: null 16 | metadata: 17 | __metadata_info__: {} 18 | default_generation_parameters: null 19 | url: GEMMA_API_URL 20 | model_id: GEMMA_MODEL_ID 21 | system_prompt: '' 22 | tools: [] 23 | agentspec_version: 25.4.1 24 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/serialization/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from .serializer import ( 8 | autodeserialize, 9 | deserialize, 10 | deserialize_from_dict, 11 | serialize, 12 | serialize_to_dict, 13 | ) 14 | 15 | __all__ = [ 16 | "autodeserialize", 17 | "deserialize", 18 | "deserialize_from_dict", 19 | "serialize", 20 | "serialize_to_dict", 21 | ] 22 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/config_examples/howto_ociagent.yaml: -------------------------------------------------------------------------------- 1 | component_type: OciAgent 2 | id: be5b6589 3 | name: oci_agent_be5b6589 4 | description: '' 5 | metadata: 6 | __metadata_info__: 7 | name: oci_agent_be5b6589 8 | description: '' 9 | inputs: [] 10 | outputs: [] 11 | agent_endpoint_id: AGENT_ENDPOINT 12 | client_config: 13 | component_type: OciClientConfigWithApiKey 14 | id: ceb3acb1-d2c2-4aed-8f4e-c1cd24daa40c 15 | name: oci_client_config 16 | description: null 17 | metadata: {} 18 | service_endpoint: OCIGENAI_ENDPOINT 19 | auth_type: API_KEY 20 | auth_profile: DEFAULT 21 | auth_file_location: ~/.oci/config 22 | agentspec_version: 25.4.1 23 | -------------------------------------------------------------------------------- /wayflowcore/tests/tracing/opentelemetry/conftest.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | import pytest 8 | 9 | from .otel_server_utils import _start_otel_server 10 | 11 | OTEL_SERVER_PORT = 4318 12 | 13 | 14 | @pytest.fixture(scope="session") 15 | def otel_server(): 16 | process, url = _start_otel_server(host="localhost", port=OTEL_SERVER_PORT) 17 | yield url 18 | process.kill() 19 | process.wait() 20 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/events/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from .event import Event 8 | from .eventlistener import ( 9 | EventListener, 10 | get_event_listeners, 11 | record_event, 12 | register_event_listeners, 13 | ) 14 | 15 | __all__ = [ 16 | "Event", 17 | "EventListener", 18 | "get_event_listeners", 19 | "record_event", 20 | "register_event_listeners", 21 | ] 22 | -------------------------------------------------------------------------------- /wayflowcore/tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py310,py311,py312,py313 3 | [testenv] 4 | skip_install = true 5 | deps = 6 | ; Requirements 7 | -r requirements-dev.txt 8 | ; Root Requirements 9 | -r ../requirements-dev.txt 10 | ; --- Conditional Dependencies --- 11 | ; Add 'exceptiongroup' only for py311, py312, py313 12 | {py311,py312,py313}: exceptiongroup 13 | commands = 14 | sh tests/run_tests.sh 15 | 16 | allowlist_externals = 17 | sh 18 | 19 | [testenv:py310] 20 | basepython = python3.10 21 | 22 | [testenv:py311] 23 | basepython = python3.11 24 | 25 | [testenv:py312] 26 | basepython = python3.12 27 | 28 | [testenv:py313] 29 | basepython = python3.13 30 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/config_examples/howto_serialize_conversations.yaml: -------------------------------------------------------------------------------- 1 | component_type: Agent 2 | id: simple_assistant 3 | name: agent_0f75efc7 4 | description: '' 5 | metadata: 6 | __metadata_info__: 7 | name: agent_0f75efc7 8 | description: '' 9 | inputs: [] 10 | outputs: [] 11 | llm_config: 12 | component_type: VllmConfig 13 | id: 80c8028b-0dd6-4dc9-ad7d-a4860ef1b849 14 | name: LLAMA_MODEL_ID 15 | description: null 16 | metadata: 17 | __metadata_info__: {} 18 | default_generation_parameters: null 19 | url: LLAMA_API_URL 20 | model_id: LLAMA_MODEL_ID 21 | system_prompt: You are a helpful assistant. Be concise. 22 | tools: [] 23 | agentspec_version: 25.4.1 24 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/warnings.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | import warnings 8 | from functools import lru_cache 9 | from typing import Type 10 | 11 | 12 | class SecurityWarning(Warning): 13 | """Warning category for security related warnings.""" 14 | 15 | 16 | @lru_cache(maxsize=None) 17 | def warn_once(message: str, category: Type[Warning] = DeprecationWarning) -> None: 18 | warnings.warn(message, category=category, stacklevel=2) 19 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/config_examples/howto_a2aagent.yaml: -------------------------------------------------------------------------------- 1 | component_type: A2AAgent 2 | id: 5ba508ef-7cae-417a-9197-8f2aeee870b6 3 | name: a2a_agent_4311ebd5__auto 4 | description: '' 5 | metadata: 6 | __metadata_info__: {} 7 | inputs: [] 8 | outputs: [] 9 | agent_url: http:// 10 | connection_config: 11 | component_type: A2AConnectionConfig 12 | id: 7d7a7c03-616b-4740-bd8e-ebcfed45092c 13 | name: connection_config 14 | description: null 15 | metadata: {} 16 | timeout: 600.0 17 | headers: null 18 | verify: false 19 | key_file: null 20 | cert_file: null 21 | ssl_ca_cert: null 22 | session_parameters: 23 | timeout: 60.0 24 | poll_interval: 2.0 25 | max_retries: 5 26 | agentspec_version: 25.4.2 27 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/config_examples/howto_io_descriptors.yaml: -------------------------------------------------------------------------------- 1 | component_type: PluginInputMessageNode 2 | id: c7f3b49e-0db5-45b6-9a18-42c565230dc9 3 | name: step_7137de34 4 | description: '' 5 | metadata: 6 | __metadata_info__: {} 7 | inputs: 8 | - type: string 9 | title: username 10 | outputs: 11 | - description: the input value provided by the user 12 | type: string 13 | title: user_provided_input 14 | branches: 15 | - next 16 | input_mapping: 17 | unclear_var_name: username 18 | output_mapping: {} 19 | message_template: Hi {{unclear_var_name}}. How are you doing? 20 | rephrase: false 21 | llm_config: null 22 | component_plugin_name: NodesPlugin 23 | component_plugin_version: 25.4.0.dev0 24 | agentspec_version: 25.4.1 25 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/agentspec/components/datastores/datastore.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from pyagentspec import Component 8 | 9 | 10 | class PluginDatastore(Component, abstract=True): 11 | """Store and perform basic manipulations on collections of entities of various types. 12 | 13 | Provides an interface for listing, creating, deleting and updating collections. 14 | It also provides a way of describing the entities in this datastore. 15 | """ 16 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/misc/type_casting_rules.rst: -------------------------------------------------------------------------------- 1 | :orphan: 2 | 3 | .. csv-table:: 4 | :header: "From \ To", "String", "Number", "Integer", "Object", "Array", "Boolean", "Null" 5 | 6 | "**String**", "✅", "❌", "❌", "❌", "❌", "❌", "❌" 7 | "**Number**", "✅ json.dumps(value)", "✅", "✅ decimals truncated", "❌", "❌", "✅ value != 0", "❌" 8 | "**Integer**", "✅ json.dumps(value)", "✅", "✅", "❌", "❌", "✅ value != 0", "❌" 9 | "**Object**", "✅ json.dumps(value)", "❌", "❌", "✅", "❌", "❌", "❌" 10 | "**Array**", "✅ json.dumps(value)", "❌", "❌", "❌", "✅", "❌", "❌" 11 | "**Boolean**", "✅ json.dumps(value)", "✅ 1 if value else 0", "✅ 1 if value else 0", "❌", "❌", "✅", "❌" 12 | "**Null**", "✅ empty string", "❌", "❌", "❌", "❌", "❌", "✅" 13 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/models/_openaihelpers/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from ._api_processor import _APIProcessor 8 | from ._chatcompletions_processor import _ChatCompletionsAPIProcessor 9 | from ._responses_processor import _ResponsesAPIProcessor 10 | from ._utils import _property_to_openai_schema 11 | 12 | __all__ = [ 13 | "_APIProcessor", 14 | "_ChatCompletionsAPIProcessor", 15 | "_ResponsesAPIProcessor", 16 | "_property_to_openai_schema", 17 | ] 18 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/_templates/landing-page.html: -------------------------------------------------------------------------------- 1 | {% extends "!layout.html" %} 2 | 3 | {% set sidebars=None %} 4 | 5 | {%- block css %} 6 | {{ super() }} 7 | 8 | {% endblock %} 9 | 10 | {%- block content %} 11 | {{ super() }}{% endblock %} 12 | 13 | {% block scripts %} 14 | {{ super() }} 15 | 16 | {% endblock %} 17 | 18 | {%- block docs_body %} 19 | {{ super() }}{% endblock %} 20 | 21 | {% block docs_toc %}{% endblock %} 22 | 23 | {% block footer %} 24 | {{ super() }} 25 | {% endblock %} 26 | 27 | {% if theme_switcher %} 28 |
  • 29 |
  • 30 | {% endif %} 31 | -------------------------------------------------------------------------------- /wayflowcore/tests/agentspec/configs/a2aagent_1.yaml: -------------------------------------------------------------------------------- 1 | component_type: A2AAgent 2 | id: 220bf277-4e63-4431-9008-df59c00440f2 3 | name: Remote A2A Agent 4 | description: A client for connecting a remote agent using A2A 5 | metadata: 6 | __metadata_info__: {} 7 | inputs: [] 8 | outputs: [] 9 | agent_url: http:// 10 | connection_config: 11 | component_type: A2AConnectionConfig 12 | id: f6559597-b0b4-45b8-a9bc-b6aa33612819 13 | name: connection_config 14 | description: null 15 | metadata: {} 16 | timeout: 600.0 17 | headers: null 18 | verify: false 19 | key_file: null 20 | cert_file: null 21 | ssl_ca_cert: null 22 | session_parameters: 23 | timeout: 60.0 24 | poll_interval: 2.0 25 | max_retries: 5 26 | agentspec_version: 25.4.2 27 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/agentspec/components/datastores/relational_datastore.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from wayflowcore.agentspec.components.datastores.datastore import PluginDatastore 8 | 9 | 10 | class PluginRelationalDatastore(PluginDatastore, abstract=True): 11 | """A relational data store that supports querying data using SQL-like queries. 12 | 13 | This class extends the PluginDatastore class and adds support for querying 14 | data using SQL-like queries. 15 | """ 16 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/executors/interrupts/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from .executioninterrupt import ExecutionInterrupt, InterruptedExecutionStatus 8 | from .timeoutexecutioninterrupt import SoftTimeoutExecutionInterrupt 9 | from .tokenlimitexecutioninterrupt import SoftTokenLimitExecutionInterrupt 10 | 11 | __all__ = [ 12 | "ExecutionInterrupt", 13 | "InterruptedExecutionStatus", 14 | "SoftTimeoutExecutionInterrupt", 15 | "SoftTokenLimitExecutionInterrupt", 16 | ] 17 | -------------------------------------------------------------------------------- /wayflowcore/tests/test_version.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | import os.path 8 | from pathlib import Path 9 | 10 | import wayflowcore 11 | 12 | 13 | def test_version_match(): 14 | installed_version = wayflowcore.__version__ 15 | version_file_path = Path(os.path.dirname(__file__)).parent.parent / "VERSION" 16 | dev_version = version_file_path.read_text().strip() 17 | assert ( 18 | installed_version == dev_version 19 | ), f"Version mismatch: installed={installed_version}, dev={dev_version}" 20 | -------------------------------------------------------------------------------- /docs/wayflowcore/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal Makefile for Sphinx documentation 2 | # 3 | 4 | SPHINXOPTS ?= -W --keep-going 5 | SPHINXBUILD ?= sphinx-build 6 | SOURCEDIR = source 7 | BUILDDIR = build/html 8 | TAG = external 9 | 10 | # Put it first so that "make" without argument is like "make help". 11 | help: 12 | @echo "Please use 'make ' where is one of:" 13 | @echo " html to make HTML documentation" 14 | @echo " clean to clean up build directory" 15 | 16 | .PHONY: help html clean 17 | 18 | # Build HTML 19 | html: 20 | @$(SPHINXBUILD) -t $(TAG) -b html "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) 21 | @echo 22 | @echo "Build finished. The HTML pages are in $(BUILDDIR)." 23 | 24 | # Clean up build directory 25 | clean: 26 | - rm -rf "$(BUILDDIR)" 27 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/_utils/dataclass_utils.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from typing import Any, Callable 8 | 9 | 10 | def _required_attribute(attribute_name: str, attribute_type: Any) -> Callable[[], Any]: 11 | # Generic factory used to ensure that a field in a dataclass is provided 12 | def _inner_required_attribute() -> None: 13 | raise ValueError( 14 | f"An attribute named `{attribute_name}` of type `{attribute_type}` is required" 15 | ) 16 | 17 | return _inner_required_attribute 18 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/steps/datastoresteps/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from .datastorecreatestep import DatastoreCreateStep 8 | from .datastoredeletestep import DatastoreDeleteStep 9 | from .datastoreliststep import DatastoreListStep 10 | from .datastorequerystep import DatastoreQueryStep 11 | from .datastoreupdatestep import DatastoreUpdateStep 12 | 13 | __all__ = [ 14 | "DatastoreCreateStep", 15 | "DatastoreDeleteStep", 16 | "DatastoreUpdateStep", 17 | "DatastoreListStep", 18 | "DatastoreQueryStep", 19 | ] 20 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.isort] 2 | src_paths = [ 3 | "wayflowcore/src", 4 | "wayflowcore/tests", 5 | ] 6 | profile = "black" 7 | line_length = 100 8 | 9 | [tool.black] 10 | line-length = 100 11 | 12 | [tool.mypy] 13 | strict = true 14 | disable_error_code = [ 15 | "type-abstract", # https://stackoverflow.com/questions/48349054/how-do-you-annotate-the-type-of-an-abstract-class-with-mypy 16 | ] 17 | plugins = ['pydantic.mypy'] 18 | 19 | [[tool.mypy.overrides]] 20 | module = [ 21 | 'tests.*', 22 | 'setup', 23 | ] 24 | ignore_errors = true 25 | 26 | [[tool.mypy.overrides]] 27 | module = [ 28 | 'jq.*', 29 | 'IPython.*', 30 | 'sentence_transformers.*', 31 | 'fasta2a.*', 32 | ] 33 | ignore_missing_imports = true 34 | 35 | [tool.bandit.assert_used] 36 | skips = ["*/test_*.py", "**/tests/**", "**/code_examples/*.py"] 37 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/config_examples/howto_imagecontent.json: -------------------------------------------------------------------------------- 1 | { 2 | "component_type": "Agent", 3 | "id": "2fc0cb26-98db-4a53-869b-61587a784b1a", 4 | "name": "agent_df87a3d8", 5 | "description": "", 6 | "metadata": { 7 | "__metadata_info__": { 8 | "name": "agent_df87a3d8", 9 | "description": "" 10 | } 11 | }, 12 | "inputs": [], 13 | "outputs": [], 14 | "llm_config": { 15 | "component_type": "VllmConfig", 16 | "id": "16d7437d-b510-4599-b1d4-51e8418043c4", 17 | "name": "GEMMA_MODEL_ID", 18 | "description": null, 19 | "metadata": { 20 | "__metadata_info__": {} 21 | }, 22 | "default_generation_parameters": null, 23 | "url": "GEMMA_API_URL", 24 | "model_id": "GEMMA_MODEL_ID" 25 | }, 26 | "system_prompt": "", 27 | "tools": [], 28 | "agentspec_version": "25.4.1" 29 | } 30 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/config_examples/howto_ociagent.json: -------------------------------------------------------------------------------- 1 | { 2 | "component_type": "OciAgent", 3 | "id": "be5b6589", 4 | "name": "oci_agent_be5b6589", 5 | "description": "", 6 | "metadata": { 7 | "__metadata_info__": { 8 | "name": "oci_agent_be5b6589", 9 | "description": "" 10 | } 11 | }, 12 | "inputs": [], 13 | "outputs": [], 14 | "agent_endpoint_id": "AGENT_ENDPOINT", 15 | "client_config": { 16 | "component_type": "OciClientConfigWithApiKey", 17 | "id": "ceb3acb1-d2c2-4aed-8f4e-c1cd24daa40c", 18 | "name": "oci_client_config", 19 | "description": null, 20 | "metadata": {}, 21 | "service_endpoint": "OCIGENAI_ENDPOINT", 22 | "auth_type": "API_KEY", 23 | "auth_profile": "DEFAULT", 24 | "auth_file_location": "~/.oci/config" 25 | }, 26 | "agentspec_version": "25.4.1" 27 | } 28 | -------------------------------------------------------------------------------- /clean-install-dev.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright (c) 2024, 2025 Oracle and/or its affiliates. 4 | # 5 | # This software is under the Apache License 2.0 6 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 7 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 8 | 9 | # Default Python version 10 | PYTHON_CMD="python3.10" 11 | 12 | # Check if the selected Python version is available 13 | if ! command -v "$PYTHON_CMD" &> /dev/null; then 14 | echo -e "\e[31mError: Python command '$PYTHON_CMD' not found. Please make sure it's installed.\e[0m" 15 | exit 1 16 | fi 17 | 18 | source ./_installation_tools.sh 19 | 20 | create_venv 21 | 22 | upgrade_pip_or_uv 23 | 24 | ./install-all-dev.sh 25 | 26 | pre-commit install && echo -e "${GREEN}Successfully installed pre-commit hooks${NC}" 27 | -------------------------------------------------------------------------------- /wayflowcore/tests/agentspec/test_import_package.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | import importlib 8 | import pkgutil 9 | 10 | 11 | def import_all_submodules(package: str, recursive: bool = True) -> None: 12 | package_ = importlib.import_module(package) 13 | for _, name, is_pkg in pkgutil.walk_packages(package_.__path__): 14 | full_name = package_.__name__ + "." + name 15 | try: 16 | importlib.import_module(full_name) 17 | except ModuleNotFoundError: 18 | continue 19 | if recursive and is_pkg: 20 | import_all_submodules(full_name) 21 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/config_examples/howto_serialize_conversations.json: -------------------------------------------------------------------------------- 1 | { 2 | "component_type": "Agent", 3 | "id": "simple_assistant", 4 | "name": "agent_0f75efc7", 5 | "description": "", 6 | "metadata": { 7 | "__metadata_info__": { 8 | "name": "agent_0f75efc7", 9 | "description": "" 10 | } 11 | }, 12 | "inputs": [], 13 | "outputs": [], 14 | "llm_config": { 15 | "component_type": "VllmConfig", 16 | "id": "80c8028b-0dd6-4dc9-ad7d-a4860ef1b849", 17 | "name": "LLAMA_MODEL_ID", 18 | "description": null, 19 | "metadata": { 20 | "__metadata_info__": {} 21 | }, 22 | "default_generation_parameters": null, 23 | "url": "LLAMA_API_URL", 24 | "model_id": "LLAMA_MODEL_ID" 25 | }, 26 | "system_prompt": "You are a helpful assistant. Be concise.", 27 | "tools": [], 28 | "agentspec_version": "25.4.1" 29 | } 30 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/agentspec/components/datastores/nodes/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from .datastorecreatenode import PluginDatastoreCreateNode 8 | from .datastoredeletenode import PluginDatastoreDeleteNode 9 | from .datastorelistnode import PluginDatastoreListNode 10 | from .datastorequerynode import PluginDatastoreQueryNode 11 | from .datastoreupdatenode import PluginDatastoreUpdateNode 12 | 13 | __all__ = [ 14 | "PluginDatastoreCreateNode", 15 | "PluginDatastoreDeleteNode", 16 | "PluginDatastoreListNode", 17 | "PluginDatastoreQueryNode", 18 | "PluginDatastoreUpdateNode", 19 | ] 20 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/embeddingmodels/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from .embeddingmodel import EmbeddingModel 8 | from .ocigenaimodel import OCIGenAIEmbeddingModel 9 | from .ollamamodel import OllamaEmbeddingModel 10 | from .openaicompatiblemodel import OpenAICompatibleEmbeddingModel 11 | from .openaimodel import OpenAIEmbeddingModel 12 | from .vllmmodel import VllmEmbeddingModel 13 | 14 | __all__ = [ 15 | "EmbeddingModel", 16 | "OCIGenAIEmbeddingModel", 17 | "OllamaEmbeddingModel", 18 | "OpenAICompatibleEmbeddingModel", 19 | "OpenAIEmbeddingModel", 20 | "VllmEmbeddingModel", 21 | ] 22 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/api/agentserver.rst: -------------------------------------------------------------------------------- 1 | Agent Server 2 | ============ 3 | 4 | This page covers the components used to expose WayFlow agents through different protocols. 5 | 6 | 7 | Server application 8 | ------------------ 9 | 10 | .. _openairesponsesserver: 11 | .. autoclass:: wayflowcore.agentserver.server.OpenAIResponsesServer 12 | :members: __init__, get_app, run 13 | 14 | .. _a2aserver: 15 | .. autoclass:: wayflowcore.agentserver.server.A2AServer 16 | :members: __init__, get_app, run 17 | 18 | .. _serverstorageconfig: 19 | .. autoclass:: wayflowcore.agentserver.serverstorageconfig.ServerStorageConfig 20 | :members: to_schema 21 | 22 | .. autofunction:: wayflowcore.agentserver.app.create_server_app 23 | 24 | 25 | CLI Reference 26 | ------------- 27 | 28 | .. _cliwayflowreference: 29 | .. argparse:: 30 | :module: wayflowcore.cli 31 | :func: build_parser 32 | :prog: wayflow 33 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from importlib.metadata import version 8 | 9 | from .agent import Agent 10 | from .conversation import Conversation 11 | from .flow import Flow 12 | from .messagelist import Message, MessageList, MessageType 13 | from .steps.step import Step 14 | from .tools import Tool, tool 15 | 16 | __all__ = [ 17 | "Agent", 18 | "Conversation", 19 | "Flow", 20 | "Message", 21 | "MessageList", 22 | "MessageType", 23 | "Step", 24 | "tool", 25 | "Tool", 26 | ] 27 | 28 | # Get the version from the information set in the setup of this package 29 | __version__ = version("wayflowcore") 30 | -------------------------------------------------------------------------------- /docs/wayflowcore/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | %SPHINXBUILD% >NUL 2>NUL 14 | if errorlevel 9009 ( 15 | echo. 16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 17 | echo.installed, then set the SPHINXBUILD environment variable to point 18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 19 | echo.may add the Sphinx directory to PATH. 20 | echo. 21 | echo.If you don't have Sphinx installed, grab it from 22 | echo.https://www.sphinx-doc.org/ 23 | exit /b 1 24 | ) 25 | 26 | if "%1" == "" goto help 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/_static/howto/example_document.md: -------------------------------------------------------------------------------- 1 | # Oracle Corporation 2 | 3 | Oracle Corporation is an American multinational computer technology company headquartered in Austin, Texas. Co-founded in 1977 in Santa Clara, California, by Larry Ellison, who remains executive chairman, Oracle Corporation is the fourth-largest software company in the world by market capitalization as of 2025. Its market value was approximately US$614 billion in June 2025. The company's 2023 ranking in the Forbes Global 2000 was 80. The company sells database software, (particularly the Oracle Database), and cloud computing software and hardware. Oracle's core application software is a suite of enterprise software products, including enterprise resource planning (ERP), human capital management (HCM), customer relationship management (CRM), enterprise performance management (EPM), Customer Experience Commerce (CX Commerce) and supply chain management (SCM) software. 4 | -------------------------------------------------------------------------------- /wayflowcore/tests/agentserver/agent_registry.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from wayflowcore.tools import tool 8 | 9 | 10 | @tool(description_mode="only_docstring") 11 | def search_hr_database(query: str) -> str: 12 | """Function that searches the HR database for employee benefits. 13 | 14 | Parameters 15 | ---------- 16 | query: 17 | a query string 18 | 19 | Returns 20 | ------- 21 | a JSON response 22 | 23 | """ 24 | return '{"John Smith": {"benefits": "Unlimited PTO", "salary": "$1,000"}, "Mary Jones": {"benefits": "25 days", "salary": "$10,000"}}' 25 | 26 | 27 | tool_registry = {search_hr_database.name: search_hr_database} 28 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/agentspec/components/datastores/inmemory_datastore.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from typing import Dict 8 | 9 | from wayflowcore.agentspec.components.datastores.datastore import PluginDatastore 10 | from wayflowcore.agentspec.components.datastores.entity import PluginEntity 11 | 12 | 13 | class PluginInMemoryDatastore(PluginDatastore): 14 | """In-memory datastore for testing and development purposes.""" 15 | 16 | # "schema" is a special field for Pydantic, so use the prefix "datastore_" to avoid clashes 17 | datastore_schema: Dict[str, PluginEntity] 18 | """Mapping of collection names to entity definitions used by this datastore.""" 19 | -------------------------------------------------------------------------------- /wayflowcore/tests/run_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright (C) 2024, 2025 Oracle and/or its affiliates. 4 | # 5 | # This software is under the Apache License 2.0 6 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 7 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 8 | 9 | set -e # Exit immediately if any command fails 10 | 11 | REPO_ROOT=$( cd "$(dirname "${BASH_SOURCE[0]}")"/.. ; pwd -P ) 12 | 13 | # run all tests 14 | if [ "$1" = "--parallel" ]; then 15 | # Run tests in parallel 16 | pytest tests/test_docstring.py tests/datastores tests/agentserver 17 | pytest -n auto $REPO_ROOT/tests --dist loadscope --ignore=tests/datastores/ --ignore=tests/test_docstring.py --ignore=tests/agentserver/ 18 | else 19 | # Run tests normally 20 | pytest $REPO_ROOT/tests 21 | fi 22 | 23 | sh $REPO_ROOT/tests/security/logging_tests.sh $REPO_ROOT/tests/security 24 | -------------------------------------------------------------------------------- /wayflowcore/tests/_utils/test_singleton.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from wayflowcore._utils.singleton import Singleton 8 | 9 | 10 | class MySingletonCustomObject(metaclass=Singleton): 11 | def __init__(self): 12 | self.a = None 13 | 14 | 15 | class MyCustomObject: 16 | def __init__(self): 17 | self.a = None 18 | 19 | 20 | def test_instantiating_singleton_returns_same_instance(): 21 | o1 = MySingletonCustomObject() 22 | o2 = MySingletonCustomObject() 23 | assert id(o1) == id(o2) 24 | 25 | 26 | def test_instantiating_non_singleton_returns_different_instances(): 27 | o1 = MyCustomObject() 28 | o2 = MyCustomObject() 29 | assert id(o1) != id(o2) 30 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/tools/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from .agentbasedtools import DescribedAgent 8 | from .clienttools import ClientTool 9 | from .flowbasedtools import DescribedFlow 10 | from .remotetools import RemoteTool 11 | from .servertools import ServerTool, register_server_tool 12 | from .toolbox import ToolBox 13 | from .toolhelpers import tool 14 | from .tools import Tool, ToolRequest, ToolResult 15 | 16 | __all__ = [ 17 | "DescribedAgent", 18 | "ClientTool", 19 | "tool", 20 | "Tool", 21 | "ToolBox", 22 | "ToolRequest", 23 | "ToolResult", 24 | "DescribedFlow", 25 | "ServerTool", 26 | "RemoteTool", 27 | "register_server_tool", 28 | ] 29 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/contextproviders/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from typing import Dict, Type 8 | 9 | from .constantcontextprovider import ConstantContextProvider 10 | from .contextprovider import ContextProvider 11 | from .flowcontextprovider import FlowContextProvider 12 | from .toolcontextprovider import ToolContextProvider 13 | 14 | __all__ = [ 15 | "ContextProvider", 16 | "FlowContextProvider", 17 | "ToolContextProvider", 18 | "ConstantContextProvider", 19 | ] 20 | 21 | _SUPPORTED_CONTEXT_PROVIDER_TYPES: Dict[str, Type[ContextProvider]] = { 22 | "flow": FlowContextProvider, 23 | "tool": ToolContextProvider, 24 | "constant": ConstantContextProvider, 25 | } 26 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/mcp/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from .clienttransport import ( 8 | ClientTransport, 9 | SessionParameters, 10 | SSEmTLSTransport, 11 | SSETransport, 12 | StdioTransport, 13 | StreamableHTTPmTLSTransport, 14 | StreamableHTTPTransport, 15 | ) 16 | from .mcphelpers import enable_mcp_without_auth 17 | from .tools import MCPTool, MCPToolBox 18 | 19 | __all__ = [ 20 | "MCPTool", 21 | "MCPToolBox", 22 | "enable_mcp_without_auth", 23 | "SSETransport", 24 | "SSEmTLSTransport", 25 | "StdioTransport", 26 | "StreamableHTTPmTLSTransport", 27 | "StreamableHTTPTransport", 28 | "SessionParameters", 29 | "ClientTransport", 30 | ] 31 | -------------------------------------------------------------------------------- /wayflowcore/dev_scripts/openai-models-gen/generate_apis.sh: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | # THIS FILE IS USED TO GENERATE THE PYDANTIC MODELS FOR THE OPENAI RESPONSES PEN API SPEC 8 | 9 | # 10 | mkdir -p data 11 | 12 | # 1. get the latest version of the open API spec 13 | wget -N -P data https://app.stainless.com/api/spec/documented/openai/openapi.documented.yml 14 | 15 | # 2. filter only the models needed for the APIs we want to support (responses) 16 | python generate_models.py 17 | 18 | # 3. generate the pydantic models for these models 19 | python generate_pydantic_models.py 20 | 21 | # 4. copy the models in src/wayflowcore/agentserver/models/openairesponsespydanticmodels.py 22 | # and run formatting with git hooks 23 | -------------------------------------------------------------------------------- /wayflowcore/tests/tracing/spans/conftest.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from wayflowcore.tools import ClientTool, ServerTool 8 | 9 | GET_LOCATION_CLIENT_TOOL = ClientTool( 10 | name="get_location", 11 | description="Search the location of a given company", 12 | parameters={ 13 | "company_name": { 14 | "type": "string", 15 | "description": "Name of the company to search the location for", 16 | "default": "Oracle", 17 | }, 18 | }, 19 | ) 20 | 21 | DUMMY_SERVER_TOOL = ServerTool( 22 | name="simple_function", 23 | description="This is a simple function", 24 | func=lambda: print("This is a simple function"), 25 | input_descriptors=[], 26 | ) 27 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/config_examples/howto_io_descriptors.json: -------------------------------------------------------------------------------- 1 | { 2 | "component_type": "PluginInputMessageNode", 3 | "id": "c7f3b49e-0db5-45b6-9a18-42c565230dc9", 4 | "name": "step_7137de34", 5 | "description": "", 6 | "metadata": { 7 | "__metadata_info__": {} 8 | }, 9 | "inputs": [ 10 | { 11 | "type": "string", 12 | "title": "username" 13 | } 14 | ], 15 | "outputs": [ 16 | { 17 | "description": "the input value provided by the user", 18 | "type": "string", 19 | "title": "user_provided_input" 20 | } 21 | ], 22 | "branches": [ 23 | "next" 24 | ], 25 | "input_mapping": { 26 | "unclear_var_name": "username" 27 | }, 28 | "output_mapping": {}, 29 | "message_template": "Hi {{unclear_var_name}}. How are you doing?", 30 | "rephrase": false, 31 | "llm_config": null, 32 | "component_plugin_name": "NodesPlugin", 33 | "component_plugin_version": "25.4.0.dev0", 34 | "agentspec_version": "25.4.1" 35 | } 36 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/_static/icons/github-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/config_examples/howto_a2aagent.json: -------------------------------------------------------------------------------- 1 | { 2 | "component_type": "A2AAgent", 3 | "id": "5ba508ef-7cae-417a-9197-8f2aeee870b6", 4 | "name": "a2a_agent_4311ebd5__auto", 5 | "description": "", 6 | "metadata": { 7 | "__metadata_info__": {} 8 | }, 9 | "inputs": [], 10 | "outputs": [], 11 | "agent_url": "http://", 12 | "connection_config": { 13 | "component_type": "A2AConnectionConfig", 14 | "id": "c01ebe14-f467-4c01-a25b-0f3f22bfa550", 15 | "name": "connection_config", 16 | "description": null, 17 | "metadata": {}, 18 | "timeout": 600.0, 19 | "headers": null, 20 | "verify": false, 21 | "key_file": null, 22 | "cert_file": null, 23 | "ssl_ca_cert": null 24 | }, 25 | "session_parameters": { 26 | "timeout": 60.0, 27 | "poll_interval": 2.0, 28 | "max_retries": 5 29 | }, 30 | "agentspec_version": "25.4.2" 31 | } 32 | -------------------------------------------------------------------------------- /wayflowcore/tests/agentspec/test_extended_map_node.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from wayflowcore.agentspec.components import ExtendedMapNode, all_deserialization_plugin 8 | 9 | 10 | def test_extended_map_node_can_be_partially_constructed() -> None: 11 | partial_config = { 12 | "component_type": "ExtendedMapNode", 13 | "metadata": {"__studio__": {"expanded": True, "position_x": -77.0, "position_y": -443.5}}, 14 | "name": "fancy_name", 15 | } 16 | plugin_component = ExtendedMapNode.build_from_partial_config( 17 | partial_config, plugins=all_deserialization_plugin 18 | ) 19 | assert isinstance(plugin_component, ExtendedMapNode) 20 | assert plugin_component.name == "fancy_name" 21 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/templates/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from .llamatemplates import LLAMA_AGENT_TEMPLATE, LLAMA_CHAT_TEMPLATE 8 | from .nativetemplates import NATIVE_AGENT_TEMPLATE, NATIVE_CHAT_TEMPLATE 9 | from .pythoncalltemplates import PYTHON_CALL_AGENT_TEMPLATE, PYTHON_CALL_CHAT_TEMPLATE 10 | from .reacttemplates import REACT_AGENT_TEMPLATE, REACT_CHAT_TEMPLATE 11 | from .template import PromptTemplate 12 | 13 | __all__ = [ 14 | "NATIVE_CHAT_TEMPLATE", 15 | "NATIVE_AGENT_TEMPLATE", 16 | "REACT_CHAT_TEMPLATE", 17 | "REACT_AGENT_TEMPLATE", 18 | "LLAMA_CHAT_TEMPLATE", 19 | "LLAMA_AGENT_TEMPLATE", 20 | "PYTHON_CALL_CHAT_TEMPLATE", 21 | "PYTHON_CALL_AGENT_TEMPLATE", 22 | "PromptTemplate", 23 | ] 24 | -------------------------------------------------------------------------------- /wayflowcore/tests/agentspec/configs/ociagent_1.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | agent_endpoint_id: "ORACLE_PROCESS_HELPER_AGENT_ENDPOINT_ID" 8 | agents: [] 9 | client_config: 10 | auth_file_location: ~/.oci/config 11 | auth_profile: DEFAULT 12 | auth_type: API_KEY 13 | component_type: OciClientConfigWithApiKey 14 | description: null 15 | id: oci_client 16 | metadata: {} 17 | name: oci_client 18 | service_endpoint: https://agent-runtime.generativeai.us-chicago-1.oci.oraclecloud.com 19 | component_type: OciAgent 20 | description: OCI agent 21 | flows: [] 22 | id: oci_agent 23 | inputs: [] 24 | llm_config: null 25 | metadata: {} 26 | name: oci_agent 27 | outputs: [] 28 | system_prompt: '' 29 | tools: [] 30 | agentspec_version: 25.4.1 31 | -------------------------------------------------------------------------------- /.gitlab/jobs/schedule_regression.yml: -------------------------------------------------------------------------------- 1 | schedule_regression: 2 | stage: trigger 3 | when: manual 4 | variables: 5 | llmCodeGenSubmodule: 6 | value: "all" 7 | dryRunSubmodule: 8 | value: "same" 9 | script: 10 | - !reference [ .get_private_branch, script ] 11 | - | 12 | curl -X POST "${JENKINS_URL}/job/Regression/job/regression/buildWithParameters" \ 13 | --user "$JENKINS_BOT_AUTH" \ 14 | --data-urlencode "BRANCH=$PRIVATE_BRANCH" \ 15 | --data-urlencode "PUBLIC_BRANCH=$CI_COMMIT_REF_NAME" \ 16 | --data-urlencode "PUBLIC_COMMIT=$CI_COMMIT_SHA" \ 17 | --data-urlencode "PR_SOURCE_PROJECT=$CI_PROJECT_NAMESPACE" \ 18 | --data-urlencode "PR_SOURCE_REPOSITORY=$CI_PROJECT_NAME" \ 19 | --data-urlencode "EMAIL=$GITLAB_USER_EMAIL" \ 20 | --data-urlencode "llmCodeGenSubmodule=$llmCodeGenSubmodule" \ 21 | --data-urlencode "USE_${REPOSITORY_HOST}=true" \ 22 | --data-urlencode "${REPOSITORY_HOST}_PIPELINE_ID=$CI_PIPELINE_ID" 23 | - sleep 50 24 | -------------------------------------------------------------------------------- /wayflowcore/tests/test_assistantexecutionstate.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from wayflowcore.agent import Agent 8 | 9 | 10 | def test_events_list_length_limit_is_respected(remotely_hosted_llm): 11 | events_max_len = 1 12 | agent = Agent(llm=remotely_hosted_llm) 13 | conversation = agent.start_conversation() 14 | conversation.state._EVENTS_LIST_MAX_LENGTH = events_max_len 15 | assert len(conversation.state.events) == 0 16 | conversation.append_user_message("Hello, how are you?") 17 | _ = conversation.execute() 18 | assert len(conversation.state.events) == events_max_len 19 | conversation.append_user_message("Tell me a nice joke") 20 | _ = conversation.execute() 21 | assert len(conversation.state.events) == events_max_len 22 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/code_examples/quickstart.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | # isort:skip_file 7 | # fmt: off 8 | # mypy: ignore-errors 9 | 10 | from wayflowcore.models import VllmModel 11 | 12 | llm = VllmModel( 13 | model_id="model-id", 14 | host_port=os.environ["VLLM_HOST_PORT"], 15 | ) 16 | 17 | # .. full-code: 18 | from wayflowcore.agent import Agent 19 | 20 | assistant = Agent(llm=llm) 21 | 22 | conversation = assistant.start_conversation() 23 | conversation.append_user_message("I need help regarding my sql query") 24 | conversation.execute() 25 | 26 | # get the assistant's response to your query 27 | assistant_answer = conversation.get_last_message().content 28 | # I'd be happy to help with your SQL query... 29 | 30 | print(assistant_answer) 31 | # .. end-full-code 32 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/_utils/singleton.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from typing import Any, Dict 8 | 9 | 10 | class Singleton(type): 11 | """A metaclass that creates a Singleton base class when called.""" 12 | 13 | # Taken from https://stackoverflow.com/questions/6760685/creating-a-singleton-in-python 14 | _instances: Dict[Any, Any] = {} 15 | 16 | def __call__(cls, *args: Any, **kwargs: Dict[str, Any]) -> Any: 17 | """ 18 | Singleton class creation. 19 | 20 | Args: 21 | *args: arguments 22 | **kwargs: keyword arguments 23 | 24 | Returns: 25 | Singleton: object 26 | """ 27 | if cls not in cls._instances: 28 | cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) 29 | return cls._instances[cls] 30 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/_components/llm_config_tabs.rst: -------------------------------------------------------------------------------- 1 | .. :orphan: 2 | 3 | .. :no-search: 4 | 5 | .. tabs:: 6 | 7 | .. tab:: OCI GenAI 8 | 9 | .. code-block:: python 10 | 11 | from wayflowcore.models import OCIGenAIModel, OCIClientConfigWithApiKey 12 | 13 | llm = OCIGenAIModel( 14 | model_id="provider.model-id", 15 | compartment_id="compartment-id", 16 | client_config=OCIClientConfigWithApiKey( 17 | service_endpoint="https://url-to-service-endpoint.com", 18 | ), 19 | ) 20 | 21 | .. tab:: vLLM 22 | 23 | .. code-block:: python 24 | 25 | from wayflowcore.models import VllmModel 26 | 27 | llm = VllmModel( 28 | model_id="model-id", 29 | host_port="VLLM_HOST_PORT", 30 | ) 31 | 32 | .. tab:: Ollama 33 | 34 | .. code-block:: python 35 | 36 | from wayflowcore.models import OllamaModel 37 | 38 | llm = OllamaModel( 39 | model_id="model-id", 40 | ) 41 | -------------------------------------------------------------------------------- /wayflowcore/tests/agentspec/test_plugin_datastore_nodes.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from wayflowcore.agentspec.components import all_deserialization_plugin 8 | from wayflowcore.agentspec.components.datastores.nodes import PluginDatastoreCreateNode 9 | 10 | 11 | def test_plugin_datastore_create_node_can_be_partially_constructed() -> None: 12 | partial_config = { 13 | "component_type": "PluginDatastoreCreateNode", 14 | "metadata": {"__studio__": {"expanded": True, "position_x": -1458.5, "position_y": -955.0}}, 15 | "name": "fancy_name", 16 | } 17 | plugin_component = PluginDatastoreCreateNode.build_from_partial_config( 18 | partial_config, plugins=all_deserialization_plugin 19 | ) 20 | assert isinstance(plugin_component, PluginDatastoreCreateNode) 21 | assert plugin_component.name == "fancy_name" 22 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/cli/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | import argparse 8 | from typing import Optional, Sequence 9 | 10 | from .serve import add_parser as add_serve_parser 11 | 12 | __all__ = ["main"] 13 | 14 | 15 | def build_parser() -> argparse.ArgumentParser: 16 | parser = argparse.ArgumentParser( 17 | prog="wayflow", 18 | description="WayFlow command line interface.", 19 | ) 20 | subparsers = parser.add_subparsers(dest="command", required=True) 21 | 22 | add_serve_parser(subparsers) 23 | return parser 24 | 25 | 26 | def main(argv: Optional[Sequence[str]] = None) -> None: 27 | parser = build_parser() 28 | 29 | args = parser.parse_args(argv) 30 | handler = getattr(args, "handler", None) 31 | if handler is None: 32 | parser.error("No command specified.") 33 | 34 | handler(args) 35 | -------------------------------------------------------------------------------- /wayflowcore/tests/agentspec/test_startnode.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | import logging 7 | 8 | from wayflowcore import Flow 9 | from wayflowcore.agentspec import AgentSpecExporter, AgentSpecLoader 10 | from wayflowcore.property import IntegerProperty as RuntimeIntegerProperty 11 | from wayflowcore.steps import StartStep 12 | 13 | 14 | def test_start_step_can_be_exported_to_agentspec_then_imported(caplog) -> None: 15 | with caplog.at_level(logging.WARNING): 16 | step = StartStep( 17 | input_descriptors=[ 18 | RuntimeIntegerProperty(name="a", default_value=19), 19 | ], 20 | ) 21 | flow = Flow.from_steps([step]) 22 | agentspec_flow = AgentSpecExporter().to_json(flow) 23 | converted_back_flow = AgentSpecLoader().load_json(agentspec_flow) 24 | 25 | assert not [r for r in caplog.records if r.levelno >= logging.WARNING] 26 | -------------------------------------------------------------------------------- /wayflowcore/tests/testhelpers/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2024, 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from wayflowcore.evaluation.assistantevaluator import HumanProxyAssistant 8 | 9 | from .assistanttester import AssistantTester 10 | from .flowscriptrunner import ( 11 | AnswerCheck, 12 | AssistantCheck, 13 | FlowScript, 14 | FlowScriptCheck, 15 | FlowScriptInteraction, 16 | FlowScriptRunner, 17 | IODictCheck, 18 | StepExecutionCheck, 19 | ) 20 | from .promptbenchmarker import PromptBenchmarker, PromptBenchmarkerPlaceholder 21 | 22 | __all__ = [ 23 | "AssistantTester", 24 | "FlowScriptCheck", 25 | "FlowScriptInteraction", 26 | "FlowScriptRunner", 27 | "AnswerCheck", 28 | "AssistantCheck", 29 | "IODictCheck", 30 | "StepExecutionCheck", 31 | "FlowScript", 32 | "HumanProxyAssistant", 33 | "PromptBenchmarker", 34 | "PromptBenchmarkerPlaceholder", 35 | ] 36 | -------------------------------------------------------------------------------- /wayflowcore/requirements-dev.txt: -------------------------------------------------------------------------------- 1 | # For docs 2 | sphinx==6.1 3 | sphinx-substitution-extensions==2022.2.16 4 | sphinx-tabs==3.4.5 5 | sphinx-copybutton==0.5.2 6 | pydata-sphinx-theme==0.16.1 7 | sphinx-argparse==0.5.2 8 | # These are added as newer versions require sphinx>5.0, and pip doesn't resolve to older versions correctly 9 | sphinxcontrib-applehelp<1.0.8 10 | sphinxcontrib-devhelp<1.0.6 11 | sphinxcontrib-htmlhelp<2.0.5 12 | sphinxcontrib.serializinghtml<1.1.10 13 | sphinxcontrib.qthelp<1.0.7 14 | sphinx_toolbox<=3.8.0 15 | sphinx_design==0.6.1 16 | 17 | # To detect available memory when running tests and skip if not enough 18 | psutil 19 | 20 | # install package 21 | -c constraints/constraints_dev.txt 22 | -e .[oci,datastore,a2a] 23 | 24 | # For mypy type-checking stubs 25 | pandas-stubs 26 | types-requests 27 | types-PyYAML 28 | types-Deprecated 29 | types-python-dateutil 30 | 31 | # Additional packages for tests 32 | cryptography 33 | starlette>=0.47.2 34 | uvicorn>=0.23.1 35 | openai # testing the openai responses server 36 | google-adk[a2a] # testing the a2a server 37 | 38 | # This is used to load database connection arguments in the unit tests 39 | python-dotenv 40 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/templates/nativetemplates.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | 8 | from wayflowcore.templates.template import PromptTemplate 9 | from wayflowcore.transforms import RemoveEmptyNonUserMessageTransform 10 | 11 | NATIVE_CHAT_TEMPLATE = PromptTemplate( 12 | messages=[PromptTemplate.CHAT_HISTORY_PLACEHOLDER], 13 | post_rendering_transforms=[RemoveEmptyNonUserMessageTransform()], 14 | ) 15 | 16 | NATIVE_AGENT_TEMPLATE = PromptTemplate( 17 | messages=[ 18 | { 19 | "role": "system", 20 | "content": "{% if custom_instruction %}{{custom_instruction}}{% endif %}", 21 | }, 22 | PromptTemplate.CHAT_HISTORY_PLACEHOLDER, 23 | { 24 | "role": "system", 25 | "content": "{% if __PLAN__ %}The current plan you should follow is the following: \n{{__PLAN__}}{% endif %}", 26 | }, 27 | ], 28 | post_rendering_transforms=[RemoveEmptyNonUserMessageTransform()], 29 | ) 30 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/datastore/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | 8 | from .datastore import Datastore 9 | from .entity import Entity, nullable 10 | from .inmemory import InMemoryDatastore 11 | from .oracle import ( 12 | MTlsOracleDatabaseConnectionConfig, 13 | OracleDatabaseConnectionConfig, 14 | OracleDatabaseDatastore, 15 | TlsOracleDatabaseConnectionConfig, 16 | ) 17 | from .postgres import ( 18 | PostgresDatabaseConnectionConfig, 19 | PostgresDatabaseDatastore, 20 | TlsPostgresDatabaseConnectionConfig, 21 | ) 22 | 23 | __all__ = [ 24 | "Datastore", 25 | "Entity", 26 | "nullable", 27 | "InMemoryDatastore", 28 | "OracleDatabaseConnectionConfig", 29 | "TlsOracleDatabaseConnectionConfig", 30 | "MTlsOracleDatabaseConnectionConfig", 31 | "OracleDatabaseDatastore", 32 | "TlsPostgresDatabaseConnectionConfig", 33 | "PostgresDatabaseDatastore", 34 | "PostgresDatabaseConnectionConfig", 35 | ] 36 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/_metadata.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from typing import Any, Dict, Optional 8 | 9 | from wayflowcore.idgeneration import IdGenerator 10 | 11 | METADATA_KEY = "__metadata_info__" 12 | MetadataType = Dict[str, Any] 13 | 14 | METADATA_ID_KEY = "$$ID$$" 15 | 16 | 17 | class ObjectWithMetadata: 18 | def __init__(self, __metadata_info__: Optional[MetadataType] = None, id: Optional[str] = None): 19 | self.__metadata_info__ = dict(__metadata_info__) if __metadata_info__ is not None else {} 20 | # workaround to set the ID of any component without init argument 21 | default_id = id 22 | if METADATA_ID_KEY in self.__metadata_info__: 23 | default_id = self.__metadata_info__.pop(METADATA_ID_KEY) 24 | if not hasattr(self, "id"): 25 | self.id = IdGenerator.get_or_generate_id(default_id) 26 | 27 | if self.id is None: 28 | self.id = IdGenerator.get_or_generate_id(self.id) 29 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/_static/img/flexibility.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /wayflowcore/tests/agentspec/configs/agent_5.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | agents: [] 8 | component_type: Agent 9 | description: Agent with OCI LLM 10 | flows: [] 11 | id: agent_with_oci_llm 12 | inputs: [] 13 | llm_config: 14 | client_config: 15 | auth_file_location: ~/.oci/config 16 | auth_profile: DEFAULT 17 | auth_type: API_KEY 18 | component_type: OciClientConfigWithApiKey 19 | description: null 20 | id: oci_client 21 | metadata: {} 22 | name: oci_client 23 | service_endpoint: LLAMA_OCI_API_KEY_CONFIG_SERVICE_ENDPOINT 24 | compartment_id: LLAMA_OCI_API_KEY_CONFIG_COMPARTMENT_ID 25 | component_type: OciGenAiConfig 26 | default_generation_parameters: null 27 | description: null 28 | id: oci_llm_config 29 | metadata: {} 30 | model_id: LLAMA_OCI_API_KEY_CONFIG_MODEL_ID 31 | name: llm_config 32 | metadata: {} 33 | name: my_agent 34 | outputs: [] 35 | system_prompt: Assist the user with their requests. 36 | tools: [] 37 | agentspec_version: 25.4.1 38 | -------------------------------------------------------------------------------- /requirements-dev.txt: -------------------------------------------------------------------------------- 1 | # We fix the mypy version to ensure consistency across all developers and avoid some issue with 2 | # some of the more recent versions. 3 | mypy==1.11.2 4 | pydantic==2.11.7 5 | 6 | # pre-commit is used for installing commit hooks which ensure code quality 7 | # Learn more at: https://pre-commit.com/ 8 | pre-commit 9 | black==25.1.0 10 | isort==6.0.1 11 | bandit==1.8.3 12 | flake8==5.0.4 13 | flake8-copyright==0.2.4 14 | pyflakes==2.5.0 15 | 16 | # For docs 17 | sphinx==6.1 18 | sphinx-substitution-extensions==2022.2.16 19 | sphinx-tabs==3.4.5 20 | sphinx-copybutton==0.5.2 21 | pydata-sphinx-theme==0.16.1 22 | sphinx-argparse==0.5.2 23 | # These are added as newer versions require sphinx>5.0, and pip doesn't resolve to older versions correctly 24 | sphinxcontrib-applehelp<1.0.8 25 | sphinxcontrib-devhelp<1.0.6 26 | sphinxcontrib-htmlhelp<2.0.5 27 | sphinxcontrib.serializinghtml<1.1.10 28 | sphinxcontrib.qthelp<1.0.7 29 | sphinx_toolbox<=3.8.0 30 | sphinx_design==0.6.1 31 | 32 | # To detect available memory when running tests and skip if not enough 33 | psutil 34 | 35 | # To prevent issues with version 3.0.0 36 | snowballstemmer<3 37 | 38 | # To make sure all the tests run in the same order with the same pytest version 39 | pytest==7.4.4 40 | pytest-xdist==3.8.0 41 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/api/embeddingmodels.rst: -------------------------------------------------------------------------------- 1 | Embedding Models 2 | ================ 3 | 4 | This page presents all APIs and classes related to LLM Embedding models. 5 | 6 | EmbeddingModel 7 | ----------------- 8 | 9 | .. _embeddingmodel: 10 | .. autoclass:: wayflowcore.embeddingmodels.embeddingmodel.EmbeddingModel 11 | 12 | All models 13 | ---------- 14 | 15 | OpenAI Compatible Embedding Models 16 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 17 | 18 | .. _openaicompatibleembeddingmodel: 19 | .. autoclass:: wayflowcore.embeddingmodels.openaicompatiblemodel.OpenAICompatibleEmbeddingModel 20 | 21 | OpenAI Embedding Models 22 | ~~~~~~~~~~~~~~~~~~~~~~~ 23 | 24 | .. _openaiembeddingmodel: 25 | .. autoclass:: wayflowcore.embeddingmodels.openaimodel.OpenAIEmbeddingModel 26 | 27 | VLLM Embedding Models 28 | ~~~~~~~~~~~~~~~~~~~~~ 29 | 30 | .. _vllmembeddingmodel: 31 | .. autoclass:: wayflowcore.embeddingmodels.vllmmodel.VllmEmbeddingModel 32 | 33 | OCI GenAI Embedding Models 34 | ~~~~~~~~~~~~~~~~~~~~~~~~~~ 35 | 36 | .. _ocigenaiembeddingmodel: 37 | .. autoclass:: wayflowcore.embeddingmodels.ocigenaimodel.OCIGenAIEmbeddingModel 38 | 39 | Ollama Embedding Models 40 | ~~~~~~~~~~~~~~~~~~~~~~~ 41 | 42 | .. _ollamaembeddingmodel: 43 | .. autoclass:: wayflowcore.embeddingmodels.ollamamodel.OllamaEmbeddingModel -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/api/index.rst: -------------------------------------------------------------------------------- 1 | .. _api: 2 | 3 | API Reference 4 | ============= 5 | 6 | .. |agentspec-icon| image:: ../../_static/icons/agentspec-icon.svg 7 | :width: 100px 8 | 9 | .. grid:: 1 10 | 11 | .. grid-item-card:: |agentspec-icon| 12 | :link: https://oracle.github.io/agent-spec/api/index.html 13 | :link-alt: Agent Spec - API Reference 14 | 15 | Visit the Agent Spec API Documentation to learn more about the native Agent Spec Components. 16 | 17 | 18 | .. tip:: 19 | 20 | Click the button above ↑ to visit the `Agent Spec Documentation `_ 21 | 22 | 23 | 24 | .. toctree:: 25 | :maxdepth: 3 26 | 27 | Agent Spec Adapters 28 | Conversations 29 | LLMs 30 | Events 31 | Flows 32 | Agents 33 | Agent Server 34 | Embedding Models 35 | Context Providers 36 | Execution Interrupts 37 | PromptTemplates 38 | Serialization/Deserialization 39 | Tools 40 | Tracing 41 | Variables 42 | Datastores 43 | Warnings 44 | Evaluation 45 | Component 46 | A2A 47 | -------------------------------------------------------------------------------- /wayflowcore/tests/_utils/faker.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | import numpy as np 8 | 9 | 10 | class Faker: 11 | @staticmethod 12 | def seed(seed): 13 | np.random.seed(seed) 14 | 15 | def seed_instance(self, seed): 16 | np.random.seed(seed) 17 | 18 | def name(self): 19 | return np.random.choice( 20 | [ 21 | "Norma Fisher", 22 | "Jorge Sullivan", 23 | "Elizabeth Woods", 24 | "Susan Wagner", 25 | "Peter Montgomery", 26 | "Theodore Mcgrath", 27 | "Stephanie Collins", 28 | "Brian Hamilton", 29 | "Sean Green", 30 | "Kimberly Smith", 31 | ] 32 | ) 33 | 34 | def company(self): 35 | return np.random.choice( 36 | [ 37 | "Cook Inc", 38 | "Williams PLC", 39 | "Matthews-Rogers", 40 | "Hinton LLC", 41 | "Morales Ltd", 42 | ] 43 | ) 44 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/config_examples/howto_async.yaml: -------------------------------------------------------------------------------- 1 | component_type: Agent 2 | id: 7017dd89-e176-476f-a655-06fce4310399 3 | name: agent_0f9ffda8__auto 4 | description: '' 5 | metadata: 6 | __metadata_info__: {} 7 | inputs: 8 | - description: '"query" input variable for the template' 9 | title: query 10 | type: string 11 | outputs: [] 12 | llm_config: 13 | component_type: VllmConfig 14 | id: 2ceded67-85f7-4e47-be6c-2278f33f54f3 15 | name: LLAMA_MODEL_ID 16 | description: null 17 | metadata: 18 | __metadata_info__: {} 19 | default_generation_parameters: null 20 | url: LLAMA_API_URL 21 | model_id: LLAMA_MODEL_ID 22 | system_prompt: You are a helpful assistant, answering the user request about {{query}} 23 | tools: 24 | - component_type: ServerTool 25 | id: bd53ed97-2f4b-4936-99fa-0c5b43d00a90 26 | name: heavy_work 27 | description: Performs heavy CPU-bound work. 28 | metadata: 29 | __metadata_info__: {} 30 | inputs: [] 31 | outputs: 32 | - title: tool_output 33 | type: string 34 | - component_type: ServerTool 35 | id: e87b2e06-70db-4439-b653-02978390fa36 36 | name: remote_call 37 | description: Performs remote API calls (I/O-bound). 38 | metadata: 39 | __metadata_info__: {} 40 | inputs: [] 41 | outputs: 42 | - title: tool_output 43 | type: string 44 | agentspec_version: 25.4.1 45 | -------------------------------------------------------------------------------- /.gitlab/jobs/schedule_mergegate.yml: -------------------------------------------------------------------------------- 1 | schedule_mergegate: 2 | stage: trigger 3 | when: manual 4 | variables: 5 | DELETE_BRANCH: 6 | value: "false" 7 | script: 8 | - !reference [ .get_merge_request_id, script ] 9 | - !reference [ .get_private_branch, script ] 10 | - | 11 | curl -X POST "${JENKINS_URL}/job/Regression/job/mergegate/buildWithParameters" \ 12 | --user "$JENKINS_BOT_AUTH" \ 13 | --data-urlencode "BRANCH=$PRIVATE_BRANCH" \ 14 | --data-urlencode "PUBLIC_BRANCH=$CI_COMMIT_REF_NAME" \ 15 | --data-urlencode "EMAIL=$GITLAB_USER_EMAIL" \ 16 | --data-urlencode "PUBLIC_PRID=$PUBLIC_MERGE_REQUEST_ID" \ 17 | --data-urlencode "PRIVATE_PRID=$PRIVATE_MERGE_REQUEST_ID" \ 18 | --data-urlencode "COMMIT=$PRIVATE_MERGE_REQUEST_COMMIT_HASH" \ 19 | --data-urlencode "PUBLIC_COMMIT=$CI_COMMIT_SHA" \ 20 | --data-urlencode "PR_SOURCE_PROJECT=$CI_PROJECT_NAMESPACE" \ 21 | --data-urlencode "PR_SOURCE_REPOSITORY=$CI_PROJECT_NAME" \ 22 | --data-urlencode "PR_SOURCE_ID=$PUBLIC_MERGE_REQUEST_ID" \ 23 | --data-urlencode "USE_${REPOSITORY_HOST}=true" \ 24 | --data-urlencode "DELETE_BRANCH=$DELETE_BRANCH" \ 25 | --data-urlencode "${REPOSITORY_HOST}_PIPELINE_ID=$CI_PIPELINE_ID" 26 | - echo "waiting for external pipeline to appear on gitlab UI" 27 | - sleep 50 28 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/evaluation/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2024, 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from wayflowcore.evaluation.assistantevaluator import ( 8 | AssistantEvaluator, 9 | EvaluationEnvironment, 10 | EvaluationTask, 11 | HumanProxyAssistant, 12 | ) 13 | from wayflowcore.evaluation.conversationevaluator import ConversationEvaluator 14 | from wayflowcore.evaluation.conversationscorer import ConversationScorer 15 | from wayflowcore.evaluation.evaluation_metrics import calculate_accuracy, calculate_set_metrics 16 | from wayflowcore.evaluation.taskscorer import TaskScorer 17 | from wayflowcore.evaluation.usefulnessscorer import UsefulnessScorer 18 | from wayflowcore.evaluation.userhappinessscorer import UserHappinessScorer 19 | 20 | __all__ = [ 21 | "AssistantEvaluator", 22 | "EvaluationEnvironment", 23 | "EvaluationTask", 24 | "ConversationEvaluator", 25 | "ConversationScorer", 26 | "TaskScorer", 27 | "UsefulnessScorer", 28 | "UserHappinessScorer", 29 | "calculate_set_metrics", 30 | "calculate_accuracy", 31 | "HumanProxyAssistant", 32 | ] 33 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/_static/announcement.js: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2024, 2025 Oracle and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | document.addEventListener("DOMContentLoaded", function () { 16 | const closeBtn = document.getElementById("close-announcement"); 17 | const banner = document.querySelector(".bd-header-announcement"); 18 | 19 | if (banner) { 20 | banner.style.display = "none"; 21 | } 22 | 23 | if (!sessionStorage.getItem("announcementClosed")) { 24 | if (banner) { 25 | banner.style.display = "block"; 26 | } 27 | 28 | if (closeBtn) { 29 | closeBtn.addEventListener("click", function () { 30 | banner.style.display = "none"; 31 | sessionStorage.setItem("announcementClosed", "true"); 32 | }); 33 | } 34 | } 35 | }); 36 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/_static/icons/python-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /wayflowcore/tests/security/check_undefined_logger.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | """ 8 | Test that wayflowcore does not alter the root log level and 9 | respects the logger configuration provided by the application. 10 | """ 11 | 12 | import logging 13 | 14 | 15 | def test_wayflowcore_logging_does_not_alter_application_logger(): 16 | # When application provides a loggingconfig 17 | root_logger = logging.getLogger() 18 | root_logger.setLevel(logging.INFO) 19 | assert root_logger.getEffectiveLevel() == logging.INFO 20 | 21 | # Then wayflowcore should not alter root loglevel 22 | assert root_logger.getEffectiveLevel() == logging.INFO 23 | 24 | # instead it should use the application logger 25 | assert logging.getLogger("wayflowcore").getEffectiveLevel() == logging.INFO 26 | 27 | # similar to how named loggers in the primary application behave 28 | app_logger = logging.getLogger("my.application") 29 | assert app_logger.getEffectiveLevel() == logging.INFO 30 | 31 | 32 | if __name__ == "__main__": 33 | test_wayflowcore_logging_does_not_alter_application_logger() 34 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/executors/_ociagentconversation.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | from dataclasses import dataclass 7 | from typing import TYPE_CHECKING, List 8 | 9 | from wayflowcore.conversation import Conversation 10 | from wayflowcore.executors._ociagentexecutor import OciAgentState 11 | from wayflowcore.ociagent import OciAgent 12 | 13 | if TYPE_CHECKING: 14 | from wayflowcore.contextproviders import ContextProvider 15 | from wayflowcore.conversation import Conversation 16 | 17 | 18 | @dataclass 19 | class OciAgentConversation(Conversation): 20 | component: OciAgent 21 | state: OciAgentState 22 | 23 | @property 24 | def current_step_name(self) -> str: 25 | return "oci_agent" 26 | 27 | def _get_all_context_providers_from_parent_conversations(self) -> List["ContextProvider"]: 28 | return [] 29 | 30 | def _get_all_sub_conversations(self) -> List[Conversation]: 31 | return [] 32 | 33 | def __repr__(self) -> str: 34 | return f"OciAgentConversation({self.get_messages()})" 35 | 36 | def __str__(self) -> str: 37 | return f"OciAgentConversation({self.get_messages()})" 38 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/api/interrupts.rst: -------------------------------------------------------------------------------- 1 | Execution Interrupts 2 | ==================== 3 | 4 | We often need to interrupt the normal execution of an assistant to perform specific operations including but not limited to: 5 | 6 | - Checking the token count 7 | - Verifying the runtime 8 | - Doing step by step debugging 9 | 10 | For this reason, we provide execution interrupts, which let developers interact with the assistant's execution at specific moments. 11 | 12 | This page presents all APIs and classes related to execution interrupts in WayFlow. 13 | 14 | Execution Interrupt interface 15 | ----------------------------- 16 | 17 | .. _executioninterrupt: 18 | .. autoclass:: wayflowcore.executors.interrupts.executioninterrupt.ExecutionInterrupt 19 | 20 | .. _interruptedexecutionstatus: 21 | .. autoclass:: wayflowcore.executors.interrupts.executioninterrupt.InterruptedExecutionStatus 22 | 23 | 24 | Basic Execution Interrupt classes 25 | --------------------------------- 26 | 27 | Timeout Execution Interrupt 28 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 29 | 30 | .. _softtimeoutexecutioninterrupt: 31 | .. autoclass:: wayflowcore.executors.interrupts.timeoutexecutioninterrupt.SoftTimeoutExecutionInterrupt 32 | 33 | Token Limit Execution Interrupt 34 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 35 | 36 | .. _softtokenlimitexecutioninterrupt: 37 | .. autoclass:: wayflowcore.executors.interrupts.tokenlimitexecutioninterrupt.SoftTokenLimitExecutionInterrupt 38 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/rfcs-template.rst: -------------------------------------------------------------------------------- 1 | :orphan: 2 | 3 | ======================== 4 | WayFlow RFC Template 5 | ======================== 6 | 7 | Use this template to propose a **new feature**, **design change**, or **enhancement** to WayFlow. 8 | Please keep it concise but thorough so reviewers can understand the motivation, scope, and impact of your idea. 9 | 10 | Summary 11 | ------- 12 | 13 | One-liner summary of the proposal. 14 | What problem does this solve or what capability does it add? 15 | 16 | Motivation 17 | ---------- 18 | 19 | Explain the problem or opportunity. 20 | 21 | - What is the use case? 22 | - What is the impact on end users or developers? 23 | 24 | Proposal 25 | -------- 26 | 27 | Describe the solution in detail. 28 | 29 | - How do you propose to solve it? 30 | - Include high-level architecture or code snippets if helpful. 31 | - What components of the project are affected? 32 | 33 | Potential risks or concerns 34 | --------------------------- 35 | 36 | Are there any drawbacks or compatibility concerns to be aware of? 37 | 38 | - Security, performance, or maintainability concerns? 39 | - Backward compatibility? 40 | 41 | Related Links (Optional) 42 | ------------------------ 43 | 44 | Include links to relevant GitHub issues, external references, docs, etc. 45 | 46 | Implementation Plan (Optional) 47 | ------------------------------ 48 | 49 | If you already have an idea of the implementation steps, outline them here. 50 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/agentspec/components/datastores/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from .datastore import PluginDatastore 8 | from .entity import PluginEntity 9 | from .inmemory_datastore import PluginInMemoryDatastore 10 | from .oracle_datastore import ( 11 | PluginMTlsOracleDatabaseConnectionConfig, 12 | PluginOracleDatabaseConnectionConfig, 13 | PluginOracleDatabaseDatastore, 14 | PluginTlsOracleDatabaseConnectionConfig, 15 | ) 16 | from .postgres_datastore import ( 17 | PluginPostgresDatabaseConnectionConfig, 18 | PluginPostgresDatabaseDatastore, 19 | PluginTlsPostgresDatabaseConnectionConfig, 20 | ) 21 | from .relational_datastore import PluginRelationalDatastore 22 | 23 | __all__ = [ 24 | "PluginDatastore", 25 | "PluginEntity", 26 | "PluginInMemoryDatastore", 27 | "PluginMTlsOracleDatabaseConnectionConfig", 28 | "PluginOracleDatabaseDatastore", 29 | "PluginOracleDatabaseConnectionConfig", 30 | "PluginTlsOracleDatabaseConnectionConfig", 31 | "PluginRelationalDatastore", 32 | "PluginTlsPostgresDatabaseConnectionConfig", 33 | "PluginPostgresDatabaseConnectionConfig", 34 | "PluginPostgresDatabaseDatastore", 35 | ] 36 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/api/serialization.rst: -------------------------------------------------------------------------------- 1 | .. _serialization: 2 | 3 | Serialization / Deserialization 4 | =============================== 5 | 6 | Base classes 7 | ------------ 8 | 9 | .. _serializableobject: 10 | .. autoclass:: wayflowcore.serialization.serializer.SerializableObject 11 | 12 | 13 | Serialization 14 | ------------- 15 | 16 | .. _serializationcontext: 17 | .. autoclass:: wayflowcore.serialization.context.SerializationContext 18 | 19 | .. _serialize: 20 | .. autofunction:: wayflowcore.serialization.serializer.serialize 21 | 22 | 23 | Deserialization 24 | --------------- 25 | 26 | .. _deserializationcontext: 27 | .. autoclass:: wayflowcore.serialization.context.DeserializationContext 28 | 29 | .. _deserialize: 30 | .. autofunction:: wayflowcore.serialization.serializer.deserialize 31 | 32 | .. _autodeserialize: 33 | .. autofunction:: wayflowcore.serialization.serializer.autodeserialize 34 | 35 | 36 | Plugins 37 | ------- 38 | 39 | WayFlow Plugins are the expected mean that users can use to introduce new concepts and components, or extensions to existing ones, 40 | such that they can be integrated seamlessly into the serialization, deserialization, and Agent Spec conversion processes 41 | of WayFlow. 42 | 43 | .. _wayflowserializationplugin: 44 | .. autoclass:: wayflowcore.serialization.plugins.WayflowSerializationPlugin 45 | 46 | .. _wayflowdeserializationplugin: 47 | .. autoclass:: wayflowcore.serialization.plugins.WayflowDeserializationPlugin 48 | -------------------------------------------------------------------------------- /wayflowcore/tests/testhelpers/humanproxy.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2024, 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from typing import Dict, List, Optional, TypedDict 8 | 9 | from wayflowcore import Step 10 | from wayflowcore.contextproviders import ContextProvider 11 | from wayflowcore.controlconnection import ControlFlowEdge 12 | 13 | FlowConfigT = TypedDict( 14 | "FlowConfigT", 15 | { 16 | "begin_step": Step, 17 | "steps": Dict[str, Step], 18 | "control_flow_edges": List[ControlFlowEdge], 19 | "context_providers": Optional[List[ContextProvider]], 20 | }, 21 | total=False, 22 | ) 23 | 24 | 25 | def _single_step_flow_dict( 26 | step: Step, 27 | step_name: str = "single_step", 28 | context_providers: Optional[List[ContextProvider]] = None, 29 | ) -> FlowConfigT: 30 | return dict( 31 | begin_step=step, 32 | steps={step_name: step}, 33 | control_flow_edges=[ 34 | ControlFlowEdge( 35 | source_step=step, 36 | source_branch=str(branch_name), 37 | destination_step=None, 38 | ) 39 | for branch_name in step.get_branches() 40 | ], 41 | context_providers=context_providers, 42 | ) 43 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/agentserver/app.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from typing import Dict, Literal, TypeAlias, Union 8 | 9 | from wayflowcore.agentserver import ServerStorageConfig 10 | from wayflowcore.agentserver.server import A2AServer, OpenAIResponsesServer 11 | from wayflowcore.conversationalcomponent import ConversationalComponent 12 | from wayflowcore.datastore import Datastore 13 | 14 | ServerApiType: TypeAlias = Literal["openai-responses", "a2a"] 15 | 16 | 17 | def create_server_app( 18 | api: ServerApiType, 19 | agents: Dict[str, ConversationalComponent], 20 | storage: Datastore, 21 | storage_config: ServerStorageConfig, 22 | ) -> Union[OpenAIResponsesServer, A2AServer]: 23 | if api == "openai-responses": 24 | return OpenAIResponsesServer( 25 | agents=agents, 26 | storage=storage, 27 | storage_config=storage_config, 28 | ) 29 | elif api == "a2a": 30 | server = A2AServer( 31 | storage_config=storage_config, 32 | ) 33 | agent = list(agents.values())[0] 34 | server.serve_agent(agent=agent) 35 | return server 36 | 37 | raise NotImplementedError(f"API `{api}` is not supported yet.") 38 | -------------------------------------------------------------------------------- /wayflowcore/tests/agentspec/test_plugins.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from collections import Counter 8 | 9 | from wayflowcore.agentspec.components import all_deserialization_plugin, all_serialization_plugin 10 | 11 | 12 | def test_serialization_plugins_all_have_unique_names(): 13 | name_counter = Counter(p.plugin_name for p in all_serialization_plugin) 14 | 15 | most_common_name_pair = name_counter.most_common(1) 16 | assert len(most_common_name_pair) == 1 17 | most_common_name_count = most_common_name_pair[0][1] 18 | assert most_common_name_count == 1 19 | 20 | 21 | def test_deserialization_plugins_all_have_unique_names(): 22 | name_counter = Counter(p.plugin_name for p in all_deserialization_plugin) 23 | 24 | most_common_name_pair = name_counter.most_common(1) 25 | assert len(most_common_name_pair) == 1 26 | most_common_name_count = most_common_name_pair[0][1] 27 | assert most_common_name_count == 1 28 | 29 | 30 | def test_plugins_all_have_matching_ser_deser_names(): 31 | ser_plugin_names = {p.plugin_name for p in all_serialization_plugin} 32 | deser_plugin_names = {p.plugin_name for p in all_deserialization_plugin} 33 | 34 | assert ser_plugin_names == deser_plugin_names 35 | -------------------------------------------------------------------------------- /wayflowcore/tests/tracing/opentelemetry/otel_server_utils.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | import os 8 | import subprocess 9 | import time 10 | from typing import Tuple 11 | 12 | import httpx 13 | 14 | _START_SERVER_FILE_PATH = os.path.join( 15 | os.path.dirname(os.path.abspath(__file__)), "start_otel_server.py" 16 | ) 17 | 18 | 19 | def _check_server_is_up(url: str) -> bool: 20 | with httpx.Client() as client: 21 | for _ in range(50): # up to 5 seconds 22 | try: 23 | resp = client.get(url) 24 | if resp.status_code < 500: 25 | return True 26 | except Exception: 27 | time.sleep(0.2) 28 | else: 29 | return False 30 | 31 | 32 | def _start_otel_server(host: str, port: int) -> Tuple[subprocess.Popen, str]: 33 | process = subprocess.Popen( 34 | [ 35 | "python", 36 | _START_SERVER_FILE_PATH, 37 | "--host", 38 | host, 39 | "--port", 40 | str(port), 41 | ] 42 | ) 43 | url = f"http://{host}:{port}" 44 | server_is_up = _check_server_is_up(url) 45 | if not server_is_up: 46 | raise RuntimeError("Uvicorn server did not start in time") 47 | return process, url 48 | -------------------------------------------------------------------------------- /.gitlab/README.md: -------------------------------------------------------------------------------- 1 | # GitLab CI Integration 2 | 3 | ## Overview 4 | 5 | This folder contains Giltab CI/CD configurations and supporting files. It contains jobs that are designed to interface with Jenkins, allowing manual trigger jobs to initiate Jenkins pipelines from within Gitlab. The folder includes: 6 | - GitLab CI manual jobs 7 | 8 | Currently, we support three key pipelines: 9 | - **Regression Pipeline** – for running regression tests 10 | 11 | Each job is a scheduler that initiates a corresponding Jenkins pipeline. 12 | 13 | ## Getting Started 14 | 15 | This guide helps you understand the structure, setup, and usage of the GitLab CI integration with Jenkins. 16 | 17 | ## Prerequisites 18 | 19 | - Access to the Gitlab repository hosted in **Gitlab** 20 | - Jenkins access token to trigger pipelines 21 | - Gitlab project access token 22 | - Proper configuration in the Jenkins job to accept remote triggers 23 | 24 | ## Configuration 25 | 26 | 1. update the `.gitlab/jobs` folder to add your jobs and update `.gitlab-ci.yml` file to include or reference manual jobs you added. 27 | 2. Ensure Jenkins is configured to accept remote builds via token or webhook. 28 | 3. Link Jenkins job names and parameters in the GitLab job scripts as needed. 29 | 4. Add required environment variables in GitLab CI/CD settings (e.g., `GITLAB_MERGE_BOT_TOKEN`, `JENKINS_BOT_AUTH`). 30 | 31 | ## How to Use the Jobs 32 | 33 | ### Regression Pipeline 34 | 35 | This pipeline is triggered manually ,and it's responsibility is to trigger the regression pipeline in jenkins. 36 | 37 | 38 | -------------------------------------------------------------------------------- /wayflowcore/tests/agentspec/test_template_node.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from typing import cast 8 | 9 | from wayflowcore import Flow 10 | from wayflowcore.agentspec import AgentSpecExporter, AgentSpecLoader 11 | from wayflowcore.executors.executionstatus import FinishedStatus 12 | from wayflowcore.property import IntegerProperty as RuntimeIntegerProperty 13 | from wayflowcore.steps import TemplateRenderingStep 14 | 15 | 16 | def test_template_step_can_be_exported_to_agentspec_then_imported() -> None: 17 | step = TemplateRenderingStep( 18 | template="{{a}} + {{b}} = {{c}}", 19 | input_descriptors=[ 20 | RuntimeIntegerProperty(name="a", default_value=19), 21 | RuntimeIntegerProperty(name="b", default_value=23), 22 | RuntimeIntegerProperty(name="c"), 23 | ], 24 | output_mapping={TemplateRenderingStep.OUTPUT: "equation"}, 25 | ) 26 | flow = Flow.from_steps([step]) 27 | serialized_flow = AgentSpecExporter().to_yaml(flow) 28 | new_flow = cast(Flow, AgentSpecLoader().load_yaml(serialized_flow)) 29 | conversation = new_flow.start_conversation({"c": 43}) 30 | status = conversation.execute() 31 | assert isinstance(status, FinishedStatus) 32 | assert status.output_values == {"equation": "19 + 23 = 43"} 33 | -------------------------------------------------------------------------------- /docs/wayflowcore/README: -------------------------------------------------------------------------------- 1 | # Building the docs 2 | 3 | To build the docs, run the command `make html`. 4 | Note: The above command should be run from `docs/wayflowcore` folder. 5 | 6 | Note: the project should be installed in editable mode. Please refer 7 | to [the main README.md](../README.md). 8 | 9 | # Deploying the docs 10 | 11 | ## Deploying the main docs 12 | 13 | After building the docs, they can be deployed with a simple Python HTTP server: 14 | `` 15 | cd build/html 16 | python3 -m http.server 7860 17 | `` 18 | 19 | # Writing the docs 20 | 21 | When adding new functionality, ask yourself whether it should be part 22 | of the API for users of the `wayflowcore` library. If not, it should probably be marked 23 | as non-public with a leading underscore (`_foo`). In this case, it will 24 | not be included in the generated documentation. 25 | 26 | All public classes, methods and functions should have a docstring, 27 | ideally following the [numpydoc 28 | standard](https://numpydoc.readthedocs.io/en/latest/example.html). 29 | 30 | To add a new public class or module in the documentation, add an 31 | `autoclass` or `automodule` command in the `.rst` files inside the 32 | `docs/wayflowcore/source` folder. 33 | 34 | Additional notes: 35 | 36 | - Accurate type annotations will improve the documentation. 37 | Optionally, it is also possible to provide a parameter type in the 38 | docstring, which overrides the type annotation. This is usually 39 | not necessary. 40 | - Default parameter values are automatically included in the 41 | documentation. They don't need to be added in the docstring. 42 | -------------------------------------------------------------------------------- /wayflowcore/tests/agentspec/test_partial_serde.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | import pytest 7 | from pyagentspec.serialization import AgentSpecDeserializer, AgentSpecSerializer 8 | 9 | from wayflowcore.agentspec.components import all_deserialization_plugin, all_serialization_plugin 10 | from wayflowcore.agentspec.components.flow import ExtendedFlow 11 | 12 | 13 | def test_serde_of_partially_configured_components_works_with_wayflow_plugins(): 14 | incomplete_extended_flow_dict = {"component_type": "ExtendedFlow", "name": "Foo"} 15 | 16 | deserializer = AgentSpecDeserializer(plugins=all_deserialization_plugin) 17 | with pytest.warns( 18 | UserWarning, match="Missing `agentspec_version` field at the top level of the configuration" 19 | ): 20 | component, errors = deserializer.from_partial_dict(incomplete_extended_flow_dict) 21 | assert isinstance(component, ExtendedFlow) 22 | assert component.name == "Foo" 23 | 24 | serializer = AgentSpecSerializer( 25 | _allow_partial_model_serialization=True, plugins=all_serialization_plugin 26 | ) 27 | partial_component_yaml = serializer.to_yaml(component) 28 | assert "component_type: ExtendedFlow" in partial_component_yaml 29 | assert "component_plugin_name: FlowPlugin" in partial_component_yaml 30 | assert "name: Foo" in partial_component_yaml 31 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/evaluation/conversationscorer.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2024, 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from abc import ABC, abstractmethod 8 | from typing import Dict 9 | 10 | from wayflowcore._utils.async_helpers import run_sync_in_thread 11 | from wayflowcore.messagelist import MessageList 12 | from wayflowcore.models.llmmodel import LlmModel 13 | 14 | 15 | class ConversationScorer(ABC): 16 | def __init__( 17 | self, 18 | scorer_id: str, 19 | llm: LlmModel, 20 | ): 21 | """ 22 | Base Scorer class to evaluate a conversation trace. 23 | 24 | Parameters 25 | ---------- 26 | scorer_id: 27 | The scorer identifier. Is used in the column name for the output evaluation DataFrame 28 | llm: 29 | The model to use to evaluate the conversation 30 | """ 31 | self.scorer_id = scorer_id 32 | self.llm = llm 33 | 34 | @abstractmethod 35 | def score( 36 | self, conversation_messages: MessageList, output_raw_evaluation: bool = False 37 | ) -> Dict[str, float]: 38 | pass 39 | 40 | async def score_async( 41 | self, conversation_messages: MessageList, output_raw_evaluation: bool = False 42 | ) -> Dict[str, float]: 43 | return await run_sync_in_thread(self.score, conversation_messages, output_raw_evaluation) 44 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/_utils/io_utils.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | import os 8 | from pathlib import Path 9 | from typing import Union 10 | 11 | import pandas as pd 12 | 13 | from wayflowcore.exceptions import SecurityException 14 | 15 | 16 | def secure_to_csv(df: pd.DataFrame, filepath: Union[str, Path]) -> None: 17 | """ 18 | Securely write a DataFrame to a CSV file with strict permissions. 19 | 20 | Parameters 21 | ---------- 22 | df : pandas.DataFrame 23 | The DataFrame to be written to the CSV file. 24 | filepath : str or pathlib.Path 25 | The path where the CSV file should be saved. If the directory doesn't 26 | exist, it will be created with secure permissions. 27 | """ 28 | _filepath = Path(filepath).resolve() # filepath sanitation 29 | _filepath.parent.mkdir(mode=0o700, parents=True, exist_ok=True) 30 | 31 | # Due to security constraints, we set the permissions for all the files we generate to 600 (rw only for owner) 32 | old_umask = os.umask(0o077) 33 | try: 34 | df.to_csv(_filepath, index=False) 35 | if _filepath.stat().st_mode & 0o777 != 0o600: # Verify final permissions 36 | raise SecurityException("Final file has incorrect permissions") 37 | finally: 38 | # Whatever happens, we restore the original umask 39 | os.umask(old_umask) 40 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/config_examples/tutorial_agent.yaml: -------------------------------------------------------------------------------- 1 | component_type: Agent 2 | id: 61bd7075-4f41-4344-8e0d-1d6935975794 3 | name: agent_58415549__auto 4 | description: '' 5 | metadata: 6 | __metadata_info__: {} 7 | inputs: [] 8 | outputs: [] 9 | llm_config: 10 | component_type: VllmConfig 11 | id: 7796961b-db94-4a5e-bd12-8c532989fe0f 12 | name: LLAMA_MODEL_ID 13 | description: null 14 | metadata: 15 | __metadata_info__: {} 16 | default_generation_parameters: null 17 | url: LLAMA_API_URL 18 | model_id: LLAMA_MODEL_ID 19 | system_prompt: "You are a knowledgeable, factual, and helpful HR assistant that can\ 20 | \ answer simple HR-related questions like salary and benefits.\nYou are given a\ 21 | \ tool to look up the HR database.\nYour task:\n - Ask the user if they need\ 22 | \ assistance\n - Use the provided tool below to retrieve HR data\n - Based\ 23 | \ on the data you retrieved, answer the user's question\nImportant:\n - Be helpful\ 24 | \ and concise in your messages\n - Do not tell the user any details not mentioned\ 25 | \ in the tool response, let's be factual." 26 | tools: 27 | - component_type: ServerTool 28 | id: c6d943c1-20a3-4f66-b89b-8173ab854e0b 29 | name: search_hr_database 30 | description: "Function that searches the HR database for employee benefits.\n\n\ 31 | Parameters\n----------\nquery:\n a query string\n\nReturns\n-------\n a\ 32 | \ JSON response" 33 | metadata: 34 | __metadata_info__: {} 35 | inputs: 36 | - type: string 37 | title: query 38 | outputs: 39 | - type: string 40 | title: tool_output 41 | agentspec_version: 25.4.1 42 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/_static/img/extensibility.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/api/conversation.rst: -------------------------------------------------------------------------------- 1 | Conversations 2 | ============= 3 | 4 | Messages 5 | -------- 6 | 7 | .. _message: 8 | .. autoclass:: wayflowcore.messagelist.Message 9 | 10 | .. _messagetype: 11 | .. autoclass:: wayflowcore.messagelist.MessageType 12 | 13 | .. _messagecontent: 14 | .. autoclass:: wayflowcore.messagelist.MessageContent 15 | 16 | .. _textcontent: 17 | .. autoclass:: wayflowcore.messagelist.TextContent 18 | 19 | .. _imagecontent: 20 | .. autoclass:: wayflowcore.messagelist.ImageContent 21 | 22 | .. _messagelist: 23 | .. autoclass:: wayflowcore.messagelist.MessageList 24 | 25 | ExecutionStatus 26 | --------------- 27 | 28 | .. _executionstatus: 29 | .. autoclass:: wayflowcore.executors.executionstatus.ExecutionStatus 30 | 31 | .. _usermessagerequesttatus: 32 | .. autoclass:: wayflowcore.executors.executionstatus.UserMessageRequestStatus 33 | 34 | .. _finishedexecutionstatus: 35 | .. autoclass:: wayflowcore.executors.executionstatus.FinishedStatus 36 | 37 | .. _toolrequestexecutionstatus: 38 | .. autoclass:: wayflowcore.executors.executionstatus.ToolRequestStatus 39 | 40 | Conversation 41 | ------------ 42 | 43 | Base class for conversations. Can manipulate a conversation object, and can be serialized/deserialized. 44 | 45 | .. _conversationalcomponent: 46 | .. autoclass:: wayflowcore.conversationalcomponent.ConversationalComponent 47 | 48 | .. _conversation: 49 | .. autoclass:: wayflowcore.conversation.Conversation 50 | 51 | Execution Plan 52 | -------------- 53 | 54 | .. autoclass:: wayflowcore.planning.ExecutionPlan 55 | 56 | .. autoclass:: wayflowcore.planning.Task 57 | 58 | .. autoclass:: wayflowcore.planning.TaskStatus 59 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/api/prompttemplate.rst: -------------------------------------------------------------------------------- 1 | PromptTemplate 2 | ============== 3 | 4 | This page presents all APIs and classes related to prompt Templates. 5 | 6 | .. _prompttemplate: 7 | .. autoclass:: wayflowcore.templates.template.PromptTemplate 8 | 9 | OutputParser 10 | ------------ 11 | 12 | .. _outputparser: 13 | .. autoclass:: wayflowcore.outputparser.OutputParser 14 | 15 | .. _regexoutputparser: 16 | .. autoclass:: wayflowcore.outputparser.RegexOutputParser 17 | 18 | .. _regexpattern: 19 | .. autoclass:: wayflowcore.outputparser.RegexPattern 20 | 21 | .. _jsonoutputparser: 22 | .. autoclass:: wayflowcore.outputparser.JsonOutputParser 23 | 24 | .. _tooloutputparser: 25 | .. autoclass:: wayflowcore.outputparser.ToolOutputParser 26 | 27 | 28 | Message transforms 29 | ------------------ 30 | 31 | .. _messagetransform: 32 | .. autoclass:: wayflowcore.transforms.MessageTransform 33 | 34 | .. autoclass:: wayflowcore.transforms.CoalesceSystemMessagesTransform 35 | 36 | .. autoclass:: wayflowcore.transforms.RemoveEmptyNonUserMessageTransform 37 | 38 | .. autoclass:: wayflowcore.transforms.AppendTrailingSystemMessageToUserMessageTransform 39 | 40 | .. autoclass:: wayflowcore.transforms.SplitPromptOnMarkerMessageTransform 41 | 42 | 43 | Helpers 44 | ------- 45 | 46 | .. _prompttemplatehelpers: 47 | .. autofunction:: wayflowcore.templates.structuredgeneration.adapt_prompt_template_for_json_structured_generation 48 | 49 | .. autoclass:: wayflowcore._utils._templating_helpers.ToolRequestAsDictT 50 | 51 | .. autoclass:: wayflowcore._utils._templating_helpers.ToolResultAsDictT 52 | 53 | .. autoclass:: wayflowcore._utils._templating_helpers.MessageAsDictT 54 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/serialization/stepserialization.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | import logging 8 | from typing import TYPE_CHECKING, Any, Dict, cast 9 | 10 | from deprecated import deprecated 11 | 12 | if TYPE_CHECKING: 13 | from wayflowcore.serialization.context import DeserializationContext, SerializationContext 14 | from wayflowcore.steps.step import Step 15 | 16 | logger = logging.getLogger(__name__) 17 | 18 | 19 | @deprecated( 20 | "`serialize_step_to_dict` is deprecated. Please use `serialize_to_dict(Step, ...)` instead." 21 | ) 22 | def serialize_step_to_dict( 23 | step: "Step", serialization_context: "SerializationContext" 24 | ) -> Dict[str, Any]: 25 | """ 26 | Converts a step to a nested dict of standard types such that it can be easily serialized with either JSON or YAML 27 | 28 | Parameters 29 | ---------- 30 | step: 31 | The Step that is intended to be serialized 32 | serialization_context: 33 | Context for serialization operations. 34 | """ 35 | return step._serialize_to_dict(serialization_context) 36 | 37 | 38 | @deprecated( 39 | "`deserialize_step_from_dict` is deprecated. Please use `deserialize_from_dict(Step, ...)` instead." 40 | ) 41 | def deserialize_step_from_dict( 42 | step_as_dict: Dict[str, Any], deserialization_context: "DeserializationContext" 43 | ) -> "Step": 44 | return cast(Step, Step._deserialize_from_dict(step_as_dict, deserialization_context)) 45 | -------------------------------------------------------------------------------- /wayflowcore/tests/agentspec/configs/agent_4.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | $referenced_components: 8 | 4660ecdd-d26f-4fe3-88d0-00fde69e24ba: 9 | component_type: OllamaConfig 10 | default_generation_parameters: null 11 | description: null 12 | id: 4660ecdd-d26f-4fe3-88d0-00fde69e24ba 13 | metadata: {} 14 | model_id: llama3.1 15 | name: llama-3.1 16 | url: OLLAMA8BV31_API_ENDPOINT 17 | agents: [] 18 | component_type: Agent 19 | description: null 20 | flows: [] 21 | id: 5140714a-326b-4029-83b1-72e37a202b9a 22 | inputs: [] 23 | llm_config: 24 | $component_ref: 4660ecdd-d26f-4fe3-88d0-00fde69e24ba 25 | metadata: {} 26 | name: Oracle Agent 27 | outputs: [] 28 | system_prompt: "Oracle Cloud Infrastructure (OCI) is the next-generation cloud designed\ 29 | \ to run any application, faster and more securely, for less.\n\n Oracle Cloud\ 30 | \ spans 50 interconnected geographic commercial and government cloud regions. Unlike\ 31 | \ other providers, each region offers a consistent set of more than 150 Oracle Cloud\ 32 | \ Infrastructure services, with consistent low pricing worldwide.\n For more\ 33 | \ complete support of customer cloud strategies, Oracle Cloud also offers a full\ 34 | \ suite of Oracle Cloud Applications and direct interconnections with Microsoft\ 35 | \ Azure and Google Cloud.\n\n You are a helpful Oracle agent. Please assist the user with any request.\ 36 | \ Be polite in your answers." 37 | tools: [] 38 | agentspec_version: 25.4.1 39 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/agentspec/components/tools.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from typing import Any, Dict 8 | 9 | from pyagentspec.tools import ToolBox 10 | from pydantic import BaseModel 11 | 12 | from wayflowcore.agentspec.components._pydantic_plugins import ( 13 | PydanticComponentDeserializationPlugin, 14 | PydanticComponentSerializationPlugin, 15 | ) 16 | 17 | 18 | class PluginToolBox(ToolBox): 19 | """ 20 | Class to expose a list of tools to agentic components. 21 | 22 | ToolBox is dynamic which means that agentic components equipped 23 | with a toolbox can may see its tools to evolve throughout its 24 | execution. 25 | 26 | .. tip:: 27 | 28 | Agent Spec now natively supports ``ToolBox`` which should be preferred to using ``PluginToolBox``. 29 | """ 30 | 31 | 32 | class PluginToolRequest(BaseModel): 33 | name: str 34 | args: Dict[str, Any] 35 | tool_request_id: str 36 | 37 | 38 | class PluginToolResult(BaseModel): 39 | content: Any 40 | tool_request_id: str 41 | 42 | 43 | TOOLS_PLUGIN_NAME = "ToolPlugin" 44 | 45 | tools_serialization_plugin = PydanticComponentSerializationPlugin( 46 | name=TOOLS_PLUGIN_NAME, 47 | component_types_and_models={ 48 | PluginToolBox.__name__: PluginToolBox, 49 | }, 50 | ) 51 | tools_deserialization_plugin = PydanticComponentDeserializationPlugin( 52 | name=TOOLS_PLUGIN_NAME, 53 | component_types_and_models={ 54 | PluginToolBox.__name__: PluginToolBox, 55 | }, 56 | ) 57 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/tools/toolbox.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from abc import abstractmethod 8 | from dataclasses import dataclass, field 9 | from typing import TYPE_CHECKING, Sequence 10 | 11 | from wayflowcore.component import Component 12 | from wayflowcore.idgeneration import IdGenerator 13 | 14 | if TYPE_CHECKING: 15 | from wayflowcore.tools import Tool 16 | 17 | 18 | @dataclass 19 | class ToolBox(Component): 20 | """ 21 | Class to expose a list of tools to agentic components. 22 | 23 | ToolBox is dynamic which means that agentic components equipped 24 | with a toolbox can may see its tools to evolve throughout its 25 | execution. 26 | """ 27 | 28 | id: str = field(default_factory=IdGenerator.get_or_generate_id, compare=False, hash=False) 29 | 30 | @abstractmethod 31 | def get_tools(self) -> Sequence["Tool"]: 32 | """ 33 | Return the list of tools exposed by the ``ToolBox``. 34 | 35 | Will be called at every iteration in the execution loop 36 | of agentic components. 37 | """ 38 | 39 | @abstractmethod 40 | async def get_tools_async(self) -> Sequence["Tool"]: 41 | """ 42 | Return the list of tools exposed by the ``ToolBox`` in an asynchronous manner. 43 | 44 | Will be called at every iteration in the execution loop 45 | of agentic components. 46 | """ 47 | 48 | @property 49 | def might_yield(self) -> bool: 50 | return any(t.might_yield for t in self.get_tools()) 51 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/tracing/spanexporter.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from abc import ABC, abstractmethod 8 | from typing import List 9 | 10 | from wayflowcore.tracing.span import Span 11 | 12 | 13 | class SpanExporter(ABC): 14 | """Interface for exporting spans. 15 | 16 | Interface to be implemented by services that want to export in their own format 17 | the spans being recorded. 18 | """ 19 | 20 | @abstractmethod 21 | def export(self, spans: List[Span], mask_sensitive_information: bool = True) -> None: 22 | """ 23 | Exports a batch of telemetry data. 24 | 25 | Parameters 26 | ---------- 27 | spans: 28 | The spans to be exported 29 | mask_sensitive_information 30 | Whether to mask potentially sensitive information from the span and its events 31 | """ 32 | 33 | @abstractmethod 34 | def startup(self) -> None: 35 | """Start the exporter.""" 36 | 37 | @abstractmethod 38 | def shutdown(self) -> None: 39 | """Shut down the exporter.""" 40 | 41 | @abstractmethod 42 | def force_flush(self, timeout_millis: int = 30000) -> bool: 43 | """ 44 | Ensure that all the pending exports are completed as soon as possible. 45 | 46 | Parameters 47 | ---------- 48 | timeout_millis: 49 | The time conceded to perform the flush 50 | 51 | Returns 52 | ------- 53 | False if the timeout is exceeded, True otherwise 54 | """ 55 | -------------------------------------------------------------------------------- /wayflowcore/testing_scripts/run_repl_from_serialized_graph.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2024, 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | # Usage: 8 | # ``` 9 | # > python run_repl_from_serialized_flow.py path/to/config/file.yaml 10 | # ``` 11 | 12 | import sys 13 | 14 | from wayflowcore.executors.executionstatus import FinishedStatus 15 | from wayflowcore.flow import Flow 16 | from wayflowcore.messagelist import MessageType 17 | from wayflowcore.serialization import deserialize 18 | 19 | # needed for registration 20 | 21 | if __name__ == "__main__": 22 | serialized_flow_file_path = sys.argv[1] 23 | with open(serialized_flow_file_path) as serialized_flow_file: 24 | serialized_flow = serialized_flow_file.read() 25 | assistant = deserialize(Flow, serialized_flow) 26 | conversation = assistant.start_conversation() 27 | user_input, finished = None, False 28 | 29 | print() 30 | message_idx = 0 31 | while not finished: 32 | user_input = input("\nUSER >>> ") 33 | conversation.append_user_message(user_input) 34 | message_idx += 1 35 | status = conversation.execute() 36 | finished = isinstance(status, FinishedStatus) 37 | messages = conversation.get_messages() 38 | for message in messages[message_idx:]: 39 | if message.message_type == MessageType.TOOL_REQUEST: 40 | print(f"\n{message.message_type.value} >>> {message.tool_requests}") 41 | else: 42 | print(f"\n{message.message_type.value} >>> {message.content}") 43 | message_idx = len(messages) 44 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/api/events.rst: -------------------------------------------------------------------------------- 1 | .. _events: 2 | 3 | Events 4 | ====== 5 | 6 | This page presents all APIs and classes related to events in WayFlow. 7 | 8 | Events 9 | ------ 10 | 11 | .. _event: 12 | .. autoclass:: wayflowcore.events.event.Event 13 | 14 | .. _llmgenerationrequestevent: 15 | .. autoclass:: wayflowcore.events.event.LlmGenerationRequestEvent 16 | 17 | .. _llmgenerationresponseevent: 18 | .. autoclass:: wayflowcore.events.event.LlmGenerationResponseEvent 19 | 20 | .. _conversationalcomponentexecutionstartedevent: 21 | .. autoclass:: wayflowcore.events.event.ConversationalComponentExecutionStartedEvent 22 | 23 | .. _conversationalcomponentexecutionfinishedevent: 24 | .. autoclass:: wayflowcore.events.event.ConversationalComponentExecutionFinishedEvent 25 | 26 | .. _conversationcreatedevent: 27 | .. autoclass:: wayflowcore.events.event.ConversationCreatedEvent 28 | 29 | .. _conversationmessageaddedevent: 30 | .. autoclass:: wayflowcore.events.event.ConversationMessageAddedEvent 31 | 32 | .. _agentnextactiondecisionstartevent: 33 | .. autoclass:: wayflowcore.events.event.AgentNextActionDecisionStartEvent 34 | 35 | .. _agentdecidednextactionevent: 36 | .. autoclass:: wayflowcore.events.event.AgentDecidedNextActionEvent 37 | 38 | 39 | Event Listeners 40 | --------------- 41 | 42 | .. _eventlistener: 43 | .. autoclass:: wayflowcore.events.eventlistener.EventListener 44 | 45 | .. _genericeventlistener: 46 | .. autoclass:: wayflowcore.events.eventlistener.GenericEventListener 47 | 48 | .. _registereventlisteners: 49 | .. autofunction:: wayflowcore.events.eventlistener.register_event_listeners 50 | 51 | .. _geteventlisteners: 52 | .. autofunction:: wayflowcore.events.eventlistener.get_event_listeners 53 | 54 | .. _recordevent: 55 | .. autofunction:: wayflowcore.events.eventlistener.record_event 56 | -------------------------------------------------------------------------------- /wayflowcore/tests/agentspec/configs/mcp_agent.yaml: -------------------------------------------------------------------------------- 1 | component_type: ExtendedAgent 2 | id: 968c6098-44fc-4921-90b7-32aaf1db849e 3 | name: mcp_agent 4 | description: null 5 | metadata: {} 6 | inputs: [] 7 | outputs: [] 8 | llm_config: 9 | component_type: VllmConfig 10 | id: da3d4cf4-6431-4e66-b4f6-47bc1af578af 11 | name: llm_model 12 | description: null 13 | metadata: {} 14 | default_generation_parameters: null 15 | url: remote/url 16 | model_id: gemma 17 | system_prompt: you are a helpful assistant 18 | tools: 19 | - component_type: MCPTool 20 | id: 0a201a3e-d71a-477f-b95e-007ba44fce2e 21 | name: fooza_tool 22 | description: some tool to compute the fooza operation 23 | metadata: {} 24 | inputs: [] 25 | outputs: [] 26 | client_transport: 27 | $component_ref: 22a99832-458d-4993-b95a-f94870f70a3a 28 | toolboxes: 29 | - component_type: PluginMCPToolBox 30 | id: e23b3cbf-d9b9-4020-adde-3ff06b148c55 31 | name: toolbox 32 | description: null 33 | metadata: {} 34 | client_transport: 35 | $component_ref: 22a99832-458d-4993-b95a-f94870f70a3a 36 | tool_filter: null 37 | component_plugin_name: MCPPlugin 38 | component_plugin_version: 25.4.0 39 | context_providers: null 40 | can_finish_conversation: false 41 | max_iterations: 10 42 | initial_message: Hi! How can I help you? 43 | caller_input_mode: always 44 | agents: [] 45 | flows: [] 46 | agent_template: null 47 | component_plugin_name: AgentPlugin 48 | component_plugin_version: 25.4.0 49 | $referenced_components: 50 | 22a99832-458d-4993-b95a-f94870f70a3a: 51 | component_type: SSETransport 52 | id: 22a99832-458d-4993-b95a-f94870f70a3a 53 | name: transport 54 | description: null 55 | metadata: {} 56 | url: MCP_SERVER_URL 57 | headers: null 58 | timeout: 5 59 | sse_read_timeout: 300 60 | agentspec_version: 25.4.1 61 | -------------------------------------------------------------------------------- /wayflowcore/tests/datastores/entities.json: -------------------------------------------------------------------------------- 1 | { 2 | "employees": [ 3 | { 4 | "ID": 1, 5 | "name": "Dwayne Chute", 6 | "email": "dwayne@dudemuffin.com", 7 | "department_area": "Utica, NY", 8 | "department_name": "sales", 9 | "salary": 120000.0 10 | }, 11 | { 12 | "ID": 2, 13 | "name": "Joe Happens", 14 | "email": "joe@dudemuffin.com", 15 | "department_area": "Utica, NY", 16 | "department_name": "sales", 17 | "salary": 120500.0 18 | }, 19 | { 20 | "ID": 3, 21 | "name": "Pamela Beefly", 22 | "email": "pam@dudemuffin.com", 23 | "department_area": "Utica, NY", 24 | "department_name": "reception", 25 | "salary": 95000.0 26 | }, 27 | { 28 | "ID": 4, 29 | "name": "Mike Swat", 30 | "email": "mikeswat@dudemuffin.com", 31 | "department_area": "Utica, NY", 32 | "department_name": "sales", 33 | "salary": 150000.0 34 | } 35 | ], 36 | "departments": [ 37 | { 38 | "department_name": "sales", 39 | "area": "Utica, NY", 40 | "regional_manager": 3, 41 | "assistant_to_the_regional_manager": 1 42 | }, 43 | { 44 | "department_name": "reception", 45 | "area": "Utica, NY", 46 | "regional_manager": 3, 47 | "assistant_to_the_regional_manager": null 48 | }, 49 | { 50 | "department_name": "accounting", 51 | "area": "Utica, NY", 52 | "regional_manager": 3, 53 | "assistant_to_the_regional_manager": null 54 | } 55 | ] 56 | } 57 | -------------------------------------------------------------------------------- /wayflowcore/tests/agentspec/configs/agent_1.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | $referenced_components: 8 | 4660ecdd-d26f-4fe3-88d0-00fde69e24ba: 9 | component_type: VllmConfig 10 | default_generation_parameters: null 11 | description: null 12 | id: 4660ecdd-d26f-4fe3-88d0-00fde69e24ba 13 | metadata: {} 14 | model_id: /storage/models/Llama-3.1-70B-Instruct 15 | name: llama-3.1-70b-instruct 16 | url: LLAMA70B_API_URL 17 | agents: [] 18 | component_type: Agent 19 | description: Example of Agent 20 | flows: [] 21 | id: 5140714a-326b-4029-83b1-72e37a202b9a 22 | inputs: [] 23 | llm_config: 24 | $component_ref: 4660ecdd-d26f-4fe3-88d0-00fde69e24ba 25 | metadata: {} 26 | name: Oracle Agent 27 | outputs: [] 28 | system_prompt: "Oracle Cloud Infrastructure (OCI) is the next-generation cloud designed\ 29 | \ to run any application, faster and more securely, for less.\n\n Oracle Cloud\ 30 | \ spans 50 interconnected geographic commercial and government cloud regions. Unlike\ 31 | \ other providers, each region offers a consistent set of more than 150 Oracle Cloud\ 32 | \ Infrastructure services, with consistent low pricing worldwide.\n For more\ 33 | \ complete support of customer cloud strategies, Oracle Cloud also offers a full\ 34 | \ suite of Oracle Cloud Applications and direct interconnections with Microsoft\ 35 | \ Azure and Google Cloud.\n\n Not all clouds are created equal. \n\ 36 | \n You are a helpful OCI agent. Please assist the user with any request.\ 37 | \ Be polite in your answers." 38 | tools: [] 39 | agentspec_version: 25.4.1 40 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/api/agent.rst: -------------------------------------------------------------------------------- 1 | Agents 2 | ====== 3 | 4 | This page presents all APIs and classes related to WayFlow agents. 5 | 6 | 7 | .. |agentspec-icon| image:: ../../_static/icons/agentspec-icon.svg 8 | :width: 100px 9 | 10 | .. grid:: 1 11 | 12 | .. grid-item-card:: |agentspec-icon| 13 | :link: https://oracle.github.io/agent-spec/api/agent.html 14 | :link-alt: Agent Spec - Agents API Reference 15 | 16 | Visit the Agent Spec API Documentation to learn more about Agent Components. 17 | 18 | 19 | .. tip:: 20 | 21 | Click the button above ↑ to visit the `Agent Spec Documentation `_ 22 | 23 | 24 | Agent related classes 25 | --------------------- 26 | 27 | Agent class 28 | ~~~~~~~~~~~ 29 | 30 | .. _agent: 31 | .. autoclass:: wayflowcore.agent.Agent 32 | :exclude-members: execute 33 | 34 | OCI Agent class 35 | ~~~~~~~~~~~~~~~ 36 | 37 | .. _ociagent: 38 | .. autoclass:: wayflowcore.ociagent.OciAgent 39 | :exclude-members: execute 40 | 41 | A2A Agent class 42 | ~~~~~~~~~~~~~~~ 43 | 44 | .. _a2aagent: 45 | .. autoclass:: wayflowcore.a2a.a2aagent.A2AAgent 46 | :exclude-members: execute 47 | 48 | DescribedFlow 49 | ~~~~~~~~~~~~~ 50 | 51 | .. _describedflow: 52 | .. autoclass:: wayflowcore.tools.DescribedFlow 53 | 54 | DescribedAgent 55 | ~~~~~~~~~~~~~~ 56 | 57 | .. _describedassistant: 58 | .. autoclass:: wayflowcore.tools.DescribedAgent 59 | 60 | Swarm class 61 | ~~~~~~~~~~~ 62 | 63 | .. _swarm: 64 | .. autoclass:: wayflowcore.swarm.Swarm 65 | 66 | ManagerWorkers class 67 | ~~~~~~~~~~~~~~~~~~~~ 68 | 69 | .. _managerworkers: 70 | .. autoclass:: wayflowcore.managerworkers.ManagerWorkers 71 | 72 | 73 | Agent Behavior Configuration 74 | ---------------------------- 75 | 76 | .. _callerinputmode: 77 | .. autoclass:: wayflowcore.agent.CallerInputMode 78 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/embeddingmodels/vllmmodel.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from wayflowcore.embeddingmodels.openaicompatiblemodel import OpenAICompatibleEmbeddingModel 8 | from wayflowcore.serialization.serializer import SerializableObject 9 | 10 | 11 | class VllmEmbeddingModel(OpenAICompatibleEmbeddingModel, SerializableObject): 12 | """ 13 | Embedding model for self-hosted models via vLLM. 14 | 15 | Parameters 16 | ---------- 17 | base_url 18 | The complete URL of the vLLM server (e.g., "http://localhost:8000" or "https://secure-vllm.example.com"). 19 | Both HTTP and HTTPS protocols are supported. 20 | model_id 21 | The name of the model to use on the server. 22 | 23 | Examples 24 | -------- 25 | >>> from wayflowcore.embeddingmodels.vllmmodel import VllmEmbeddingModel # doctest: +SKIP 26 | >>> # Using HTTP 27 | >>> model = VllmEmbeddingModel(url="http://localhost:8000", model_id="hosted-model-name") # doctest: +SKIP 28 | >>> # Using HTTPS 29 | >>> secure_model = VllmEmbeddingModel(url="https://secure-vllm.example.com", model_id="hosted-model-name") # doctest: +SKIP 30 | >>> embeddings = model.embed(["WayFlow is a framework to develop and run LLM-based assistants."]) # doctest: +SKIP 31 | 32 | Notes 33 | ----- 34 | This provider makes HTTP/HTTPS POST requests to the /v1/embeddings endpoint of the specified URL. 35 | When using HTTPS, certificate verification is performed by default. For self-signed certificates, 36 | additional configuration may be needed at the application level. 37 | """ 38 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/executors/_executor.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from __future__ import annotations 8 | 9 | from abc import ABC, abstractmethod 10 | from typing import TYPE_CHECKING, Optional, Sequence 11 | 12 | if TYPE_CHECKING: 13 | from wayflowcore.conversation import Conversation 14 | from wayflowcore.executors.executionstatus import ExecutionStatus 15 | from wayflowcore.executors.interrupts.executioninterrupt import ( 16 | ExecutionInterrupt, 17 | InterruptedExecutionStatus, 18 | ) 19 | 20 | 21 | class ExecutionInterruptedException(Exception): 22 | 23 | def __init__(self, execution_status: InterruptedExecutionStatus): 24 | super().__init__("Execution interrupted") 25 | self.execution_status: InterruptedExecutionStatus = execution_status 26 | 27 | 28 | class ConversationExecutor(ABC): 29 | """Base Executor class. An executor is stateless, and exposes an execute method on the conversation.""" 30 | 31 | @staticmethod 32 | @abstractmethod 33 | async def execute_async( 34 | conversation: "Conversation", 35 | execution_interrupts: Optional[Sequence["ExecutionInterrupt"]] = None, 36 | ) -> ExecutionStatus: 37 | """ 38 | Runs a conversation given a list of messages and a state. The state is specific to the type of 39 | conversation (can be agent-based or flow-based). 40 | 41 | Parameters 42 | ---------- 43 | conversation: 44 | A conversation object 45 | execution_interrupts: 46 | List of execution interrupts 47 | """ 48 | -------------------------------------------------------------------------------- /.gitlab/jobs/templates/get_merge_request_id.yml: -------------------------------------------------------------------------------- 1 | .get_merge_request_id: 2 | script: 3 | - | 4 | #!/bin/bash 5 | 6 | # Encode the branch name 7 | ENCODED_BRANCH_NAME=$(echo -n "${CI_COMMIT_REF_NAME}" | sed 's|/|%2F|g') 8 | API_URL="$GITLAB_URL/projects/$CI_PROJECT_ID" 9 | 10 | echo "Checking merge requests for branch: '${CI_COMMIT_REF_NAME}'" 11 | 12 | # Temporary file for HTTP response 13 | HTTP_RESPONSE=$(mktemp) 14 | 15 | # Make API call and capture response + HTTP code 16 | HTTP_STATUS=$(curl -s -o "$HTTP_RESPONSE" -w "%{http_code}" \ 17 | --header "PRIVATE-TOKEN: $GITLAB_BOT_TOKEN" \ 18 | "${API_URL}/merge_requests?state=opened&source_branch=$ENCODED_BRANCH_NAME") 19 | 20 | if [ "$HTTP_STATUS" -ne 200 ]; then 21 | echo "Error: Received HTTP status $HTTP_STATUS when fetching merge requests. Exiting." 22 | cat "$HTTP_RESPONSE" 23 | rm "$HTTP_RESPONSE" 24 | exit 1 25 | fi 26 | 27 | RESPONSE=$(cat "$HTTP_RESPONSE") 28 | rm "$HTTP_RESPONSE" 29 | 30 | # Count merge requests by counting occurrences of "iid" 31 | MR_COUNT=$(echo "$RESPONSE" | grep -o '"iid":' | wc -l) 32 | 33 | if [ "$MR_COUNT" -eq 0 ]; then 34 | echo "No merge requests found for branch '${CI_COMMIT_REF_NAME}'." 35 | exit 1 36 | elif [ "$MR_COUNT" -gt 1 ]; then 37 | echo "Error: More than one merge request ($MR_COUNT) is open for branch '${CI_COMMIT_REF_NAME}' in $CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME." 38 | exit 1 39 | else 40 | echo "One merge request found for branch '${CI_COMMIT_REF_NAME}'." 41 | MR_ID=$(echo "$RESPONSE" | grep -o '"iid":[0-9]*' | head -n1 | cut -d ':' -f2) 42 | export PUBLIC_MERGE_REQUEST_ID="$MR_ID" 43 | echo "PUBLIC_MERGE_REQUEST_ID='$PUBLIC_MERGE_REQUEST_ID'" 44 | fi -------------------------------------------------------------------------------- /wayflowcore/tests/integration/steps/test_constant_values_step.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from datetime import datetime 8 | 9 | import pytest 10 | 11 | from wayflowcore.flowhelpers import run_step_and_return_outputs 12 | from wayflowcore.property import IntegerProperty 13 | from wayflowcore.steps import ConstantValuesStep 14 | 15 | 16 | @pytest.mark.parametrize( 17 | "constant_values", 18 | [ 19 | {"int_number": 3}, 20 | {"int_number_1": 3, "int_number_2": 4}, 21 | {"float_number": 3.13, "int_number": 4, "bool_value": True, "string_value": "string"}, 22 | ], 23 | ) 24 | def test_different_constant_values(constant_values): 25 | step = ConstantValuesStep(constant_values) 26 | output = run_step_and_return_outputs(step, inputs={}) 27 | assert output == constant_values 28 | 29 | 30 | @pytest.mark.parametrize( 31 | "constant_values", 32 | [ 33 | {"list": [1, 2, 3]}, 34 | {"datetime": datetime(year=2025, month=1, day=1)}, 35 | {"dict": {"a": 1, "b": 1}}, 36 | ], 37 | ) 38 | def test_constant_values_negative(constant_values): 39 | with pytest.raises(ValueError): 40 | step = ConstantValuesStep(constant_values) 41 | 42 | 43 | def test_override_output_descriptors(): 44 | constant_values = { 45 | "value": True, 46 | } 47 | step = ConstantValuesStep( 48 | constant_values=constant_values, output_descriptors=[IntegerProperty(name="value")] 49 | ) 50 | output = run_step_and_return_outputs(step, inputs={}) 51 | assert isinstance(output["value"], int) 52 | assert output["value"] == 1 53 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Reporting Security Vulnerabilities 2 | 3 | Oracle values the independent security research community and believes that 4 | responsible disclosure of security vulnerabilities helps us ensure the security 5 | and privacy of all our users. 6 | 7 | Please do NOT raise a GitHub Issue to report a security vulnerability. If you 8 | believe you have found a security vulnerability, please submit a report to 9 | [secalert_us@oracle.com][1] preferably with a proof of concept. Please review 10 | some additional information on [how to report security vulnerabilities to Oracle][2]. 11 | We encourage people who contact Oracle Security to use email encryption using 12 | [our encryption key][3]. 13 | 14 | We ask that you do not use other channels or contact the project maintainers 15 | directly. 16 | 17 | Non-vulnerability related security issues including ideas for new or improved 18 | security features are welcome on GitHub Issues. 19 | 20 | ## Security updates, alerts and bulletins 21 | 22 | Security updates will be released on a regular cadence. Many of our projects 23 | will typically release security fixes in conjunction with the 24 | Oracle Critical Patch Update program. Additional 25 | information, including past advisories, is available on our [security alerts][4] 26 | page. 27 | 28 | ## Security-related information 29 | 30 | We will provide security related information such as a threat model, considerations 31 | for secure use, or any known security issues in our documentation. Please note 32 | that labs and sample code are intended to demonstrate a concept and may not be 33 | sufficiently hardened for production use. 34 | 35 | [1]: mailto:secalert_us@oracle.com 36 | [2]: https://www.oracle.com/corporate/security-practices/assurance/vulnerability/reporting.html 37 | [3]: https://www.oracle.com/security-alerts/encryptionkey.html 38 | [4]: https://www.oracle.com/security-alerts/ 39 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/embeddingmodels/ollamamodel.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from wayflowcore.embeddingmodels.openaicompatiblemodel import OpenAICompatibleEmbeddingModel 8 | from wayflowcore.serialization.serializer import SerializableObject 9 | 10 | 11 | class OllamaEmbeddingModel(OpenAICompatibleEmbeddingModel, SerializableObject): 12 | """ 13 | Embedding model for self-hosted models via Ollama. 14 | 15 | Parameters 16 | ---------- 17 | base_url 18 | The complete URL of the Ollama server (e.g., "http://localhost:11434" or "https://ollama.example.com"). 19 | Both HTTP and HTTPS protocols are supported. 20 | model_id 21 | The name of the model to use on the Ollama server. 22 | 23 | Examples 24 | -------- 25 | >>> from wayflowcore.embeddingmodels.ollamamodel import OllamaEmbeddingModel # doctest: +SKIP 26 | >>> # Using HTTP 27 | >>> model = OllamaEmbeddingModel(url="http://localhost:11434", model_id="nomic-embed-text") # doctest: +SKIP 28 | >>> # Using HTTPS 29 | >>> secure_model = OllamaEmbeddingModel(url="https://ollama.example.com", model_id="nomic-embed-text") # doctest: +SKIP 30 | >>> embeddings = model.embed(["WayFlow is a framework to develop and run LLM-based assistants."]) # doctest: +SKIP 31 | 32 | Notes 33 | ----- 34 | This provider makes HTTP/HTTPS POST requests to the /v1/embeddings endpoint of the specified URL. 35 | When using HTTPS, certificate verification is performed by default. For self-signed certificates, 36 | additional configuration may be needed at the application level. 37 | """ 38 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/config_examples/howto_async.json: -------------------------------------------------------------------------------- 1 | { 2 | "component_type": "Agent", 3 | "id": "7017dd89-e176-476f-a655-06fce4310399", 4 | "name": "agent_0f9ffda8__auto", 5 | "description": "", 6 | "metadata": { 7 | "__metadata_info__": {} 8 | }, 9 | "inputs": [ 10 | { 11 | "description": "\"query\" input variable for the template", 12 | "title": "query", 13 | "type": "string" 14 | } 15 | ], 16 | "outputs": [], 17 | "llm_config": { 18 | "component_type": "VllmConfig", 19 | "id": "2ceded67-85f7-4e47-be6c-2278f33f54f3", 20 | "name": "LLAMA_MODEL_ID", 21 | "description": null, 22 | "metadata": { 23 | "__metadata_info__": {} 24 | }, 25 | "default_generation_parameters": null, 26 | "url": "LLAMA_API_URL", 27 | "model_id": "LLAMA_MODEL_ID" 28 | }, 29 | "system_prompt": "You are a helpful assistant, answering the user request about {{query}}", 30 | "tools": [ 31 | { 32 | "component_type": "ServerTool", 33 | "id": "bd53ed97-2f4b-4936-99fa-0c5b43d00a90", 34 | "name": "heavy_work", 35 | "description": "Performs heavy CPU-bound work.", 36 | "metadata": { 37 | "__metadata_info__": {} 38 | }, 39 | "inputs": [], 40 | "outputs": [ 41 | { 42 | "title": "tool_output", 43 | "type": "string" 44 | } 45 | ] 46 | }, 47 | { 48 | "component_type": "ServerTool", 49 | "id": "e87b2e06-70db-4439-b653-02978390fa36", 50 | "name": "remote_call", 51 | "description": "Performs remote API calls (I/O-bound).", 52 | "metadata": { 53 | "__metadata_info__": {} 54 | }, 55 | "inputs": [], 56 | "outputs": [ 57 | { 58 | "title": "tool_output", 59 | "type": "string" 60 | } 61 | ] 62 | } 63 | ], 64 | "agentspec_version": "25.4.1" 65 | } 66 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/executors/_a2aagentconversation.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from dataclasses import dataclass 8 | from textwrap import dedent 9 | from typing import TYPE_CHECKING, List 10 | 11 | from wayflowcore.a2a.a2aagent import A2AAgent 12 | from wayflowcore.conversation import Conversation 13 | from wayflowcore.executors._a2aagentexecutor import A2AAgentState 14 | 15 | if TYPE_CHECKING: 16 | from wayflowcore.contextproviders import ContextProvider 17 | from wayflowcore.conversation import Conversation 18 | 19 | 20 | @dataclass 21 | class A2AAgentConversation(Conversation): 22 | component: A2AAgent 23 | state: A2AAgentState 24 | 25 | @property 26 | def current_step_name(self) -> str: 27 | return "a2a_agent" 28 | 29 | def _get_all_context_providers_from_parent_conversations(self) -> List["ContextProvider"]: 30 | return [] 31 | 32 | def _get_all_sub_conversations(self) -> List["Conversation"]: 33 | return [] 34 | 35 | def __repr__(self) -> str: 36 | return f"A2AAgentConversation({self.get_messages()})" 37 | 38 | def __str__(self) -> str: 39 | result = f"State: {self.state}\nList of messages:\n" 40 | 41 | for i, message in enumerate(self.message_list.messages): 42 | message_str = dedent( 43 | """ 44 | Message #{} 45 | Message type: {} 46 | Message content:\n 47 | {}\n 48 | """ 49 | ).format(i, message.message_type, message.content) 50 | 51 | result += message_str 52 | return result 53 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/code_examples/howto_a2aagent.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | # isort:skip_file 8 | # fmt: off 9 | # mypy: ignore-errors 10 | # docs-title: Code Example - How to Use A2A Agents 11 | 12 | # .. start-##_Creating_the_agent 13 | from wayflowcore.a2a.a2aagent import A2AAgent, A2AConnectionConfig 14 | 15 | agent = A2AAgent( 16 | agent_url="http://", 17 | connection_config=A2AConnectionConfig(verify=False) 18 | ) 19 | # .. end-##_Creating_the_agent 20 | agent: A2AAgent # docs-skiprow 21 | (agent,) = _update_globals(["a2a_agent"]) # docs-skiprow # type: ignore 22 | 23 | # .. start-##_Running_the_agent 24 | from wayflowcore.executors.executionstatus import UserMessageRequestStatus 25 | 26 | # With a linear conversation 27 | conversation = agent.start_conversation() 28 | 29 | conversation.append_user_message("What is the answer to 2+2?") 30 | status = conversation.execute() 31 | if isinstance(status, UserMessageRequestStatus): 32 | assistant_reply = conversation.get_last_message() 33 | print(f"---\nAssistant >>> {assistant_reply.content}\n---") 34 | else: 35 | print(f"Invalid execution status, expected UserMessageRequestStatus, received {type(status)}") 36 | # .. end-##_Running_the_agent 37 | 38 | # .. start-##_Export_config_to_Agent_Spec 39 | from wayflowcore.agentspec import AgentSpecExporter 40 | 41 | serialized_assistant = AgentSpecExporter().to_json(agent) 42 | # .. end-##_Export_config_to_Agent_Spec 43 | # .. start-##_Load_Agent_Spec_config 44 | from wayflowcore.agentspec import AgentSpecLoader 45 | 46 | agent: A2AAgent = AgentSpecLoader().load_json(serialized_assistant) 47 | # .. end-##_Load_Agent_Spec_config 48 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/models/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from ._requesthelpers import ( 8 | StreamChunkType, 9 | TaggedMessageChunkType, 10 | TaggedMessageChunkTypeWithTokenUsage, 11 | ) 12 | from .llmgenerationconfig import LlmGenerationConfig 13 | from .llmmodel import LlmCompletion, LlmModel, Prompt 14 | from .llmmodelfactory import LlmModelFactory 15 | from .ociclientconfig import ( 16 | OCIClientConfig, 17 | OCIClientConfigWithApiKey, 18 | OCIClientConfigWithInstancePrincipal, 19 | OCIClientConfigWithResourcePrincipal, 20 | OCIClientConfigWithSecurityToken, 21 | OCIClientConfigWithUserAuthentication, 22 | OCIUserAuthenticationConfig, 23 | ) 24 | from .ocigenaimodel import OCIGenAIModel 25 | from .ollamamodel import OllamaModel 26 | from .openaiapitype import OpenAIAPIType 27 | from .openaicompatiblemodel import OpenAICompatibleModel 28 | from .openaimodel import OpenAIModel 29 | from .vllmmodel import VllmModel 30 | 31 | __all__ = [ 32 | "LlmCompletion", 33 | "LlmGenerationConfig", 34 | "LlmModel", 35 | "LlmModelFactory", 36 | "OCIGenAIModel", 37 | "OllamaModel", 38 | "OpenAICompatibleModel", 39 | "OpenAIAPIType", 40 | "OpenAIModel", 41 | "Prompt", 42 | "StreamChunkType", 43 | "VllmModel", 44 | "TaggedMessageChunkType", 45 | "TaggedMessageChunkTypeWithTokenUsage", 46 | "OCIClientConfigWithApiKey", 47 | "OCIClientConfigWithSecurityToken", 48 | "OCIClientConfigWithInstancePrincipal", 49 | "OCIClientConfigWithResourcePrincipal", 50 | "OCIClientConfigWithUserAuthentication", 51 | "OCIUserAuthenticationConfig", 52 | "OCIClientConfig", 53 | ] 54 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/config_examples/tutorial_agent.json: -------------------------------------------------------------------------------- 1 | { 2 | "component_type": "Agent", 3 | "id": "61bd7075-4f41-4344-8e0d-1d6935975794", 4 | "name": "agent_58415549__auto", 5 | "description": "", 6 | "metadata": { 7 | "__metadata_info__": {} 8 | }, 9 | "inputs": [], 10 | "outputs": [], 11 | "llm_config": { 12 | "component_type": "VllmConfig", 13 | "id": "7796961b-db94-4a5e-bd12-8c532989fe0f", 14 | "name": "LLAMA_MODEL_ID", 15 | "description": null, 16 | "metadata": { 17 | "__metadata_info__": {} 18 | }, 19 | "default_generation_parameters": null, 20 | "url": "LLAMA_API_URL", 21 | "model_id": "LLAMA_MODEL_ID" 22 | }, 23 | "system_prompt": "You are a knowledgeable, factual, and helpful HR assistant that can answer simple HR-related questions like salary and benefits.\nYou are given a tool to look up the HR database.\nYour task:\n - Ask the user if they need assistance\n - Use the provided tool below to retrieve HR data\n - Based on the data you retrieved, answer the user's question\nImportant:\n - Be helpful and concise in your messages\n - Do not tell the user any details not mentioned in the tool response, let's be factual.", 24 | "tools": [ 25 | { 26 | "component_type": "ServerTool", 27 | "id": "c6d943c1-20a3-4f66-b89b-8173ab854e0b", 28 | "name": "search_hr_database", 29 | "description": "Function that searches the HR database for employee benefits.\n\nParameters\n----------\nquery:\n a query string\n\nReturns\n-------\n a JSON response", 30 | "metadata": { 31 | "__metadata_info__": {} 32 | }, 33 | "inputs": [ 34 | { 35 | "type": "string", 36 | "title": "query" 37 | } 38 | ], 39 | "outputs": [ 40 | { 41 | "type": "string", 42 | "title": "tool_output" 43 | } 44 | ] 45 | } 46 | ], 47 | "agentspec_version": "25.4.1" 48 | } 49 | -------------------------------------------------------------------------------- /LICENSE-UPL.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2025 Oracle and/or its affiliates. 2 | 3 | The Universal Permissive License (UPL), Version 1.0 4 | 5 | Subject to the condition set forth below, permission is hereby granted to any 6 | person obtaining a copy of this software, associated documentation and/or data 7 | (collectively the "Software"), free of charge and under any and all copyright 8 | rights in the Software, and any and all patent rights owned or freely 9 | licensable by each licensor hereunder covering either (i) the unmodified 10 | Software as contributed to or provided by such licensor, or (ii) the Larger 11 | Works (as defined below), to deal in both 12 | 13 | (a) the Software, and 14 | (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if 15 | one is included with the Software (each a "Larger Work" to which the Software 16 | is contributed by such licensors), 17 | 18 | without restriction, including without limitation the rights to copy, create 19 | derivative works of, display, perform, and distribute the Software and make, 20 | use, sell, offer for sale, import, export, have made, and have sold the 21 | Software and the Larger Work(s), and to sublicense the foregoing rights on 22 | either these or other terms. 23 | 24 | This license is subject to the following condition: 25 | The above copyright notice and either this complete permission notice or at 26 | a minimum a reference to the UPL must be included in all copies or 27 | substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 35 | SOFTWARE. -------------------------------------------------------------------------------- /wayflowcore/tests/agentspec/test_mapnode.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from typing import cast 8 | 9 | from wayflowcore.agentspec import AgentSpecExporter, AgentSpecLoader 10 | from wayflowcore.flow import Flow 11 | from wayflowcore.property import ListProperty, StringProperty 12 | from wayflowcore.steps import CompleteStep, MapStep, OutputMessageStep, StartStep 13 | 14 | from ..testhelpers.testhelpers import assert_flows_are_copies 15 | 16 | 17 | def test_mapstep_with_non_iterable_input_can_be_serialized_and_deserialized() -> None: 18 | 19 | message_incipit_property = StringProperty(name="message_incipit") 20 | i_property = StringProperty(name="i") 21 | iterated_input_property = ListProperty(name=MapStep.ITERATED_INPUT, item_type=i_property) 22 | 23 | output_step = OutputMessageStep( 24 | name="outputstep", 25 | message_template="{{message_incipit}}: {{i}}", 26 | ) 27 | 28 | start_step = StartStep(name="start", input_descriptors=[message_incipit_property, i_property]) 29 | map_step = MapStep( 30 | name="mapstep", 31 | flow=Flow.from_steps([start_step, output_step, CompleteStep("end")]), 32 | unpack_input={"i": "."}, 33 | input_descriptors=[iterated_input_property, message_incipit_property], 34 | ) 35 | 36 | outer_start_step = StartStep( 37 | name="start", input_descriptors=[message_incipit_property, iterated_input_property] 38 | ) 39 | flow = Flow.from_steps([outer_start_step, map_step, CompleteStep("end")]) 40 | agentspec_flow = AgentSpecExporter().to_json(flow) 41 | loaded_flow = cast(Flow, AgentSpecLoader().load_json(agentspec_flow)) 42 | 43 | assert_flows_are_copies(flow, loaded_flow) 44 | -------------------------------------------------------------------------------- /wayflowcore/tests/agentspec/configs/legacy/mcp_agent.yaml: -------------------------------------------------------------------------------- 1 | component_type: ExtendedAgent 2 | id: 968c6098-44fc-4921-90b7-32aaf1db849e 3 | name: mcp_agent 4 | description: null 5 | metadata: {} 6 | inputs: [] 7 | outputs: [] 8 | llm_config: 9 | component_type: VllmConfig 10 | id: da3d4cf4-6431-4e66-b4f6-47bc1af578af 11 | name: llm_model 12 | description: null 13 | metadata: {} 14 | default_generation_parameters: null 15 | url: remote/url 16 | model_id: gemma 17 | system_prompt: you are a helpful assistant 18 | tools: 19 | - component_type: PluginMCPTool 20 | id: 0a201a3e-d71a-477f-b95e-007ba44fce2e 21 | name: fooza_tool 22 | description: some tool to compute the fooza operation 23 | metadata: {} 24 | inputs: [] 25 | outputs: [] 26 | client_transport: 27 | $component_ref: 22a99832-458d-4993-b95a-f94870f70a3a 28 | component_plugin_name: MCPPlugin 29 | component_plugin_version: 25.4.0 30 | toolboxes: 31 | - component_type: PluginMCPToolBox 32 | id: e23b3cbf-d9b9-4020-adde-3ff06b148c55 33 | name: toolbox 34 | description: null 35 | metadata: {} 36 | client_transport: 37 | $component_ref: 22a99832-458d-4993-b95a-f94870f70a3a 38 | tool_filter: null 39 | component_plugin_name: MCPPlugin 40 | component_plugin_version: 25.4.0 41 | context_providers: null 42 | can_finish_conversation: false 43 | max_iterations: 10 44 | initial_message: Hi! How can I help you? 45 | caller_input_mode: always 46 | agents: [] 47 | flows: [] 48 | agent_template: null 49 | component_plugin_name: AgentPlugin 50 | component_plugin_version: 25.4.0 51 | $referenced_components: 52 | 22a99832-458d-4993-b95a-f94870f70a3a: 53 | component_type: PluginSSETransport 54 | id: 22a99832-458d-4993-b95a-f94870f70a3a 55 | name: transport 56 | description: null 57 | metadata: {} 58 | url: MCP_SERVER_URL 59 | headers: null 60 | timeout: 5 61 | sse_read_timeout: 300 62 | component_plugin_name: MCPPlugin 63 | component_plugin_version: 25.4.0 64 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/api/evaluation.rst: -------------------------------------------------------------------------------- 1 | .. _evaluation: 2 | 3 | Evaluation APIs 4 | =============== 5 | 6 | 7 | Assistant Evaluation 8 | -------------------- 9 | 10 | .. _evaluationtask: 11 | .. autoclass:: wayflowcore.evaluation.assistantevaluator.EvaluationTask 12 | 13 | .. _evaluationenvironment: 14 | .. autoclass:: wayflowcore.evaluation.assistantevaluator.EvaluationEnvironment 15 | 16 | .. _assistantevaluator: 17 | .. autoclass:: wayflowcore.evaluation.assistantevaluator.AssistantEvaluator 18 | 19 | .. _taskscorer: 20 | .. autoclass:: wayflowcore.evaluation.taskscorer.TaskScorer 21 | 22 | .. _runproxyconversation: 23 | .. autoclass:: wayflowcore.evaluation.assistantevaluator.run_proxy_agent_conversation 24 | 25 | .. _assistantevaluationresult: 26 | .. autoclass:: wayflowcore.evaluation.assistantevaluator.AssistantEvaluationResult 27 | 28 | .. _humanproxyassistant: 29 | .. autoclass:: wayflowcore.evaluation.assistantevaluator.HumanProxyAssistant 30 | 31 | Conversation Evaluation 32 | ----------------------- 33 | 34 | .. _conversationevaluator: 35 | .. autoclass:: wayflowcore.evaluation.conversationevaluator.ConversationEvaluator 36 | 37 | .. _conversationscorer: 38 | .. autoclass:: wayflowcore.evaluation.conversationscorer.ConversationScorer 39 | 40 | .. _usefullnessscorer: 41 | .. autoclass:: wayflowcore.evaluation.usefulnessscorer.UsefulnessScorer 42 | 43 | .. _userhappinessscorer: 44 | .. autoclass:: wayflowcore.evaluation.userhappinessscorer.UserHappinessScorer 45 | 46 | .. _criteriascorer: 47 | .. autoclass:: wayflowcore.evaluation.criteriascorer.CriteriaScorer 48 | 49 | .. _defaultscoremap: 50 | .. autoclass:: wayflowcore.evaluation.criteriascorer.DEFAULT_SCORE_MAP 51 | 52 | Evaluation Metrics 53 | ------------------ 54 | 55 | .. _calculate_set_metrics: 56 | .. autofunction:: wayflowcore.evaluation.evaluation_metrics.calculate_set_metrics 57 | 58 | .. _calculate_accuracy: 59 | .. autofunction:: wayflowcore.evaluation.evaluation_metrics.calculate_accuracy 60 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/component.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from abc import ABC 8 | from dataclasses import dataclass 9 | from typing import ClassVar, Optional 10 | 11 | from wayflowcore._metadata import MetadataType 12 | from wayflowcore.serialization.serializer import ( 13 | FrozenSerializableDataclass, 14 | SerializableDataclass, 15 | SerializableObject, 16 | ) 17 | 18 | 19 | class Component(SerializableObject, ABC): 20 | """Class for all components present in the intermediate representation""" 21 | 22 | def __init__( 23 | self, 24 | name: Optional[str], 25 | description: Optional[str], 26 | id: Optional[str], 27 | __metadata_info__: Optional[MetadataType] = None, 28 | ): 29 | # all arguments are mandatory to avoid missing them in implementations 30 | super().__init__(id=id, __metadata_info__=__metadata_info__) 31 | self.name = name or self.id 32 | self.description = description 33 | 34 | 35 | @dataclass(kw_only=True) 36 | class DataclassComponent(SerializableDataclass, Component, ABC): 37 | """ 38 | Base class for dataclasses to be serializable and to have ID and metadata attributes 39 | """ 40 | 41 | name: str = "" 42 | description: Optional[str] = None 43 | 44 | _can_be_referenced: ClassVar[bool] = True 45 | 46 | 47 | @dataclass(frozen=True, kw_only=True) 48 | class FrozenDataclassComponent(FrozenSerializableDataclass, Component, ABC): 49 | """ 50 | Base class for frozen dataclasses to be serializable and to have ID and metadata attributes 51 | """ 52 | 53 | name: str = "" 54 | description: Optional[str] = None 55 | 56 | _can_be_referenced: ClassVar[bool] = True 57 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/api/tracing.rst: -------------------------------------------------------------------------------- 1 | .. _tracing: 2 | 3 | Tracing 4 | ======= 5 | 6 | This page presents all APIs and classes related to tracing in WayFlow. 7 | 8 | 9 | Trace 10 | ------ 11 | 12 | .. _get_trace: 13 | .. autofunction:: wayflowcore.tracing.trace.get_trace 14 | 15 | .. _trace: 16 | .. autoclass:: wayflowcore.tracing.trace.Trace 17 | 18 | 19 | Spans 20 | ----- 21 | 22 | .. _get_current_span: 23 | .. autofunction:: wayflowcore.tracing.span.get_current_span 24 | 25 | .. _get_active_span_stack: 26 | .. autofunction:: wayflowcore.tracing.span.get_active_span_stack 27 | 28 | .. _span: 29 | .. autoclass:: wayflowcore.tracing.span.Span 30 | 31 | .. _llm_generation_span: 32 | .. autoclass:: wayflowcore.tracing.span.LlmGenerationSpan 33 | 34 | .. _conversational_component_execution_span: 35 | .. autoclass:: wayflowcore.tracing.span.ConversationalComponentExecutionSpan 36 | 37 | .. _conversation_span: 38 | .. autoclass:: wayflowcore.tracing.span.ConversationSpan 39 | 40 | .. _tool_execution_span: 41 | .. autoclass:: wayflowcore.tracing.span.ToolExecutionSpan 42 | 43 | .. _step_invocation_span: 44 | .. autoclass:: wayflowcore.tracing.span.StepInvocationSpan 45 | 46 | .. _context_provider_execution_span: 47 | .. autoclass:: wayflowcore.tracing.span.ContextProviderExecutionSpan 48 | 49 | Span Processors 50 | ---------------- 51 | 52 | .. _spanprocessor: 53 | .. autoclass:: wayflowcore.tracing.spanprocessor.SpanProcessor 54 | 55 | .. _simplespanprocessor: 56 | .. autoclass:: wayflowcore.tracing.spanprocessor.SimpleSpanProcessor 57 | 58 | 59 | Span Exporter 60 | ------------- 61 | 62 | .. _spanexporter: 63 | .. autoclass:: wayflowcore.tracing.spanexporter.SpanExporter 64 | 65 | 66 | OpenTelemetry 67 | ------------- 68 | 69 | .. _otelsimplespanprocessor: 70 | .. autoclass:: wayflowcore.tracing.opentelemetry.spanprocessor.OtelSimpleSpanProcessor 71 | 72 | .. _otelbatchspanprocessor: 73 | .. autoclass:: wayflowcore.tracing.opentelemetry.spanprocessor.OtelBatchSpanProcessor 74 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/LICENSE_UPL.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2025 Oracle and/or its affiliates. 2 | 3 | The Universal Permissive License (UPL), Version 1.0 4 | 5 | Subject to the condition set forth below, permission is hereby granted to any 6 | person obtaining a copy of this software, associated documentation and/or data 7 | (collectively the "Software"), free of charge and under any and all copyright 8 | rights in the Software, and any and all patent rights owned or freely 9 | licensable by each licensor hereunder covering either (i) the unmodified 10 | Software as contributed to or provided by such licensor, or (ii) the Larger 11 | Works (as defined below), to deal in both 12 | 13 | (a) the Software, and 14 | (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if 15 | one is included with the Software (each a "Larger Work" to which the Software 16 | is contributed by such licensors), 17 | 18 | without restriction, including without limitation the rights to copy, create 19 | derivative works of, display, perform, and distribute the Software and make, 20 | use, sell, offer for sale, import, export, have made, and have sold the 21 | Software and the Larger Work(s), and to sublicense the foregoing rights on 22 | either these or other terms. 23 | 24 | This license is subject to the following condition: 25 | The above copyright notice and either this complete permission notice or at 26 | a minimum a reference to the UPL must be included in all copies or 27 | substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 35 | SOFTWARE. -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/agentspec/components/_utils.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from typing import List 8 | 9 | from pyagentspec.property import Property 10 | 11 | from wayflowcore._utils._templating_helpers import ( 12 | get_non_str_variables_names_from_str_template, 13 | get_optional_variable_names_from_str, 14 | get_variable_names_from_str_template, 15 | ) 16 | 17 | 18 | def get_placeholder_properties_from_string_with_jinja_loops( 19 | string_with_placeholders: str, 20 | ) -> List[Property]: 21 | all_found_var_names = get_variable_names_from_str_template(string_with_placeholders) 22 | found_non_str_var_names = get_non_str_variables_names_from_str_template( 23 | string_with_placeholders, all_found_var_names 24 | ) 25 | found_optional_var_names = get_optional_variable_names_from_str( 26 | string_with_placeholders, all_found_var_names 27 | ) 28 | return [ 29 | Property( 30 | json_schema={ 31 | "title": var_name, 32 | "type": "string", 33 | # 'description': '' # TODO description 34 | **({"default": ""} if var_name in found_optional_var_names else {}), 35 | } 36 | ) 37 | for var_name in all_found_var_names 38 | if var_name not in found_non_str_var_names 39 | ] + [ 40 | Property( 41 | json_schema={ 42 | "title": var_name, 43 | # 'description': '' # TODO description 44 | **({"default": ""} if var_name in found_optional_var_names else {}), 45 | } 46 | ) 47 | for var_name in found_non_str_var_names 48 | if var_name in all_found_var_names 49 | ] 50 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/idgeneration.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | import uuid 8 | from typing import Optional 9 | 10 | import numpy as np 11 | 12 | AUTO_GENERATED_SUFFIX = "__auto" 13 | 14 | 15 | class IdGenerator: 16 | @staticmethod 17 | def _generate_id() -> str: 18 | id = uuid.uuid4() 19 | return str(id) 20 | 21 | @staticmethod 22 | def get_or_generate_id(id: Optional[str] = None) -> str: 23 | if id is not None: 24 | return id 25 | return IdGenerator._generate_id() 26 | 27 | @staticmethod 28 | def get_or_generate_name( 29 | name: Optional[str] = None, prefix: Optional[str] = None, length: Optional[int] = None 30 | ) -> str: 31 | """ 32 | If needed, generates a name automatically of the form: 33 | >>> f"{prefix}_{random_string_of_size_length}__auto" # doctest: +SKIP 34 | 35 | Parameters 36 | ---------- 37 | name: 38 | The current name. A name will be auto-generated if this is `None`. 39 | prefix: 40 | Prefix for the auto-generated name. 41 | length: 42 | Number of random characters [1234567890abcdef] to include in the name. 43 | 44 | """ 45 | if name is not None: 46 | return name 47 | name = "".join(np.random.choice(list("1234567890abcdef"), size=length)) 48 | if length is not None: 49 | name = name[: min(len(name), length)] 50 | if prefix is not None: 51 | name = prefix + name 52 | return f"{name}{AUTO_GENERATED_SUFFIX}" 53 | 54 | @staticmethod 55 | def is_auto_generated(value: str) -> bool: 56 | return value.endswith(AUTO_GENERATED_SUFFIX) 57 | -------------------------------------------------------------------------------- /wayflowcore/tests/test_idgenerator.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from wayflowcore.idgeneration import AUTO_GENERATED_SUFFIX, IdGenerator 8 | 9 | 10 | def test_get_or_generate_id_with_provided_id(): 11 | my_id = "custom_id" 12 | result = IdGenerator.get_or_generate_id(my_id) 13 | assert result == my_id 14 | 15 | 16 | def test_get_or_generate_id_without_id_generates_new(): 17 | result = IdGenerator.get_or_generate_id() 18 | assert isinstance(result, str) 19 | 20 | 21 | def test_get_or_generate_name_with_custom_name(): 22 | custom_name = "my_name" 23 | result = IdGenerator.get_or_generate_name(name=custom_name) 24 | assert result == custom_name 25 | assert IdGenerator.is_auto_generated(result) is False 26 | 27 | 28 | def test_get_or_generate_name_auto_generated_default_that_is_auto_generated(): 29 | result = IdGenerator.get_or_generate_name() 30 | assert IdGenerator.is_auto_generated(result) is True 31 | 32 | 33 | def test_get_or_generate_name_did_not_auto_generate_default(): 34 | result = IdGenerator.get_or_generate_name("hello") 35 | assert IdGenerator.is_auto_generated(result) is False 36 | 37 | 38 | def test_get_or_generate_name_with_length_limit(): 39 | result = IdGenerator.get_or_generate_name(length=8) 40 | assert result.endswith(AUTO_GENERATED_SUFFIX) 41 | assert len(result) == len(AUTO_GENERATED_SUFFIX) + 8 42 | assert IdGenerator.is_auto_generated(result) is True 43 | 44 | 45 | def test_get_or_generate_name_with_prefix(): 46 | result = IdGenerator.get_or_generate_name(prefix="myprefix_") 47 | assert result.startswith("myprefix_") 48 | assert result.endswith(AUTO_GENERATED_SUFFIX) 49 | assert IdGenerator.is_auto_generated(result) is True 50 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/embeddingmodels/embeddingmodel.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | from abc import ABC, abstractmethod 7 | from typing import List, Optional 8 | 9 | from wayflowcore._metadata import MetadataType 10 | from wayflowcore.component import Component 11 | from wayflowcore.idgeneration import IdGenerator 12 | from wayflowcore.serialization.serializer import SerializableObject 13 | 14 | 15 | class EmbeddingModel(Component, SerializableObject, ABC): 16 | """ 17 | Abstract base class for embedding models. 18 | 19 | Implementations should define the 'embed' method which returns a list of 20 | vector embeddings (each embedding is a list of floats) given a list of text strings. 21 | """ 22 | 23 | def __init__( 24 | self, 25 | __metadata_info__: Optional[MetadataType], 26 | id: Optional[str] = None, 27 | name: Optional[str] = None, 28 | description: Optional[str] = None, 29 | ): 30 | super().__init__( 31 | name=IdGenerator.get_or_generate_name(name, prefix="embedding_model", length=8), 32 | id=id, 33 | description=description, 34 | __metadata_info__=__metadata_info__, 35 | ) 36 | 37 | @abstractmethod 38 | def embed(self, data: List[str]) -> List[List[float]]: 39 | """ 40 | Generate embeddings for the given list of text strings. 41 | 42 | Parameters 43 | ---------- 44 | data 45 | A list of text strings for which to generate embeddings. 46 | 47 | Returns 48 | ------- 49 | List[List[float]] 50 | A list where each element is a list of floats representing the embedding 51 | of the corresponding text. 52 | """ 53 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/contextproviders/constantcontextprovider.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from typing import TYPE_CHECKING, Any, Callable, List, Optional 8 | 9 | from wayflowcore._metadata import MetadataType 10 | from wayflowcore.property import Property 11 | 12 | from .contextprovider import ContextProvider 13 | 14 | if TYPE_CHECKING: 15 | from wayflowcore.conversation import Conversation 16 | 17 | 18 | ContextProviderType = Callable[["Conversation"], Any] 19 | 20 | 21 | class ConstantContextProvider(ContextProvider): 22 | """Context provider to return constant value""" 23 | 24 | def __init__( 25 | self, 26 | value: Any, 27 | output_description: "Property", 28 | name: Optional[str] = None, 29 | id: Optional[str] = None, 30 | description: Optional[str] = None, 31 | __metadata_info__: Optional[MetadataType] = None, 32 | ) -> None: 33 | self._value = value 34 | self._output_description = output_description 35 | super().__init__( 36 | name=name, description=description, id=id, __metadata_info__=__metadata_info__ 37 | ) 38 | 39 | async def call_async(self, conversation: "Conversation") -> Any: 40 | from wayflowcore.tracing.span import ContextProviderExecutionSpan 41 | 42 | with ContextProviderExecutionSpan(context_provider=self) as span: 43 | value = self._value 44 | span.record_end_span_event( 45 | output=value, 46 | ) 47 | return value 48 | 49 | @property 50 | def callable(self) -> ContextProviderType: 51 | return self.__call__ 52 | 53 | def get_output_descriptors(self) -> List["Property"]: 54 | return [self._output_description] 55 | -------------------------------------------------------------------------------- /wayflowcore/tests/integration/steps/test_steps.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | import pytest 7 | 8 | from wayflowcore import Step 9 | from wayflowcore.flowhelpers import run_step_and_return_outputs 10 | from wayflowcore.property import IntegerProperty 11 | from wayflowcore.steps.step import StepResult 12 | 13 | 14 | class StepWithAllMethodsButInvokeMixin: 15 | def _compute_step_specific_input_descriptors_from_static_config(self): 16 | return [] 17 | 18 | def _compute_step_specific_output_descriptors_from_static_config(self): 19 | return [IntegerProperty(name="output")] 20 | 21 | def _get_step_specific_static_configuration_descriptors(self): 22 | return {} 23 | 24 | 25 | def test_step_raises_when_no_implemented_invoke(): 26 | 27 | class MyCustomStepWithoutInvoke(StepWithAllMethodsButInvokeMixin, Step): 28 | pass 29 | 30 | step = MyCustomStepWithoutInvoke(step_static_configuration={}) 31 | with pytest.raises(NotImplementedError): 32 | run_step_and_return_outputs(step) 33 | 34 | 35 | def test_step_works_when_implemented_invoke(): 36 | 37 | class MyCustomStepWithInvoke(StepWithAllMethodsButInvokeMixin, Step): 38 | def _invoke_step(self, inputs, conversation): 39 | return StepResult(outputs={"output": 1}) 40 | 41 | step = MyCustomStepWithInvoke(step_static_configuration={}) 42 | assert run_step_and_return_outputs(step) == {"output": 1} 43 | 44 | 45 | def test_step_works_when_implemented_invoke_async(): 46 | 47 | class MyCustomStepWithInvokeAsync(StepWithAllMethodsButInvokeMixin, Step): 48 | async def _invoke_step_async(self, inputs, conversation): 49 | return StepResult(outputs={"output": 1}) 50 | 51 | step = MyCustomStepWithInvokeAsync(step_static_configuration={}) 52 | assert run_step_and_return_outputs(step) == {"output": 1} 53 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/stepdescription.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from dataclasses import dataclass 8 | from typing import Dict, List, Tuple, Union 9 | 10 | from wayflowcore.serialization.serializer import SerializableDataclassMixin, SerializableObject 11 | 12 | 13 | @dataclass 14 | class StepDescription(SerializableDataclassMixin, SerializableObject): 15 | """ 16 | Data class that contains all the information needed to describe a step. 17 | This is used by Steps in order to identify steps inside LLM prompts. 18 | """ 19 | 20 | step_name: str 21 | description: str 22 | displayed_step_name: str = None # type: ignore 23 | 24 | def __post_init__(self) -> None: 25 | if self.displayed_step_name is None: 26 | self.displayed_step_name = self.step_name 27 | 28 | 29 | # Tuple[step_name,step_description,Optional[step_displayed_name]] 30 | StepDescriptionInput = Union[Tuple[str, str], Tuple[str, str, str], StepDescription] 31 | 32 | 33 | def make_steps_descriptions( 34 | next_steps: Union[List[StepDescriptionInput], Dict[str, str]], 35 | ) -> List[StepDescription]: 36 | step_descriptions = ( 37 | [ 38 | StepDescription(*next_step) if not isinstance(next_step, StepDescription) else next_step 39 | for next_step in next_steps 40 | ] 41 | if not isinstance(next_steps, dict) 42 | else [ 43 | StepDescription(step_name=step_name, description=description) 44 | for step_name, description in next_steps.items() 45 | ] 46 | ) 47 | if len(step_descriptions) != len( 48 | set([step_description.displayed_step_name for step_description in step_descriptions]) 49 | ): 50 | raise ValueError( 51 | f"Two next steps seem to have the same displayed names. This will make it impossible for the LLM to differentiate them: {step_descriptions}" 52 | ) 53 | return step_descriptions 54 | -------------------------------------------------------------------------------- /.gitlab/jobs/templates/get_private_branch.yml: -------------------------------------------------------------------------------- 1 | .get_private_branch: 2 | script: 3 | - | 4 | #!/bin/bash 5 | 6 | # Encode inputs 7 | ENCODED_BRANCH_NAME=$(echo -n "${CI_COMMIT_REF_NAME}" | sed 's|/|%2F|g') 8 | FULL_PROJECT_NAME="${PRIVATE_PROJECT}/${PRIVATE_REPOSITORY}" 9 | PROJECT_ENCODED=$(echo -n "$FULL_PROJECT_NAME" | sed 's|/|%2F|g') 10 | API_URL="$GITLAB_URL/projects/${PROJECT_ENCODED}" 11 | 12 | echo "Checking merge requests for branch: '${CI_COMMIT_REF_NAME}' in $FULL_PROJECT_NAME" 13 | 14 | HTTP_RESPONSE=$(mktemp) 15 | 16 | # API call 17 | HTTP_STATUS=$(curl -s -o "$HTTP_RESPONSE" -w "%{http_code}" \ 18 | --header "PRIVATE-TOKEN: $GITLAB_BOT_TOKEN" \ 19 | "${API_URL}/merge_requests?state=opened&source_branch=$ENCODED_BRANCH_NAME") 20 | 21 | if [ "$HTTP_STATUS" -ne 200 ] && [ "$HTTP_STATUS" -ne 404 ]; then 22 | echo "Error: Invalid HTTP status $HTTP_STATUS. Exiting." 23 | cat "$HTTP_RESPONSE" 24 | rm "$HTTP_RESPONSE" 25 | exit 1 26 | fi 27 | 28 | RESPONSE=$(cat "$HTTP_RESPONSE") 29 | rm "$HTTP_RESPONSE" 30 | 31 | # Count number of merge requests found (by counting "iid" fields) 32 | MR_COUNT=$(echo "$RESPONSE" | (grep -o '"iid":' || true) | wc -l) 33 | if [ "$MR_COUNT" -gt 1 ]; then 34 | echo "Error: More than one merge request ($MR_COUNT) is open for branch '${CI_COMMIT_REF_NAME}' in $FULL_PROJECT_NAME." 35 | exit 1 36 | elif [ "$MR_COUNT" -eq 0 ]; then 37 | echo "No merge requests found for branch '${CI_COMMIT_REF_NAME}' in $FULL_PROJECT_NAME. Falling back to 'main'." 38 | export PRIVATE_BRANCH="main" 39 | export PRIVATE_MERGE_REQUEST_ID="" 40 | export PRIVATE_MERGE_REQUEST_COMMIT_HASH="" 41 | else 42 | echo "One merge request found for branch '${CI_COMMIT_REF_NAME}' in $FULL_PROJECT_NAME." 43 | MR_ID=$(echo "$RESPONSE" | grep -o '"iid":[0-9]*' | head -n1 | cut -d ':' -f2) 44 | MR_COMMIT_HASH=$(echo "$RESPONSE" | grep -o '"sha":"[0-9a-f]\+"' | head -n1 | cut -d '"' -f4) 45 | export PRIVATE_BRANCH="${CI_COMMIT_REF_NAME}" 46 | export PRIVATE_MERGE_REQUEST_ID="$MR_ID" 47 | export PRIVATE_MERGE_REQUEST_COMMIT_HASH="$MR_COMMIT_HASH" 48 | fi -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/code_examples/example_ociuserauthentication.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | # isort:skip_file 7 | # fmt: off 8 | # mypy: ignore-errors 9 | 10 | def get_oci_genai_credentials(): 11 | return { 12 | "user": "ocid1.user.oc1..aaaaaaaa", 13 | "key_content": "dummy_key_content", 14 | "fingerprint": "aa:aa:aa:aa:aa:aa:aa:aa:aa:aa:aa:aa:aa:aa:aa:aa", 15 | "tenancy": "ocid1.tenancy.oc1..aaaaaaaa", 16 | "compartment_id": "ocid1.compartment.oc1..aaaaaaaa", 17 | "region": "us-chicago-1", 18 | } 19 | 20 | 21 | # .. start-userauthenticationconfig: 22 | from wayflowcore.models.ociclientconfig import ( 23 | OCIClientConfigWithUserAuthentication, 24 | OCIUserAuthenticationConfig, 25 | ) 26 | 27 | # Assume we have an API to get credentials 28 | oci_genai_cred = get_oci_genai_credentials() 29 | 30 | user_config = OCIUserAuthenticationConfig( 31 | user=oci_genai_cred["user"], 32 | key_content=oci_genai_cred["key_content"], 33 | fingerprint=oci_genai_cred["fingerprint"], 34 | tenancy=oci_genai_cred["tenancy"], 35 | region=oci_genai_cred["region"], 36 | ) 37 | # .. end-userauthenticationconfig: 38 | 39 | # .. start-clientconfig: 40 | client_config = OCIClientConfigWithUserAuthentication( 41 | service_endpoint="my_service_endpoint", # replace it with your endpoint 42 | compartment_id=oci_genai_cred["compartment_id"], 43 | user_config=user_config, 44 | ) 45 | # .. end-clientconfig: 46 | 47 | # .. start-ocigenaimodel: 48 | from wayflowcore.models.ocigenaimodel import OCIGenAIModel 49 | 50 | llm = OCIGenAIModel( 51 | model_id="cohere.command-r-plus-08-2024", 52 | client_config=client_config, 53 | ) 54 | # .. end-ocigenaimodel: 55 | 56 | # .. start-llmmodelfactory: 57 | from wayflowcore.models import LlmModelFactory 58 | 59 | COHERE_CONFIG = { 60 | "model_type": "ocigenai", 61 | "model_id": "cohere.command-r-plus-08-2024", 62 | "client_config": client_config, 63 | } 64 | llm = LlmModelFactory.from_config(COHERE_CONFIG) 65 | # .. end-llmmodelfactory 66 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/code_examples/howto_tool_from_flow.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | # isort:skip_file 7 | # fmt: off 8 | # mypy: ignore-errors 9 | 10 | import os 11 | 12 | # .. define-model-location: 13 | os.environ["MY_LLM_HOST_PORT"] = "model.example.com" 14 | # .. end-define-model-location 15 | 16 | # .. start: 17 | import os 18 | 19 | from wayflowcore.controlconnection import ControlFlowEdge 20 | from wayflowcore.dataconnection import DataFlowEdge 21 | from wayflowcore.flow import Flow 22 | from wayflowcore.models.llmmodelfactory import LlmModelFactory 23 | from wayflowcore.property import StringProperty 24 | from wayflowcore.steps import PromptExecutionStep, StartStep 25 | from wayflowcore.tools.servertools import ServerTool 26 | 27 | model_config = { 28 | "model_type": "vllm", 29 | "host_port": os.environ["MY_LLM_HOST_PORT"], 30 | "model_id": "meta-llama/Meta-Llama-3.1-8B-Instruct", 31 | } 32 | llm = LlmModelFactory.from_config(model_config) 33 | 34 | start_step = StartStep(input_descriptors=[StringProperty("topic")]) 35 | poem_generation_step = PromptExecutionStep( 36 | llm=llm, prompt_template="Write a 12 lines poem about the following topic: {{ topic }}" 37 | ) 38 | poem_generation_flow = Flow( 39 | begin_step=start_step, 40 | steps={"start_step": start_step, "poem_generation_step": poem_generation_step}, 41 | control_flow_edges=[ 42 | ControlFlowEdge(source_step=start_step, destination_step=poem_generation_step), 43 | ControlFlowEdge(source_step=poem_generation_step, destination_step=None), 44 | ], 45 | data_flow_edges=[DataFlowEdge(start_step, "topic", poem_generation_step, "topic")], 46 | ) 47 | 48 | poem_generation_tool = ServerTool.from_flow( 49 | flow=poem_generation_flow, 50 | flow_name="generate_poem", 51 | flow_description="A simple flow to generate a 12 lines poem based on a topic.", 52 | # The below line is needed to specify which output of the flow should be used as the output of 53 | # the tool 54 | flow_output=PromptExecutionStep.OUTPUT, 55 | ) 56 | 57 | # .. end-start 58 | -------------------------------------------------------------------------------- /wayflowcore/src/wayflowcore/agentserver/openairesponses/services/service.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2025 Oracle and/or its affiliates. 2 | # 3 | # This software is under the Apache License 2.0 4 | # (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License 5 | # (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option. 6 | 7 | from abc import ABC, abstractmethod 8 | from typing import Any, AsyncIterable, List, Optional, Union 9 | 10 | from ..models.openairesponsespydanticmodels import ( 11 | CreateResponse, 12 | ListModelsResponse, 13 | Order, 14 | Response, 15 | ResponseAdditionalContent, 16 | ResponseError, 17 | ResponseStreamEvent, 18 | ) 19 | 20 | 21 | class OpenAIResponsesService(ABC): 22 | 23 | @abstractmethod 24 | async def list_models( 25 | self, 26 | limit: Optional[int] = 20, 27 | order: Optional[Order] = "desc", 28 | after: Optional[str] = None, 29 | before: Optional[str] = None, 30 | ) -> ListModelsResponse: 31 | """ 32 | List models 33 | """ 34 | 35 | @abstractmethod 36 | async def create_response(self, body: CreateResponse) -> AsyncIterable[ResponseStreamEvent]: 37 | """ 38 | Create a model response 39 | """ 40 | # fake implementation for IDE typechecker to work 41 | yield ResponseStreamEvent() # type: ignore 42 | 43 | @abstractmethod 44 | async def get_response( 45 | self, 46 | response_id: str, 47 | include: Optional[List[ResponseAdditionalContent]] = None, 48 | stream: Optional[bool] = None, 49 | starting_after: Optional[int] = None, 50 | include_obfuscation: Optional[bool] = None, 51 | ) -> Response: 52 | """ 53 | Get a model response 54 | """ 55 | ... 56 | 57 | @abstractmethod 58 | async def delete_response(self, response_id: str) -> Optional[ResponseError]: 59 | """ 60 | Delete a model response 61 | """ 62 | 63 | @abstractmethod 64 | async def cancel_response(self, response_id: str) -> Union[Response, ResponseError]: 65 | """ 66 | Cancel a response 67 | """ 68 | 69 | @abstractmethod 70 | def _add_agent(self, agent_id: str, agent: Any) -> None: 71 | pass 72 | -------------------------------------------------------------------------------- /docs/wayflowcore/source/core/howtoguides/create_a_tool_from_a_flow.rst: -------------------------------------------------------------------------------- 1 | ================================= 2 | How to Create a Tool Using a Flow 3 | ================================= 4 | 5 | .. admonition:: Prerequisites 6 | 7 | This guide assumes familiarity with: 8 | 9 | - :doc:`Flows <../tutorials/basic_flow>` 10 | - :doc:`Agents <../tutorials/basic_agent>` 11 | - :doc:`Tools <../api/tools>` 12 | - :doc:`Building Assistants with Tools ` 13 | 14 | Equipping assistants with :doc:`Tools <../api/tools>` enhances their capabilities. 15 | In WayFlow, tools can be defined in various ways. 16 | One approach is to define a flow as the basis for the tool. 17 | In this guide, you will see a basic example of how a flow is used to define a tool. 18 | 19 | 20 | Defining the tool 21 | ================= 22 | 23 | In this guide, you will use an LLM. 24 | 25 | WayFlow supports several LLM API providers. 26 | Select an LLM from the options below: 27 | 28 | .. include:: ../_components/llm_config_tabs.rst 29 | 30 | Now define a flow and pass additional information to describe the tool, including a name, description, and the output choice. 31 | 32 | .. literalinclude:: ../code_examples/howto_tool_from_flow.py 33 | :language: python 34 | :start-after: .. start: 35 | :end-before: .. end-start 36 | 37 | .. note:: 38 | The above example also works with more complex flows. However, only flows that do not yield are supported — meaning the flow must run to completion without pausing to request additional input from the user. 39 | 40 | .. tip:: 41 | You can now use this tool like any other server tool, and pass it either to an :ref:`Agent ` or to a :ref:`ToolExecutionStep `. 42 | 43 | 44 | Recap 45 | ===== 46 | 47 | In this guide, you learned how to create server tools from ``Flows`` by using the ``ServerTool.from_flow`` method. 48 | 49 | .. collapse:: Below is the complete code from this guide. 50 | 51 | .. literalinclude:: ../code_examples/howto_tool_from_flow.py 52 | :language: python 53 | :start-after: .. start: 54 | :end-before: .. end-start 55 | 56 | Next steps 57 | ========== 58 | 59 | Having learned how to use tools in WayFlow, you may now proceed to :doc:`How to Build Assistants with Tools `. 60 | --------------------------------------------------------------------------------