How to Execute Agent Spec Across Frameworks#

This guide demonstrates how to:

  1. Load an Agent Spec JSON representation of an agent

  2. Run it with an agentic framework using one of the Agent Spec adapters

  3. Build the basics of an Agent Spec adapter

This guide shows how to execute a flexible ReAct RAG agent using a tool that simulates information retrieval based on a query. The example uses a pre-built Agent Spec representation of the agent, shown below.

{
  "component_type": "Agent",
  "id": "7d3f3251-8d66-42d3-aff8-0e0d0d9486a8",
  "name": "adaptive_expert_agent",
  "description": null,
  "metadata": {},
  "inputs": [
    {
      "title": "domain_of_expertise",
      "type": "string"
    }
  ],
  "outputs": [],
  "llm_config": {
    "component_type": "VllmConfig",
    "id": "301ea6c6-17b7-46ab-967f-e354c15ba97b",
    "name": "Llama 3.1 8B instruct",
    "description": null,
    "metadata": {},
    "default_generation_parameters": {},
    "url": "LLAMA_PLACEHOLDER_LINK",
    "model_id": "meta-llama/Meta-Llama-3.1-8B-Instruct"
  },
  "system_prompt": "You are an expert in {{domain_of_expertise}}.\nPlease help the users with their requests.",
  "tools": [
    {
      "component_type": "ServerTool",
      "id": "5c38a0ba-8ac4-4712-bf26-39759fe48ccb",
      "name": "rag_tool",
      "description": "Tool that performs RAG",
      "metadata": {},
      "inputs": [
        {
          "title": "query",
          "type": "string"
        }
      ],
      "outputs": [
        {
          "items": {
            "type": "string"
          },
          "title": "results",
          "type": "array"
        }
      ]
    }
  ],
  "agentspec_version": "25.4.1"
}

It also assumes having a common registry of tool implementations containing the tool utilized by this agent.

from typing import List


def hello_world() -> None:
    """Prints 'Hello world!'"""
    print("Hello world!")
    return None


def rag_tool(query: str) -> List[str]:
    """Search and return the list of results"""
    return ["result 1", "result 2"]


tool_registry = {
    "rag_tool": rag_tool,
    "hello_world_tool": hello_world,
}

Adapters#

Using adapters is the recommended way of integrating an agentic framework runtime. Ideally, an adapter should translate programmatically the representation of the Agent Spec components into the equivalent solution, as per each framework’s definition, and return an object that developers can run.

As a reference runtime for Agent Spec, WayFlow offers an Agent Spec adapter as part of the package. Besides WayFlow, the Agent Spec team provides the implementation of adapters for two other common agentic frameworks:

Each adapter contains two main public classes, AgentSpecExporter and AgentSpecLoader.

The AgentSpecExporter exposes APIs to export an object of the reference agentic framework into the equivalent Agent Spec representation in one of the following forms: YAML, JSON, or PyAgentSpec Component object.

class AgentSpecExporter:
    """Helper class to convert agentic framework objects to Agent Spec configurations."""

    def to_yaml(self, framework_component: FrameworkComponent) -> str:
        """Transform the given framework component into the respective Agent Spec YAML representation."""

    def to_json(self, framework_component: FrameworkComponent) -> str:
        """Transform the given framework component into the respective Agent Spec JSON representation."""

    def to_component(self, autogen_component: FrameworkComponent) -> Component:
        """Transform the given framework component into the respective PyAgentSpec Component."""

The AgentSpecLoader exposes APIs to load an Agent Spec representation in one of the aforementioned forms, i.e., YAML, JSON, or PyAgentSpec Component object, into the corresponding agentic framework’s object. The loader requires to specify the registry of tool implementations. These tools will be mapped to the ServerTools used in the Agent Spec representation to load and transform.

class AgentSpecLoader:
    """Helper class to convert Agent Spec configurations to agentic framework objects."""

    def __init__(self, tool_registry: Optional[Dict[str, Callable]] = None):
        """Ask for the tool registry containing the implementation of ServerTools"""

    def load_yaml(self, serialized_assistant: str) -> FrameworkComponent:
        """Transform the given Agent Spec YAML representation into the respective framework Component"""

    def load_json(self, serialized_assistant: str) -> FrameworkComponent:
        """Transform the given Agent Spec JSON representation into the respective framework Component"""

    def load_component(self, agentspec_component: AgentSpecComponent) -> FrameworkComponent:
        """Transform the given PyAgentSpec Component into the respective framework Component"""

Basic implementation of an adapter#

As an example of how to build an adapter, let’s take WayFlow as agentic framework and implement the main functions needed to perform the transformation from an Agent Spec representation to a runnable WayFlow component.

1. Load an Agent Spec JSON representation of an agent#

The first step is to read the Agent Spec JSON representation of the assistant and deserialize it to obtain a PyAgentSpec Agent component. This component and its internals serve as the basis for building framework-specific implementations of the agent. We can take advantage of the PyAgentSpec deserialization functionality for that.

from pyagentspec.serialization import AgentSpecDeserializer

with open(CONFIGS_DIR / "simple_agent_with_rag_tool.json", "r") as file:
    assistant_json = file.read()

deserializer = AgentSpecDeserializer()
deserialized_agentspec_agent = deserializer.from_json(assistant_json)

API Reference: AgentSpecDeserializer

The agent contains mainly three components that need to be created in WayFlow:

  • The vLLM used by the agent

  • The RAG tool that the agent could use to gather more information

  • The agent itself

The following sections detail how to create these components across different frameworks. The programmatic way to accomplish this is to build reusable methods that translate individual Agent Spec components, which are then combined to perform the final agent translation.

2. Defining the LLM#

WayFlow provides a specialized class for vLLMs called VllmModel. Use this class to define the agent’s language model.

from wayflowcore.models import VllmModel

from pyagentspec.llms import LlmConfig, VllmConfig


def convert_agentspec_llm_to_wayflow(agentspec_llm: LlmConfig):
    if isinstance(agentspec_llm, VllmConfig):
        return VllmModel(
            model_id=agentspec_llm.model_id,
            host_port=agentspec_llm.url,
        )
    # Here we should write the translation for
    # the other types of LLM that are available in Agent Spec


3. Defining the tools#

The tool types available in WayFlow align with the ones defined in Agent Spec (Client, Server, Remote). If the Agent Spec specifies a ServerTool, the corresponding class in WayFlow must be used.

from wayflowcore.property import Property
from wayflowcore.tools import ServerTool as WayflowServerTool

from pyagentspec.tools import ServerTool, Tool


def convert_agentspec_tool_to_wayflow(agentspec_tool: Tool):
    if isinstance(agentspec_tool, ServerTool):
        return WayflowServerTool(
            func=tool_registry[agentspec_tool.name],
            name=agentspec_tool.name,
            description=agentspec_tool.description,
            input_descriptors=[
                Property.from_json_schema(input_.json_schema) for input_ in agentspec_tool.inputs
            ],
            output_descriptors=[
                Property.from_json_schema(output.json_schema) for output in agentspec_tool.outputs
            ],
        )


4. Defining the agent#

Create a ReAct-style agent in WayFlow using the Agent class and providing the list of available tools.

from wayflowcore.agent import Agent as WayflowAgent

from pyagentspec.agent import Agent


def convert_agentspec_agent_to_wayflow(agentspec_agent: Agent):
    return WayflowAgent(
        llm=convert_agentspec_llm_to_wayflow(agentspec_agent.llm_config),
        custom_instruction=agentspec_agent.system_prompt,
        tools=[convert_agentspec_tool_to_wayflow(tool) for tool in agentspec_agent.tools],
    )


5. Conversion#

Define the conversion method for the required Agent Spec components and invoke it on the agent to produce the corresponding WayFlow implementation.

from pyagentspec import Component


def convert_agentspec_to_wayflow(agentspec_component: Component):
    if isinstance(agentspec_component, LlmConfig):
        return convert_agentspec_llm_to_wayflow(agentspec_component)
    elif isinstance(agentspec_component, Tool):
        return convert_agentspec_tool_to_wayflow(agentspec_component)
    elif isinstance(agentspec_component, Agent):
        return convert_agentspec_agent_to_wayflow(agentspec_component)
    # Here we should write the translation for
    # the other components that are available in Agent Spec


agent = convert_agentspec_to_wayflow(deserialized_agentspec_agent)

6. Execution#

Finally, we can start the conversation with our new agent and execute it.

# We fill the input of the Agent when we start the conversation
conversation = agent.start_conversation(inputs={"domain_of_expertise": "computer science"})
status = conversation.execute()

Using the Agent Spec adapter from WayFlow#

The execution of this section requires to install the package wayflowcore.

pip install "wayflowcore==25.4.1"

The transformation can be easily performed using this library by creating an AgentSpecLoader object, and calling the load_json method directly on the Agent Spec JSON representation of the agent, or the load_component method on the PyAgentSpec component object.

from wayflowcore.agentspec import AgentSpecLoader
from wayflowcore.tools import tool

loader = AgentSpecLoader(
    tool_registry={
        tool_name: tool(tool_function, description_mode="only_docstring")
        for tool_name, tool_function in tool_registry.items()
    }
)
agent = loader.load_component(deserialized_agentspec_agent)

You can find more information about the Agent Spec adapter in the WayFlow API Reference.

Recap#

This guide covered how to:

  1. Load an Agent Spec JSON representation of an agent

  2. Run it with an agentic framework using WayFlow

  3. Build the basics of an Agent Spec adapter

Below is the complete code from this guide.
from typing import List


def hello_world() -> None:
    """Prints 'Hello world!'"""
    print("Hello world!")
    return None


def rag_tool(query: str) -> List[str]:
    """Search and return the list of results"""
    return ["result 1", "result 2"]


tool_registry = {
    "rag_tool": rag_tool,
    "hello_world_tool": hello_world,
}


from pyagentspec.serialization import AgentSpecDeserializer

with open(CONFIGS_DIR / "simple_agent_with_rag_tool.json", "r") as file:
    assistant_json = file.read()

deserializer = AgentSpecDeserializer()
deserialized_agentspec_agent = deserializer.from_json(assistant_json)


from wayflowcore.models import VllmModel

from pyagentspec.llms import LlmConfig, VllmConfig


def convert_agentspec_llm_to_wayflow(agentspec_llm: LlmConfig):
    if isinstance(agentspec_llm, VllmConfig):
        return VllmModel(
            model_id=agentspec_llm.model_id,
            host_port=agentspec_llm.url,
        )
    # Here we should write the translation for
    # the other types of LLM that are available in Agent Spec


from wayflowcore.property import Property
from wayflowcore.tools import ServerTool as WayflowServerTool

from pyagentspec.tools import ServerTool, Tool


def convert_agentspec_tool_to_wayflow(agentspec_tool: Tool):
    if isinstance(agentspec_tool, ServerTool):
        return WayflowServerTool(
            func=tool_registry[agentspec_tool.name],
            name=agentspec_tool.name,
            description=agentspec_tool.description,
            input_descriptors=[
                Property.from_json_schema(input_.json_schema) for input_ in agentspec_tool.inputs
            ],
            output_descriptors=[
                Property.from_json_schema(output.json_schema) for output in agentspec_tool.outputs
            ],
        )


from wayflowcore.agent import Agent as WayflowAgent

from pyagentspec.agent import Agent


def convert_agentspec_agent_to_wayflow(agentspec_agent: Agent):
    return WayflowAgent(
        llm=convert_agentspec_llm_to_wayflow(agentspec_agent.llm_config),
        custom_instruction=agentspec_agent.system_prompt,
        tools=[convert_agentspec_tool_to_wayflow(tool) for tool in agentspec_agent.tools],
    )


from pyagentspec import Component


def convert_agentspec_to_wayflow(agentspec_component: Component):
    if isinstance(agentspec_component, LlmConfig):
        return convert_agentspec_llm_to_wayflow(agentspec_component)
    elif isinstance(agentspec_component, Tool):
        return convert_agentspec_tool_to_wayflow(agentspec_component)
    elif isinstance(agentspec_component, Agent):
        return convert_agentspec_agent_to_wayflow(agentspec_component)
    # Here we should write the translation for
    # the other components that are available in Agent Spec


agent = convert_agentspec_to_wayflow(deserialized_agentspec_agent)
conversation = agent.start_conversation(inputs={"domain_of_expertise": "computer science"})
status = conversation.execute()


from wayflowcore.agentspec import AgentSpecLoader
from wayflowcore.tools import tool

loader = AgentSpecLoader(
    tool_registry={
        tool_name: tool(tool_function, description_mode="only_docstring")
        for tool_name, tool_function in tool_registry.items()
    }
)
agent = loader.load_component(deserialized_agentspec_agent)

If you are interested in implementing an Agent Spec runtime adapter for a framework that is not currently supported, or you would like to enhance one of the existing ones, contributions are welcome! See the Contributing section for more details.

Next steps#

Having seen how to implement the same agent across three different frameworks, consider experimenting with your preferred one using your own Agent Spec configuration.