flock-core 0.4.528__py3-none-any.whl → 0.5.0b0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of flock-core might be problematic. Click here for more details.
- flock/cli/execute_flock.py +1 -1
- flock/cli/manage_agents.py +6 -6
- flock/components/__init__.py +30 -0
- flock/components/evaluation/__init__.py +9 -0
- flock/components/evaluation/declarative_evaluation_component.py +222 -0
- flock/components/routing/__init__.py +15 -0
- flock/{routers/conditional/conditional_router.py → components/routing/conditional_routing_component.py} +61 -53
- flock/components/routing/default_routing_component.py +103 -0
- flock/components/routing/llm_routing_component.py +206 -0
- flock/components/utility/__init__.py +15 -0
- flock/{modules/enterprise_memory/enterprise_memory_module.py → components/utility/memory_utility_component.py} +195 -173
- flock/{modules/performance/metrics_module.py → components/utility/metrics_utility_component.py} +110 -95
- flock/{modules/output/output_module.py → components/utility/output_utility_component.py} +47 -45
- flock/core/__init__.py +26 -18
- flock/core/agent/__init__.py +16 -0
- flock/core/agent/flock_agent_components.py +104 -0
- flock/core/agent/flock_agent_execution.py +101 -0
- flock/core/agent/flock_agent_integration.py +206 -0
- flock/core/agent/flock_agent_lifecycle.py +177 -0
- flock/core/agent/flock_agent_serialization.py +381 -0
- flock/core/api/endpoints.py +2 -2
- flock/core/api/service.py +2 -2
- flock/core/component/__init__.py +15 -0
- flock/core/{flock_module.py → component/agent_component_base.py} +136 -34
- flock/core/component/evaluation_component.py +56 -0
- flock/core/component/routing_component.py +74 -0
- flock/core/component/utility_component.py +69 -0
- flock/core/config/flock_agent_config.py +49 -2
- flock/core/evaluation/utils.py +3 -2
- flock/core/execution/batch_executor.py +1 -1
- flock/core/execution/evaluation_executor.py +2 -2
- flock/core/execution/opik_executor.py +1 -1
- flock/core/flock.py +147 -493
- flock/core/flock_agent.py +195 -1032
- flock/core/flock_factory.py +114 -90
- flock/core/flock_scheduler.py +1 -1
- flock/core/flock_server_manager.py +8 -8
- flock/core/logging/logging.py +1 -0
- flock/core/mcp/flock_mcp_server.py +53 -48
- flock/core/mcp/{flock_mcp_tool_base.py → flock_mcp_tool.py} +2 -2
- flock/core/mcp/mcp_client.py +9 -9
- flock/core/mcp/mcp_client_manager.py +9 -9
- flock/core/mcp/mcp_config.py +24 -24
- flock/core/mixin/dspy_integration.py +5 -5
- flock/core/orchestration/__init__.py +18 -0
- flock/core/orchestration/flock_batch_processor.py +94 -0
- flock/core/orchestration/flock_evaluator.py +113 -0
- flock/core/orchestration/flock_execution.py +288 -0
- flock/core/orchestration/flock_initialization.py +125 -0
- flock/core/orchestration/flock_server_manager.py +67 -0
- flock/core/orchestration/flock_web_server.py +117 -0
- flock/core/registry/__init__.py +45 -0
- flock/core/registry/agent_registry.py +69 -0
- flock/core/registry/callable_registry.py +139 -0
- flock/core/registry/component_discovery.py +142 -0
- flock/core/registry/component_registry.py +64 -0
- flock/core/registry/config_mapping.py +64 -0
- flock/core/registry/decorators.py +137 -0
- flock/core/registry/registry_hub.py +205 -0
- flock/core/registry/server_registry.py +57 -0
- flock/core/registry/type_registry.py +86 -0
- flock/core/serialization/flock_serializer.py +36 -32
- flock/core/serialization/serialization_utils.py +28 -25
- flock/core/util/hydrator.py +1 -1
- flock/core/util/input_resolver.py +29 -2
- flock/mcp/servers/sse/flock_sse_server.py +10 -10
- flock/mcp/servers/stdio/flock_stdio_server.py +10 -10
- flock/mcp/servers/streamable_http/flock_streamable_http_server.py +10 -10
- flock/mcp/servers/websockets/flock_websocket_server.py +10 -10
- flock/platform/docker_tools.py +3 -3
- flock/webapp/app/chat.py +1 -1
- flock/webapp/app/main.py +9 -5
- flock/webapp/app/services/flock_service.py +1 -1
- flock/webapp/app/services/sharing_store.py +1 -0
- flock/workflow/activities.py +67 -92
- flock/workflow/agent_execution_activity.py +6 -6
- flock/workflow/flock_workflow.py +1 -1
- flock_core-0.5.0b0.dist-info/METADATA +272 -0
- {flock_core-0.4.528.dist-info → flock_core-0.5.0b0.dist-info}/RECORD +82 -95
- flock/core/flock_evaluator.py +0 -60
- flock/core/flock_registry.py +0 -702
- flock/core/flock_router.py +0 -83
- flock/evaluators/__init__.py +0 -1
- flock/evaluators/declarative/__init__.py +0 -1
- flock/evaluators/declarative/declarative_evaluator.py +0 -217
- flock/evaluators/memory/memory_evaluator.py +0 -90
- flock/evaluators/test/test_case_evaluator.py +0 -38
- flock/evaluators/zep/zep_evaluator.py +0 -59
- flock/modules/__init__.py +0 -1
- flock/modules/assertion/__init__.py +0 -1
- flock/modules/assertion/assertion_module.py +0 -286
- flock/modules/callback/__init__.py +0 -1
- flock/modules/callback/callback_module.py +0 -91
- flock/modules/enterprise_memory/README.md +0 -99
- flock/modules/mem0/__init__.py +0 -1
- flock/modules/mem0/mem0_module.py +0 -126
- flock/modules/mem0_async/__init__.py +0 -1
- flock/modules/mem0_async/async_mem0_module.py +0 -126
- flock/modules/memory/__init__.py +0 -1
- flock/modules/memory/memory_module.py +0 -429
- flock/modules/memory/memory_parser.py +0 -125
- flock/modules/memory/memory_storage.py +0 -736
- flock/modules/output/__init__.py +0 -1
- flock/modules/performance/__init__.py +0 -1
- flock/modules/zep/__init__.py +0 -1
- flock/modules/zep/zep_module.py +0 -192
- flock/routers/__init__.py +0 -1
- flock/routers/agent/__init__.py +0 -1
- flock/routers/agent/agent_router.py +0 -236
- flock/routers/agent/handoff_agent.py +0 -58
- flock/routers/default/__init__.py +0 -1
- flock/routers/default/default_router.py +0 -80
- flock/routers/feedback/feedback_router.py +0 -114
- flock/routers/list_generator/list_generator_router.py +0 -166
- flock/routers/llm/__init__.py +0 -1
- flock/routers/llm/llm_router.py +0 -365
- flock/tools/__init__.py +0 -0
- flock/tools/azure_tools.py +0 -781
- flock/tools/code_tools.py +0 -167
- flock/tools/file_tools.py +0 -149
- flock/tools/github_tools.py +0 -157
- flock/tools/markdown_tools.py +0 -205
- flock/tools/system_tools.py +0 -9
- flock/tools/text_tools.py +0 -810
- flock/tools/web_tools.py +0 -90
- flock/tools/zendesk_tools.py +0 -147
- flock_core-0.4.528.dist-info/METADATA +0 -675
- {flock_core-0.4.528.dist-info → flock_core-0.5.0b0.dist-info}/WHEEL +0 -0
- {flock_core-0.4.528.dist-info → flock_core-0.5.0b0.dist-info}/entry_points.txt +0 -0
- {flock_core-0.4.528.dist-info → flock_core-0.5.0b0.dist-info}/licenses/LICENSE +0 -0
flock/platform/docker_tools.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import asyncio
|
|
1
2
|
import subprocess
|
|
2
|
-
import time
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
def _check_docker_running():
|
|
@@ -16,7 +16,7 @@ def _check_docker_running():
|
|
|
16
16
|
return False
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
def _start_docker():
|
|
19
|
+
async def _start_docker():
|
|
20
20
|
"""Attempt to start Docker.
|
|
21
21
|
This example first tries 'systemctl start docker' and then 'service docker start'.
|
|
22
22
|
Adjust as needed for your environment.
|
|
@@ -37,7 +37,7 @@ def _start_docker():
|
|
|
37
37
|
text=True,
|
|
38
38
|
)
|
|
39
39
|
# Give Docker a moment to start.
|
|
40
|
-
|
|
40
|
+
await asyncio.sleep(3)
|
|
41
41
|
if _check_docker_running():
|
|
42
42
|
print("Docker is now running.")
|
|
43
43
|
return True
|
flock/webapp/app/chat.py
CHANGED
|
@@ -473,7 +473,7 @@ async def chat_send_shared(
|
|
|
473
473
|
if frozen_chat_cfg.history_key: run_input[frozen_chat_cfg.history_key] = [h["text"] for h in history if h.get("role") == "user" or h.get("role") == "bot"]
|
|
474
474
|
|
|
475
475
|
try:
|
|
476
|
-
result_dict = await flock_inst.run_async(
|
|
476
|
+
result_dict = await flock_inst.run_async(agent=bot_agent, input=run_input, box_result=False)
|
|
477
477
|
if frozen_chat_cfg.response_key:
|
|
478
478
|
bot_text = str(result_dict.get(frozen_chat_cfg.response_key, result_dict))
|
|
479
479
|
else:
|
flock/webapp/app/main.py
CHANGED
|
@@ -124,6 +124,10 @@ def mask_sensitive_value_web(value: str) -> str:
|
|
|
124
124
|
if len(value) <= 4: return "••••"
|
|
125
125
|
return value[:2] + "•" * (len(value) - 4) + value[-2:]
|
|
126
126
|
|
|
127
|
+
def create_hx_trigger_header(triggers: dict[str, Any]) -> str:
|
|
128
|
+
"""Helper function to create HX-Trigger header with JSON serialization."""
|
|
129
|
+
return json.dumps(triggers)
|
|
130
|
+
|
|
127
131
|
def get_show_secrets_setting_web(env_vars: dict[str, str]) -> bool:
|
|
128
132
|
return env_vars.get(SHOW_SECRETS_KEY, "false").lower() == "true"
|
|
129
133
|
|
|
@@ -843,12 +847,12 @@ async def ui_load_flock_by_name_action(request: Request, selected_flock_filename
|
|
|
843
847
|
if loaded_flock:
|
|
844
848
|
success_message_text = f"Flock '{loaded_flock.name}' loaded from '{selected_flock_filename}'."
|
|
845
849
|
response_headers["HX-Push-Url"] = "/ui/editor/execute?ui_mode=" + ui_mode_query
|
|
846
|
-
response_headers["HX-Trigger"] =
|
|
850
|
+
response_headers["HX-Trigger"] = create_hx_trigger_header({"flockLoaded": None, "notify": {"type": "success", "message": success_message_text}})
|
|
847
851
|
context = get_base_context_web(request, success=success_message_text, ui_mode=ui_mode_query)
|
|
848
852
|
return templates.TemplateResponse("partials/_execution_view_container.html", context, headers=response_headers)
|
|
849
853
|
else:
|
|
850
854
|
error_message_text = f"Failed to load flock file '{selected_flock_filename}'."
|
|
851
|
-
response_headers["HX-Trigger"] =
|
|
855
|
+
response_headers["HX-Trigger"] = create_hx_trigger_header({"notify": {"type": "error", "message": error_message_text}})
|
|
852
856
|
context = get_base_context_web(request, error=error_message_text, ui_mode=ui_mode_query)
|
|
853
857
|
context["error_message_inline"] = error_message_text # For direct display in partial
|
|
854
858
|
return templates.TemplateResponse("partials/_load_manager_view.html", context, headers=response_headers)
|
|
@@ -874,13 +878,13 @@ async def ui_load_flock_by_upload_action(request: Request, flock_file_upload: Up
|
|
|
874
878
|
if loaded_flock:
|
|
875
879
|
success_message_text = f"Flock '{loaded_flock.name}' loaded from '{filename_to_load}'."
|
|
876
880
|
response_headers["HX-Push-Url"] = f"/ui/editor/execute?ui_mode={ui_mode_query}"
|
|
877
|
-
response_headers["HX-Trigger"] =
|
|
881
|
+
response_headers["HX-Trigger"] = create_hx_trigger_header({"flockLoaded": None, "flockFileListChanged": None, "notify": {"type": "success", "message": success_message_text}})
|
|
878
882
|
context = get_base_context_web(request, success=success_message_text, ui_mode=ui_mode_query)
|
|
879
883
|
return templates.TemplateResponse("partials/_execution_view_container.html", context, headers=response_headers)
|
|
880
884
|
else: error_message_text = f"Failed to process uploaded '{filename_to_load}'."
|
|
881
885
|
|
|
882
886
|
final_error_msg = error_message_text or "Upload failed."
|
|
883
|
-
response_headers["HX-Trigger"] =
|
|
887
|
+
response_headers["HX-Trigger"] = create_hx_trigger_header({"notify": {"type": "error", "message": final_error_msg}})
|
|
884
888
|
context = get_base_context_web(request, error=final_error_msg, ui_mode=ui_mode_query)
|
|
885
889
|
return templates.TemplateResponse("partials/_create_flock_form.html", context, headers=response_headers)
|
|
886
890
|
|
|
@@ -893,7 +897,7 @@ async def ui_create_flock_action(request: Request, flock_name: str = Form(...),
|
|
|
893
897
|
|
|
894
898
|
new_flock = create_new_flock_service(flock_name, default_model, description, request.app.state)
|
|
895
899
|
success_msg_text = f"New flock '{new_flock.name}' created. Navigating to Execute page. Configure properties and agents as needed."
|
|
896
|
-
response_headers = {"HX-Push-Url": f"/ui/editor/execute?ui_mode={ui_mode_query}", "HX-Trigger":
|
|
900
|
+
response_headers = {"HX-Push-Url": f"/ui/editor/execute?ui_mode={ui_mode_query}", "HX-Trigger": create_hx_trigger_header({"flockLoaded": None, "notify": {"type": "success", "message": success_msg_text}})}
|
|
897
901
|
context = get_base_context_web(request, success=success_msg_text, ui_mode=ui_mode_query)
|
|
898
902
|
return templates.TemplateResponse("partials/_execution_view_container.html", context, headers=response_headers)
|
|
899
903
|
|
|
@@ -281,7 +281,7 @@ async def run_current_flock_service(
|
|
|
281
281
|
logger.info(f"Executing agent '{start_agent_name}' from flock '{current_flock.name}' using app_state.")
|
|
282
282
|
# Direct execution using the flock from app_state
|
|
283
283
|
result = await current_flock.run_async(
|
|
284
|
-
|
|
284
|
+
agent=start_agent_name, input=inputs, box_result=False
|
|
285
285
|
)
|
|
286
286
|
# Store run details using the run_store from app_state
|
|
287
287
|
if hasattr(run_store, "add_run_details"): # Check if RunStore has this method
|
|
@@ -304,6 +304,7 @@ class SQLiteSharedLinkStore(SharedLinkStoreInterface):
|
|
|
304
304
|
logger.error(f"SQLite error saving feedback {record.feedback_id}: {e}", exc_info=True)
|
|
305
305
|
raise
|
|
306
306
|
|
|
307
|
+
|
|
307
308
|
# ---------------------------------------------------------------------------
|
|
308
309
|
# Azure Table + Blob implementation
|
|
309
310
|
# ---------------------------------------------------------------------------
|
flock/workflow/activities.py
CHANGED
|
@@ -7,15 +7,28 @@ from temporalio import activity
|
|
|
7
7
|
|
|
8
8
|
from flock.core.context.context import FlockContext
|
|
9
9
|
from flock.core.context.context_vars import FLOCK_CURRENT_AGENT, FLOCK_MODEL
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
from flock.core.flock_router import HandOffRequest
|
|
10
|
+
|
|
11
|
+
# HandOffRequest removed - using agent.next_agent directly
|
|
13
12
|
from flock.core.logging.logging import get_logger
|
|
13
|
+
from flock.core.registry import get_registry
|
|
14
14
|
from flock.core.util.input_resolver import resolve_inputs
|
|
15
15
|
|
|
16
16
|
logger = get_logger("activities")
|
|
17
17
|
tracer = trace.get_tracer(__name__)
|
|
18
18
|
|
|
19
|
+
def apply_handoff_strategy(previous_agent_output:str, next_agent_input:str, previous_agent_handoff_strategy:str, previous_agent_handoff_map:dict[str, str]) -> str:
|
|
20
|
+
if previous_agent_handoff_strategy == "append":
|
|
21
|
+
return next_agent_input + previous_agent_output
|
|
22
|
+
elif previous_agent_handoff_strategy == "override":
|
|
23
|
+
return previous_agent_output
|
|
24
|
+
elif previous_agent_handoff_strategy == "static":
|
|
25
|
+
return next_agent_input
|
|
26
|
+
elif previous_agent_handoff_strategy == "map":
|
|
27
|
+
for key, value in previous_agent_handoff_map.items():
|
|
28
|
+
next_agent_input = next_agent_input.replace(key, value)
|
|
29
|
+
return next_agent_input
|
|
30
|
+
raise NotImplementedError
|
|
31
|
+
|
|
19
32
|
|
|
20
33
|
@activity.defn
|
|
21
34
|
async def run_agent(context: FlockContext) -> dict:
|
|
@@ -29,6 +42,9 @@ async def run_agent(context: FlockContext) -> dict:
|
|
|
29
42
|
registry = get_registry()
|
|
30
43
|
|
|
31
44
|
previous_agent_name = ""
|
|
45
|
+
previous_agent_output = ""
|
|
46
|
+
previous_agent_handoff_strategy = ""
|
|
47
|
+
previous_agent_handoff_map = {}
|
|
32
48
|
if isinstance(context, dict):
|
|
33
49
|
context = FlockContext.from_dict(context)
|
|
34
50
|
current_agent_name = context.get_variable(FLOCK_CURRENT_AGENT)
|
|
@@ -38,7 +54,7 @@ async def run_agent(context: FlockContext) -> dict:
|
|
|
38
54
|
agent = registry.get_agent(current_agent_name)
|
|
39
55
|
if agent.model is None or agent.evaluator.config.model is None:
|
|
40
56
|
agent.set_model(context.get_variable(FLOCK_MODEL))
|
|
41
|
-
|
|
57
|
+
|
|
42
58
|
if not agent:
|
|
43
59
|
logger.error("Agent not found", agent=current_agent_name)
|
|
44
60
|
span.record_exception(
|
|
@@ -53,8 +69,14 @@ async def run_agent(context: FlockContext) -> dict:
|
|
|
53
69
|
iter_span.set_attribute("agent.name", agent.name)
|
|
54
70
|
agent.context = context
|
|
55
71
|
# Resolve inputs for the agent.
|
|
72
|
+
# Gets values from context, previous agent output, and handoff strategy.
|
|
56
73
|
agent_inputs = resolve_inputs(
|
|
57
|
-
agent.input,
|
|
74
|
+
agent.input,
|
|
75
|
+
context,
|
|
76
|
+
previous_agent_name,
|
|
77
|
+
previous_agent_output,
|
|
78
|
+
previous_agent_handoff_strategy,
|
|
79
|
+
previous_agent_handoff_map
|
|
58
80
|
)
|
|
59
81
|
iter_span.add_event(
|
|
60
82
|
"resolved inputs", attributes={"inputs": str(agent_inputs)}
|
|
@@ -69,6 +91,13 @@ async def run_agent(context: FlockContext) -> dict:
|
|
|
69
91
|
logger.debug(
|
|
70
92
|
"Agent execution completed", agent=agent.name
|
|
71
93
|
)
|
|
94
|
+
context.record(
|
|
95
|
+
agent.name,
|
|
96
|
+
result,
|
|
97
|
+
timestamp=datetime.now().isoformat(),
|
|
98
|
+
hand_off=None,
|
|
99
|
+
called_from=previous_agent_name,
|
|
100
|
+
)
|
|
72
101
|
except Exception as e:
|
|
73
102
|
logger.error(
|
|
74
103
|
"Agent execution failed",
|
|
@@ -78,81 +107,46 @@ async def run_agent(context: FlockContext) -> dict:
|
|
|
78
107
|
exec_span.record_exception(e)
|
|
79
108
|
raise
|
|
80
109
|
|
|
81
|
-
# Determine the next agent using
|
|
82
|
-
|
|
110
|
+
# Determine the next agent using routing component if available
|
|
111
|
+
next_agent_name = None
|
|
83
112
|
|
|
84
|
-
if agent.
|
|
113
|
+
if agent.router:
|
|
85
114
|
logger.info(
|
|
86
|
-
f"Using
|
|
115
|
+
f"Using router: {agent.router.__class__.__name__}",
|
|
87
116
|
agent=agent.name,
|
|
88
117
|
)
|
|
89
118
|
try:
|
|
90
|
-
# Route to the next agent
|
|
91
|
-
|
|
119
|
+
# Route to the next agent using new routing component
|
|
120
|
+
next_agent_name = await agent.router.determine_next_step(
|
|
92
121
|
agent, result, context
|
|
93
122
|
)
|
|
94
123
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
"Executing handoff function", agent=agent.name
|
|
98
|
-
)
|
|
99
|
-
try:
|
|
100
|
-
handoff_data = handoff_data(context, result)
|
|
101
|
-
if isinstance(
|
|
102
|
-
handoff_data.next_agent, FlockAgent
|
|
103
|
-
):
|
|
104
|
-
handoff_data.next_agent = (
|
|
105
|
-
handoff_data.next_agent.name
|
|
106
|
-
)
|
|
107
|
-
except Exception as e:
|
|
108
|
-
logger.error(
|
|
109
|
-
"Handoff function error {} {}",
|
|
110
|
-
agent=agent.name,
|
|
111
|
-
error=str(e),
|
|
112
|
-
)
|
|
113
|
-
iter_span.record_exception(e)
|
|
114
|
-
return {"error": f"Handoff function error: {e}"}
|
|
115
|
-
elif isinstance(handoff_data.next_agent, FlockAgent):
|
|
116
|
-
handoff_data.next_agent = (
|
|
117
|
-
handoff_data.next_agent.name
|
|
118
|
-
)
|
|
124
|
+
# Set next_agent on the agent instance
|
|
125
|
+
agent.next_agent = next_agent_name
|
|
119
126
|
|
|
120
|
-
if not handoff_data.next_agent:
|
|
121
|
-
logger.info(
|
|
122
|
-
"Router found no suitable next agent",
|
|
123
|
-
agent=agent.name,
|
|
124
|
-
)
|
|
125
|
-
context.record(
|
|
126
|
-
agent.name,
|
|
127
|
-
result,
|
|
128
|
-
timestamp=datetime.now().isoformat(),
|
|
129
|
-
hand_off=None,
|
|
130
|
-
called_from=previous_agent_name,
|
|
131
|
-
)
|
|
132
|
-
logger.info("Completing chain", agent=agent.name)
|
|
133
|
-
iter_span.add_event("chain completed")
|
|
134
|
-
return result
|
|
135
127
|
except Exception as e:
|
|
136
128
|
logger.error(
|
|
137
|
-
"Router error {}
|
|
138
|
-
agent.name,
|
|
139
|
-
str(e),
|
|
129
|
+
f"Router error: {e}",
|
|
130
|
+
agent=agent.name,
|
|
131
|
+
error=str(e),
|
|
140
132
|
)
|
|
141
133
|
iter_span.record_exception(e)
|
|
142
134
|
return {"error": f"Router error: {e}"}
|
|
143
135
|
else:
|
|
144
|
-
#
|
|
136
|
+
# Check if next_agent was set directly by user
|
|
137
|
+
next_agent_name = agent.next_agent
|
|
138
|
+
if callable(next_agent_name):
|
|
139
|
+
try:
|
|
140
|
+
next_agent_name = next_agent_name(context, result)
|
|
141
|
+
except Exception as e:
|
|
142
|
+
logger.error(f"next_agent callable error: {e}")
|
|
143
|
+
return {"error": f"next_agent callable error: {e}"}
|
|
144
|
+
|
|
145
|
+
if not next_agent_name:
|
|
145
146
|
logger.info(
|
|
146
|
-
"No
|
|
147
|
+
"No next agent found, completing chain",
|
|
147
148
|
agent=agent.name,
|
|
148
149
|
)
|
|
149
|
-
context.record(
|
|
150
|
-
agent.name,
|
|
151
|
-
result,
|
|
152
|
-
timestamp=datetime.now().isoformat(),
|
|
153
|
-
hand_off=None,
|
|
154
|
-
called_from=previous_agent_name,
|
|
155
|
-
)
|
|
156
150
|
iter_span.add_event("chain completed")
|
|
157
151
|
return result
|
|
158
152
|
|
|
@@ -161,53 +155,34 @@ async def run_agent(context: FlockContext) -> dict:
|
|
|
161
155
|
agent.name,
|
|
162
156
|
result,
|
|
163
157
|
timestamp=datetime.now().isoformat(),
|
|
164
|
-
hand_off=
|
|
158
|
+
hand_off={"next_agent": next_agent_name} if next_agent_name else None,
|
|
165
159
|
called_from=previous_agent_name,
|
|
166
160
|
)
|
|
161
|
+
# Remember the current agent's details for the next iteration.
|
|
167
162
|
previous_agent_name = agent.name
|
|
168
163
|
previous_agent_output = agent.output
|
|
169
|
-
|
|
170
|
-
|
|
164
|
+
previous_agent_handoff_strategy = agent.config.handoff_strategy
|
|
165
|
+
previous_agent_handoff_map = agent.config.handoff_map
|
|
171
166
|
|
|
172
|
-
#
|
|
167
|
+
# Activate the next agent.
|
|
173
168
|
try:
|
|
174
|
-
agent = registry.get_agent(
|
|
175
|
-
if handoff_data.output_to_input_merge_strategy == "add":
|
|
176
|
-
agent.input = previous_agent_output + ", " + agent.input
|
|
177
|
-
|
|
178
|
-
if handoff_data.add_input_fields:
|
|
179
|
-
for field in handoff_data.add_input_fields:
|
|
180
|
-
agent.input = field + ", " + agent.input
|
|
181
|
-
|
|
182
|
-
if handoff_data.add_output_fields:
|
|
183
|
-
for field in handoff_data.add_output_fields:
|
|
184
|
-
agent.output = field + ", " + agent.output
|
|
185
|
-
|
|
186
|
-
if handoff_data.add_description:
|
|
187
|
-
if agent.description:
|
|
188
|
-
agent.description = (
|
|
189
|
-
agent.description
|
|
190
|
-
+ "\n"
|
|
191
|
-
+ handoff_data.add_description
|
|
192
|
-
)
|
|
193
|
-
else:
|
|
194
|
-
agent.description = handoff_data.add_description
|
|
195
|
-
|
|
196
|
-
agent.resolve_callables(context=context)
|
|
169
|
+
agent = registry.get_agent(next_agent_name)
|
|
197
170
|
if not agent:
|
|
198
171
|
logger.error(
|
|
199
172
|
"Next agent not found",
|
|
200
|
-
agent=
|
|
173
|
+
agent=next_agent_name,
|
|
201
174
|
)
|
|
202
175
|
iter_span.record_exception(
|
|
203
176
|
Exception(
|
|
204
|
-
f"Next agent '{
|
|
177
|
+
f"Next agent '{next_agent_name}' not found"
|
|
205
178
|
)
|
|
206
179
|
)
|
|
207
180
|
return {
|
|
208
|
-
"error": f"Next agent '{
|
|
181
|
+
"error": f"Next agent '{next_agent_name}' not found."
|
|
209
182
|
}
|
|
210
183
|
|
|
184
|
+
|
|
185
|
+
|
|
211
186
|
context.set_variable(FLOCK_CURRENT_AGENT, agent.name)
|
|
212
187
|
|
|
213
188
|
logger.info("Handing off to next agent", next=agent.name)
|
|
@@ -12,8 +12,8 @@ from temporalio import activity
|
|
|
12
12
|
from flock.core.context.context import FlockContext
|
|
13
13
|
from flock.core.context.context_vars import FLOCK_MODEL
|
|
14
14
|
from flock.core.flock_agent import FlockAgent # Import concrete class if needed
|
|
15
|
-
from flock.core.
|
|
16
|
-
|
|
15
|
+
from flock.core.registry import get_registry
|
|
16
|
+
# HandOffRequest removed - using agent.next_agent directly
|
|
17
17
|
from flock.core.logging.logging import get_logger
|
|
18
18
|
from flock.core.util.input_resolver import resolve_inputs
|
|
19
19
|
|
|
@@ -133,22 +133,22 @@ async def determine_next_agent(
|
|
|
133
133
|
f"Agent '{current_agent_name}' not found for routing."
|
|
134
134
|
)
|
|
135
135
|
|
|
136
|
-
if not agent.
|
|
136
|
+
if not agent.router:
|
|
137
137
|
logger.info(
|
|
138
|
-
"No
|
|
138
|
+
"No router defined for agent", agent=current_agent_name
|
|
139
139
|
)
|
|
140
140
|
span.add_event("no_router")
|
|
141
141
|
return None # Indicate no handoff
|
|
142
142
|
|
|
143
143
|
logger.debug(
|
|
144
|
-
f"Using router {agent.
|
|
144
|
+
f"Using router {agent.router.__class__.__name__}",
|
|
145
145
|
agent=agent.name,
|
|
146
146
|
)
|
|
147
147
|
try:
|
|
148
148
|
# Execute the routing logic
|
|
149
149
|
handoff_data: (
|
|
150
150
|
HandOffRequest | Callable
|
|
151
|
-
) = await agent.
|
|
151
|
+
) = await agent.router.route(agent, result, context)
|
|
152
152
|
|
|
153
153
|
# Handle callable handoff functions - This is complex in distributed systems.
|
|
154
154
|
# Consider if this pattern should be supported or if routing should always
|
flock/workflow/flock_workflow.py
CHANGED
|
@@ -7,7 +7,7 @@ from temporalio import workflow
|
|
|
7
7
|
with workflow.unsafe.imports_passed_through():
|
|
8
8
|
from flock.core.context.context import AgentDefinition, FlockContext
|
|
9
9
|
from flock.core.context.context_vars import FLOCK_CURRENT_AGENT
|
|
10
|
-
|
|
10
|
+
# HandOffRequest removed - using agent.next_agent directly
|
|
11
11
|
from flock.core.logging.logging import get_logger
|
|
12
12
|
from flock.workflow.agent_execution_activity import (
|
|
13
13
|
determine_next_agent,
|