fix(delegate-task): recover batch tasks from JSON-encoded string coer…#22092
fix(delegate-task): recover batch tasks from JSON-encoded string coer…#22092uzunkuyruk wants to merge 1 commit into
Conversation
…cion Open-weight models (Qwen, DeepSeek, GLM) sometimes emit the tasks array as a JSON-encoded string instead of a native array. The existing coerce_tool_args fallback silently wrapped this into a single-element list, causing batch delegation to fail with a confusing error. Three-layer fix: - _coerce_json: log a warning when JSON parsing fails or yields the wrong type, instead of silently returning the original string - coerce_tool_args: detect strings that look like JSON arrays before wrapping, and emit a clear warning to aid debugging - delegate_task: add post-coercion recovery — if tasks arrives as a single-element list containing a JSON string, attempt to parse and unwrap it before validation, restoring batch mode for affected models Fixes NousResearch#21933
When _coerce_json fails to parse a string as JSON or parses to the wrong type, log a clear WARNING instead of silently returning the original value. When coerce_tool_args wraps a bare string into a single-element list AND the string looks like a JSON array (starts with '['), warn that the model likely emitted a JSON-encoded string instead of a native array. This improves diagnostics for the open-weight model output drift described in #21933 (JSON-array-as-string), as well as any other tool whose array-typed argument arrives stringified through handle_function_call. Note: delegate_task does NOT go through coerce_tool_args (it is in _AGENT_LOOP_TOOLS and dispatched directly from run_agent.py with raw function_args from json.loads). The actual delegate_task fix for #21933 is the previous commit. These logging changes apply to all other array-typed arguments coerced via the shared pipeline. Salvaged from PR #22092.
|
Merged via #22436. Your The The fix that does work (handling the raw string case) was salvaged from #21966 by @Bartok9 in commit |
When _coerce_json fails to parse a string as JSON or parses to the wrong type, log a clear WARNING instead of silently returning the original value. When coerce_tool_args wraps a bare string into a single-element list AND the string looks like a JSON array (starts with '['), warn that the model likely emitted a JSON-encoded string instead of a native array. This improves diagnostics for the open-weight model output drift described in NousResearch#21933 (JSON-array-as-string), as well as any other tool whose array-typed argument arrives stringified through handle_function_call. Note: delegate_task does NOT go through coerce_tool_args (it is in _AGENT_LOOP_TOOLS and dispatched directly from run_agent.py with raw function_args from json.loads). The actual delegate_task fix for NousResearch#21933 is the previous commit. These logging changes apply to all other array-typed arguments coerced via the shared pipeline. Salvaged from PR NousResearch#22092.
When _coerce_json fails to parse a string as JSON or parses to the wrong type, log a clear WARNING instead of silently returning the original value. When coerce_tool_args wraps a bare string into a single-element list AND the string looks like a JSON array (starts with '['), warn that the model likely emitted a JSON-encoded string instead of a native array. This improves diagnostics for the open-weight model output drift described in NousResearch#21933 (JSON-array-as-string), as well as any other tool whose array-typed argument arrives stringified through handle_function_call. Note: delegate_task does NOT go through coerce_tool_args (it is in _AGENT_LOOP_TOOLS and dispatched directly from run_agent.py with raw function_args from json.loads). The actual delegate_task fix for NousResearch#21933 is the previous commit. These logging changes apply to all other array-typed arguments coerced via the shared pipeline. Salvaged from PR NousResearch#22092.
When _coerce_json fails to parse a string as JSON or parses to the wrong type, log a clear WARNING instead of silently returning the original value. When coerce_tool_args wraps a bare string into a single-element list AND the string looks like a JSON array (starts with '['), warn that the model likely emitted a JSON-encoded string instead of a native array. This improves diagnostics for the open-weight model output drift described in NousResearch#21933 (JSON-array-as-string), as well as any other tool whose array-typed argument arrives stringified through handle_function_call. Note: delegate_task does NOT go through coerce_tool_args (it is in _AGENT_LOOP_TOOLS and dispatched directly from run_agent.py with raw function_args from json.loads). The actual delegate_task fix for NousResearch#21933 is the previous commit. These logging changes apply to all other array-typed arguments coerced via the shared pipeline. Salvaged from PR NousResearch#22092.
When _coerce_json fails to parse a string as JSON or parses to the wrong type, log a clear WARNING instead of silently returning the original value. When coerce_tool_args wraps a bare string into a single-element list AND the string looks like a JSON array (starts with '['), warn that the model likely emitted a JSON-encoded string instead of a native array. This improves diagnostics for the open-weight model output drift described in NousResearch#21933 (JSON-array-as-string), as well as any other tool whose array-typed argument arrives stringified through handle_function_call. Note: delegate_task does NOT go through coerce_tool_args (it is in _AGENT_LOOP_TOOLS and dispatched directly from run_agent.py with raw function_args from json.loads). The actual delegate_task fix for NousResearch#21933 is the previous commit. These logging changes apply to all other array-typed arguments coerced via the shared pipeline. Salvaged from PR NousResearch#22092.
|
Appreciate the careful diagnosis. You're right — I'd targeted the wrapped Good salvage call taking the diagnostic logging from |
When _coerce_json fails to parse a string as JSON or parses to the wrong type, log a clear WARNING instead of silently returning the original value. When coerce_tool_args wraps a bare string into a single-element list AND the string looks like a JSON array (starts with '['), warn that the model likely emitted a JSON-encoded string instead of a native array. This improves diagnostics for the open-weight model output drift described in NousResearch#21933 (JSON-array-as-string), as well as any other tool whose array-typed argument arrives stringified through handle_function_call. Note: delegate_task does NOT go through coerce_tool_args (it is in _AGENT_LOOP_TOOLS and dispatched directly from run_agent.py with raw function_args from json.loads). The actual delegate_task fix for NousResearch#21933 is the previous commit. These logging changes apply to all other array-typed arguments coerced via the shared pipeline. Salvaged from PR NousResearch#22092.
When _coerce_json fails to parse a string as JSON or parses to the wrong type, log a clear WARNING instead of silently returning the original value. When coerce_tool_args wraps a bare string into a single-element list AND the string looks like a JSON array (starts with '['), warn that the model likely emitted a JSON-encoded string instead of a native array. This improves diagnostics for the open-weight model output drift described in NousResearch#21933 (JSON-array-as-string), as well as any other tool whose array-typed argument arrives stringified through handle_function_call. Note: delegate_task does NOT go through coerce_tool_args (it is in _AGENT_LOOP_TOOLS and dispatched directly from run_agent.py with raw function_args from json.loads). The actual delegate_task fix for NousResearch#21933 is the previous commit. These logging changes apply to all other array-typed arguments coerced via the shared pipeline. Salvaged from PR NousResearch#22092.
When _coerce_json fails to parse a string as JSON or parses to the wrong type, log a clear WARNING instead of silently returning the original value. When coerce_tool_args wraps a bare string into a single-element list AND the string looks like a JSON array (starts with '['), warn that the model likely emitted a JSON-encoded string instead of a native array. This improves diagnostics for the open-weight model output drift described in NousResearch#21933 (JSON-array-as-string), as well as any other tool whose array-typed argument arrives stringified through handle_function_call. Note: delegate_task does NOT go through coerce_tool_args (it is in _AGENT_LOOP_TOOLS and dispatched directly from run_agent.py with raw function_args from json.loads). The actual delegate_task fix for NousResearch#21933 is the previous commit. These logging changes apply to all other array-typed arguments coerced via the shared pipeline. Salvaged from PR NousResearch#22092.
What does this PR do?
Fixes silent batch delegation failures when open-weight models (Qwen, DeepSeek, GLM) emit the
tasksarray as a JSON-encoded string instead of a native array.When this happens,
coerce_tool_argssilently wraps the string into a single-element list["[{...}]"]. Thedelegate_taskfunction then receives a list containing one string, passes theisinstance(tasks, list)check, and crashes ontask.get("goal")— or falls through to the unhelpful"Provide either 'goal' or 'tasks'"error.Three-layer fix:
_coerce_json: now logs aWARNINGwhen JSON parsing fails or yields the wrong type, instead of returning the original string silentlycoerce_tool_args: detects strings that look like JSON arrays (start with[) before wrapping, and emits a clear warning to aid debuggingdelegate_task: adds post-coercion recovery — iftasksarrives as a single-element list containing a JSON string, attempt to parse and unwrap it before validation, restoring batch mode for affected modelsType of Change
References
Fixes #21933
Checklist