Skip to content

Commit dd3d619

Browse files
committed
fix(hierarchical-swarm): record the director's plan, not its raw tool call
parse_orders already extracts (plan, orders) from the director's tool call. run_director recorded the unparsed call instead, so every worker read a rendering of it as prose. Record the plan and the per-agent assignments; any_to_str has no callers left.
1 parent cfc4366 commit dd3d619

2 files changed

Lines changed: 70 additions & 8 deletions

File tree

swarms/structs/hiearchical_swarm.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
split_last_turn,
2828
)
2929
from swarms.structs.conversation import Conversation
30-
from swarms.utils.any_to_str import any_to_str
3130
from swarms.structs.ma_blocks import find_agent_by_name
3231
from swarms.structs.ma_utils import list_all_agents
3332
from swarms.structs.omni_agent_types import AgentListType
@@ -686,15 +685,21 @@ def run_director(
686685
img=img,
687686
)
688687

689-
# A tool-call list stored raw renders as a Python repr in the
690-
# history that every later agent reads. Keep it readable.
688+
if isinstance(function_call, str):
689+
director_record = function_call
690+
else:
691+
plan, orders = self.parse_orders(function_call)
692+
director_record = "\n\n".join(
693+
[plan]
694+
+ [
695+
f"{order.agent_name}: {order.task}"
696+
for order in orders
697+
]
698+
)
699+
691700
self.conversation.add(
692701
role="Director",
693-
content=(
694-
function_call
695-
if isinstance(function_call, str)
696-
else any_to_str(function_call)
697-
),
702+
content=director_record,
698703
)
699704

700705
return function_call

tests/structs/test_hierarchical_swarm.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,5 +1158,62 @@ def test_the_conversation_starts_clean(self):
11581158
), f"stale messages loaded from disk: {roles}"
11591159

11601160

1161+
def test_director_plan_is_recorded_as_prose_not_a_tool_call():
1162+
"""Workers read the shared history, so the plan must not be a tool-call repr."""
1163+
import json
1164+
from unittest.mock import patch
1165+
1166+
tool_call = [
1167+
{
1168+
"role": "assistant",
1169+
"content": [
1170+
{
1171+
"function": {
1172+
"name": "create_plan",
1173+
"arguments": json.dumps(
1174+
{
1175+
"plan": "Explain the rate hikes.",
1176+
"orders": [
1177+
{
1178+
"agent_name": "Markets",
1179+
"task": "Compile an overview.",
1180+
}
1181+
],
1182+
}
1183+
),
1184+
}
1185+
}
1186+
],
1187+
}
1188+
]
1189+
1190+
swarm = HierarchicalSwarm(
1191+
name="s",
1192+
description="d",
1193+
agents=[
1194+
Agent(
1195+
agent_name="Markets",
1196+
model_name="gpt-4o-mini",
1197+
max_loops=1,
1198+
)
1199+
],
1200+
max_loops=1,
1201+
)
1202+
1203+
with patch.object(swarm.director, "run", return_value=tool_call):
1204+
swarm.run_director(task="explain the rate hikes")
1205+
1206+
recorded = [
1207+
m["content"]
1208+
for m in swarm.conversation.conversation_history
1209+
if m.get("role") == "Director"
1210+
][-1]
1211+
1212+
assert "Explain the rate hikes." in recorded
1213+
assert "Markets: Compile an overview." in recorded
1214+
assert "arguments" not in recorded
1215+
assert "create_plan" not in recorded
1216+
1217+
11611218
if __name__ == "__main__":
11621219
pytest.main([__file__, "-v"])

0 commit comments

Comments
 (0)