Merge pull request #849 from ascender1729/feat/xml-support

feat: add robust XML output support throughout the agentic framework (#841)
pull/851/head
Kye Gomez 3 weeks ago committed by GitHub
commit 3e243a943a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,43 @@
from swarms.structs.agent import Agent
import xml.etree.ElementTree as ET
"""
User-Facing Example: How to get XML output from a Swarms agent
-------------------------------------------------------------
This example demonstrates how to use the Swarms agent framework to generate output in XML format.
You can use this pattern in your own projects to get structured, machine-readable results from any agent.
"""
if __name__ == "__main__":
# Step 1: Create your agent and specify output_type="xml"
agent = Agent(
agent_name="XML-Output-Agent",
agent_description="Agent that demonstrates XML output support",
max_loops=2,
model_name="gpt-4o-mini",
dynamic_temperature_enabled=True,
interactive=False,
output_type="xml", # Request XML output
)
# Step 2: Ask your question or give a task
task = "Summarize the latest trends in AI research."
xml_out = agent.run(task)
# Step 3: Print the XML output for inspection or downstream use
print("\n===== XML Output from Agent =====\n")
print(xml_out)
# Step 4: (Optional) Parse the XML output for programmatic use
try:
root = ET.fromstring(xml_out)
print("\nParsed XML Root Tag:", root.tag)
print("Number of top-level children:", len(root))
# Print the first child tag and text for demonstration
if len(root):
print("First child tag:", root[0].tag)
print("First child text:", root[0].text)
except ET.ParseError as e:
print(f"Failed to parse XML: {e}")
# You can copy and adapt this example for your own agent workflows!

@ -201,7 +201,7 @@ class Agent:
limit_tokens_from_string (Callable): The function to limit tokens from a string limit_tokens_from_string (Callable): The function to limit tokens from a string
custom_tools_prompt (Callable): The custom tools prompt custom_tools_prompt (Callable): The custom tools prompt
tool_schema (ToolUsageType): The tool schema tool_schema (ToolUsageType): The tool schema
output_type (agent_output_type): The output type output_type (agent_output_type): The output type. Supported: 'str', 'string', 'list', 'json', 'dict', 'yaml', 'xml'.
function_calling_type (str): The function calling type function_calling_type (str): The function calling type
output_cleaner (Callable): The output cleaner function output_cleaner (Callable): The output cleaner function
function_calling_format_type (str): The function calling format type function_calling_format_type (str): The function calling format type
@ -998,7 +998,7 @@ class Agent:
Returns: Returns:
Any: The output of the agent. Any: The output of the agent.
(string, list, json, dict, yaml) (string, list, json, dict, yaml, xml)
Examples: Examples:
agent(task="What is the capital of France?") agent(task="What is the capital of France?")
@ -1220,6 +1220,7 @@ class Agent:
if self.autosave: if self.autosave:
self.save() self.save()
# Output formatting based on output_type
return history_output_formatter( return history_output_formatter(
self.short_memory, type=self.output_type self.short_memory, type=self.output_type
) )

@ -3,4 +3,4 @@ from swarms.utils.history_output_formatter import (
) )
# Use the OutputType for type annotations # Use the OutputType for type annotations
output_type: OutputType output_type: OutputType # OutputType now includes 'xml'

@ -121,7 +121,7 @@ class SwarmRouter:
shared_memory_system (Any, optional): Shared memory system for agents. Defaults to None. shared_memory_system (Any, optional): Shared memory system for agents. Defaults to None.
rules (str, optional): Rules to inject into every agent. Defaults to None. rules (str, optional): Rules to inject into every agent. Defaults to None.
documents (List[str], optional): List of document file paths to use. Defaults to empty list. documents (List[str], optional): List of document file paths to use. Defaults to empty list.
output_type (str, optional): Output format type. Defaults to "string". output_type (str, optional): Output format type. Defaults to "string". Supported: 'str', 'string', 'list', 'json', 'dict', 'yaml', 'xml'.
Attributes: Attributes:
name (str): Name identifier for the SwarmRouter instance name (str): Name identifier for the SwarmRouter instance
@ -136,7 +136,7 @@ class SwarmRouter:
shared_memory_system (Any): Shared memory system for agents shared_memory_system (Any): Shared memory system for agents
rules (str): Rules injected into every agent rules (str): Rules injected into every agent
documents (List[str]): List of document file paths documents (List[str]): List of document file paths
output_type (str): Output format type output_type (str): Output format type. Supported: 'str', 'string', 'list', 'json', 'dict', 'yaml', 'xml'.
logs (List[SwarmLog]): List of execution logs logs (List[SwarmLog]): List of execution logs
swarm: The instantiated swarm object swarm: The instantiated swarm object

@ -1,7 +1,7 @@
import yaml import yaml
from swarms.structs.conversation import Conversation from swarms.structs.conversation import Conversation
from typing import Literal, Union, List, Dict, Any from typing import Literal, Union, List, Dict, Any
from swarms.utils.xml_utils import to_xml_string
HistoryOutputType = Literal[ HistoryOutputType = Literal[
"list", "list",
@ -14,14 +14,12 @@ HistoryOutputType = Literal[
"json", "json",
"all", "all",
"yaml", "yaml",
"xml",
# "dict-final", # "dict-final",
"dict-all-except-first", "dict-all-except-first",
"str-all-except-first", "str-all-except-first",
] ]
output_type: HistoryOutputType
def history_output_formatter( def history_output_formatter(
conversation: Conversation, type: HistoryOutputType = "list" conversation: Conversation, type: HistoryOutputType = "list"
) -> Union[List[Dict[str, Any]], Dict[str, Any], str]: ) -> Union[List[Dict[str, Any]], Dict[str, Any], str]:
@ -39,11 +37,12 @@ def history_output_formatter(
return conversation.get_str() return conversation.get_str()
elif type == "yaml": elif type == "yaml":
return yaml.safe_dump(conversation.to_dict(), sort_keys=False) return yaml.safe_dump(conversation.to_dict(), sort_keys=False)
# elif type == "dict-final":
# return conversation.to_dict()
elif type == "dict-all-except-first": elif type == "dict-all-except-first":
return conversation.return_all_except_first() return conversation.return_all_except_first()
elif type == "str-all-except-first": elif type == "str-all-except-first":
return conversation.return_all_except_first_string() return conversation.return_all_except_first_string()
elif type == "xml":
data = conversation.to_dict()
return to_xml_string(data, root_tag="conversation")
else: else:
raise ValueError(f"Invalid type: {type}") raise ValueError(f"Invalid type: {type}")

@ -0,0 +1,40 @@
import xml.etree.ElementTree as ET
from typing import Any
def dict_to_xml(tag: str, d: dict) -> ET.Element:
"""Convert a dictionary to an XML Element."""
elem = ET.Element(tag)
for key, val in d.items():
child = ET.Element(str(key))
if isinstance(val, dict):
child.append(dict_to_xml(str(key), val))
elif isinstance(val, list):
for item in val:
if isinstance(item, dict):
child.append(dict_to_xml(str(key), item))
else:
item_elem = ET.Element("item")
item_elem.text = str(item)
child.append(item_elem)
else:
child.text = str(val)
elem.append(child)
return elem
def to_xml_string(data: Any, root_tag: str = "root") -> str:
"""Convert a dict or list to an XML string."""
if isinstance(data, dict):
elem = dict_to_xml(root_tag, data)
elif isinstance(data, list):
elem = ET.Element(root_tag)
for item in data:
if isinstance(item, dict):
elem.append(dict_to_xml("item", item))
else:
item_elem = ET.Element("item")
item_elem.text = str(item)
elem.append(item_elem)
else:
elem = ET.Element(root_tag)
elem.text = str(data)
return ET.tostring(elem, encoding="unicode")
Loading…
Cancel
Save