conductor-oss / conductor-oss/python-sdk

Framework-agent failures return `None` instead of the failed task's reason

Open Beginner friendly
#483 0 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
Python
Stars
104
Forks
42
Avg merge
2d 1h
Merged PRs (30d)
3

Description

**In short:** when a framework agent fails, the SDK prints `None` instead of the reason — even though the server recorded a perfectly good one. Every such failure costs a manual walk of the server API to diagnose.

**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/?includeTasks=true" # find FAILED tasks, read reasonForIncompletion
```

## Cause

`_run_framework()` reports:

```python
error=status.reason if raw_status in ("FAILED", "TERMINATED") else None
```

For these failures `status.reason` is empty, so the result is `None`.

The reason was available all along, at both levels of the execution:

- the **workflow's** own `reasonForIncompletion`:
```
Task 41830611-7c25-4d51-a36f-50e324e59239 failed with status: FAILED and reason:
'Task execution failed: OpenAI Responses API call failed: Responses API failed with status 401 ...'
```
- the failed **task's** `reasonForIncompletion` (`Assistant_llm`), carrying the same text.

There is also an existing helper that already does this. `_extract_failed_task_reason(wf)` reads the first FAILED task's `reasonForIncompletion` and returns `Task '' failed: `. It is called by `run()` (line ~2534) and `_run_by_name()` (line ~2623) — which is why **native**-agent failures 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.

## Fix

When `status.reason` is empty, fall back to the workflow's `reasonForIncompletion`, or call `_extract_failed_task_reason` as `run()` does. Either is sufficient.

## Verify

Start the server without `OPENAI_API_KEY`, run `93` — it should name the failing task and its reason instead of printing `None`.

## Note — possible 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.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start in src/conductor/ai/agents/runtime/runtime.py at _run_framework(), then compare its failure reporting with _extract_failed_task_reason and the calls from run() and _run_by_name(). Run examples/agents/93_openai_runner_hello_world.py with the server lacking OPENAI_API_KEY; done means the framework-agent failure names the failed task and reports its reason instead of None.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.