File: src/conductor/ai/agents/runtime/runtime.py
Symptom:
$ CONDUCTOR_AGENT_LLM_MODEL=anthropic/claude-sonnet-4-6 python examples/agents/93_openai_runner_hello_world.py
Framework agent 'Assistant' execution FAILED
None
No reason, no task name, nothing actionable. Diagnosing it means walking the server API by hand:
curl -s localhost:8080/api/agent/executions?size=20
curl -s localhost:8080/api/workflow/<executionId> # find FAILED tasks, read reasonForIncompletion
Cause: The helper already exists and works — _extract_failed_task_reason(wf) reads the first FAILED task's reasonForIncompletion and returns Task '<ref>' failed: <reason>. It is called by run() (line ~2534) and _run_by_name() (line ~2623), which is why native-agent failures do report properly, e.g. 54_software_bug_assistant prints ERROR: Task 'software_assistant_54_list_mcp_0' failed: Failed to list MCP tools ... HTTP 400.
_run_framework() never calls it. It uses status.reason alone (error=status.reason if raw_status in ("FAILED","TERMINATED") else None), and for these failures status.reason is empty — so the result is None.
Fix: Call _extract_failed_task_reason in _run_framework as a fallback when status.reason is empty, matching run().
Verify: Start the server without OPENAI_API_KEY, run 93 — it should name the failing task and its reason instead of printing None.
Possibly a second gap, unconfirmed: 59_coding_agent goes through run() yet also reported no reason, while its server-side SUB_WORKFLOW task did carry one (Anthropic Messages API failed with status 404). _extract_failed_task_reason only inspects the top-level workflow's tasks, so failures inside a sub-workflow may need the same treatment. Worth checking while fixing this.
File:
src/conductor/ai/agents/runtime/runtime.pySymptom:
No reason, no task name, nothing actionable. Diagnosing it means walking the server API by hand:
Cause: The helper already exists and works —
_extract_failed_task_reason(wf)reads the first FAILED task'sreasonForIncompletionand returnsTask '<ref>' failed: <reason>. It is called byrun()(line ~2534) and_run_by_name()(line ~2623), which is why native-agent failures do report properly, e.g.54_software_bug_assistantprintsERROR: Task 'software_assistant_54_list_mcp_0' failed: Failed to list MCP tools ... HTTP 400._run_framework()never calls it. It usesstatus.reasonalone (error=status.reason if raw_status in ("FAILED","TERMINATED") else None), and for these failuresstatus.reasonis empty — so the result isNone.Fix: Call
_extract_failed_task_reasonin_run_frameworkas a fallback whenstatus.reasonis empty, matchingrun().Verify: Start the server without
OPENAI_API_KEY, run93— it should name the failing task and its reason instead of printingNone.Possibly a second gap, unconfirmed:
59_coding_agentgoes throughrun()yet also reported no reason, while its server-side SUB_WORKFLOW task did carry one (Anthropic Messages API failed with status 404)._extract_failed_task_reasononly inspects the top-level workflow's tasks, so failures inside a sub-workflow may need the same treatment. Worth checking while fixing this.