compat: treat natural no_tool finish as a complete run - #24
Conversation
Two parity gaps for OpenAI-compatible models that end a task with a plain-text answer instead of a final tool call (observed with Qwen3.5-based local endpoints): 1. workflows/stateful_react_agent/_runtime.py: _GRACEFUL_FINAL_STOP_ REASONS does not include "no_tool", so force_final_answer() rescue is skipped even though the model produced its answer and the loop ended naturally. 2. apodex/task_runner.py: the native-workflow path calls _is_complete_ run() without no_tool_is_complete=True, unlike the generic loop path (L396), so the same natural finish is reported as "run incomplete" and the report is not saved. With both applied, a local qwen3.8-27b endpoint completes the stateful react workflow end to end and the final report is saved.
|
Thanks for the attempt to fix. I think the reported issue is valid, but the root cause is that In Therefore, globally treating I suggest introducing explicit stop reasons such as |
zhanghanduo
left a comment
There was a problem hiding this comment.
The reported stateful_react issue is valid, but this fix is too broad.
Passing no_tool_is_complete=True from _run_native_workflow() makes every
native-workflow stopped_by="no_tool" a completed delivery, even though
no_tool is not a uniform success signal across workflows.
In agent_team, successful plain-text completion is converted to
final_answer by BareTextFinalizeObserver. The remaining no_tool cases
typically represent exhausted empty-response/nudge retries and are incomplete.
Marking them complete would regress the behavior covered by:
apodex/tests/test_features.py::test_native_workflow_no_tool_stop_is_not_reported_as_delivery
Please distinguish successful plain-text completion from exhausted no-tool
retries—through explicit stop reasons or an authoritative workflow completion
status—rather than treating no_tool as globally successful.
Summary
Two parity gaps break the stateful react workflow for OpenAI-compatible models that end a task with a plain-text answer instead of a final tool call. Reproduced with a local Qwen3.5-family endpoint (qwen3.8-27b via Ollama
/v1).Changes
workflows/stateful_react_agent/_runtime.py— addno_toolto_GRACEFUL_FINAL_STOP_REASONSsoforce_final_answer()rescue runs when the loop ends naturally after the model has already produced its answer.apodex/task_runner.py— passno_tool_is_complete=Truein the native-workflow completion check, matching the generic-loop path (which already passes it).Verification
run incomplete · stopped_by=no_tool · partial output was not saved as a final report.Notes
no_tool_is_complete=True; this makes the native workflow consistent.