fix(backend): fallback to DB query for AgentExecutorBlock output in dry-run

During dry-run, the sub-agent's output events may not reach the
event_bus listener before the GRAPH_EXEC_UPDATE arrives (the simulated
execution completes faster than events propagate). This causes the
AgentExecutorBlock to complete with 0 outputs.

Adds a DB fallback: after the event loop breaks on graph COMPLETED,
if no outputs were yielded, query get_node_executions for the
sub-agent's OUTPUT block results and yield them.

Evidence: normal run produces 1 output, ALL dry-runs produce 0.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Zamil Majdy
2026-03-28 22:29:42 +00:00
parent cfaa1ff0d4
commit a3e3d3ff6b

View File

@@ -163,6 +163,30 @@ class AgentExecutorBlock(Block):
extra_steps=event.stats.node_exec_count if event.stats else 0,
)
)
# Fallback for dry-run: if no outputs were yielded via events
# (common in simulation where events may arrive before listener),
# query the sub-agent's output nodes directly from the DB.
if not yielded_node_exec_ids:
from backend.data.execution import get_node_executions
results = await get_node_executions(
graph_exec_id=graph_exec_id,
statuses=[ExecutionStatus.COMPLETED],
)
for result in results:
r_block = get_block(result.block_id)
if not r_block or r_block.block_type != BlockType.OUTPUT:
continue
r_name = (result.input_data or {}).get("name")
if not r_name:
continue
for r_data in (result.output_data or {}).get("output", []):
logger.debug(
f"Execution {log_id} fallback output {r_name}: {r_data}"
)
yield r_name, r_data
break
logger.debug(