├── 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 |
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 |
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 |
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 |
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 |
--------------------------------------------------------------------------------