Skip to content

fix(task): use acall for output conversion in async paths#5696

Merged
greysonlalonde merged 1 commit intomainfrom
gl/fix/async-export-output-converter
May 4, 2026
Merged

fix(task): use acall for output conversion in async paths#5696
greysonlalonde merged 1 commit intomainfrom
gl/fix/async-export-output-converter

Conversation

@greysonlalonde
Copy link
Copy Markdown
Contributor

@greysonlalonde greysonlalonde commented May 4, 2026

Fixes #5230


Note

Medium Risk
Touches task execution/output conversion paths and adds new async conversion code; mistakes could cause incorrect structured outputs or unexpected blocking/behavior differences under async workloads.

Overview
Fixes async task output conversion to be natively non-blocking: async task execution and async guardrail retries now export structured outputs via new Task._aexport_output() instead of the sync _export_output().

Adds an async conversion pipeline in utilities/converter.py (ato_pydantic, ato_json, async_convert_to_model and helpers) that uses llm.acall and offloads the sync-only InternalInstructor.to_json via asyncio.to_thread, plus refactors shared validation/unpacking logic.

Extends async tests to assert the async conversion path never calls blocking llm.call and that function-calling JSON conversion is threaded.

Reviewed by Cursor Bugbot for commit d61dae8. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions github-actions Bot added the size/L label May 4, 2026
Copy link
Copy Markdown
Contributor

@iris-clawd iris-clawd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean async conversion pipeline. Reviewed the full diff:

Good:

  • _aexport_outputasync_convert_to_modelato_pydantic/ato_json — mirrors the sync dispatch exactly, just with acall instead of call.
  • Shared logic refactored into _build_messages, _coerce_response_to_pydantic, and _unpack_model_output — reduces duplication between sync/async paths nicely.
  • asyncio.to_thread for the function-calling JSON path (InternalInstructor.to_json) is the right call since that's sync-only.
  • Tests properly assert acall is used (not call) and that the to_thread offload happens.

One nit: missing trailing newline at end of test_async_task.py (last line is mock_to_thread.assert_awaited_once_with(instructor.to_json) with no newline). Won't break anything but some linters care.

LGTM ✅

@greysonlalonde greysonlalonde merged commit a058a3b into main May 4, 2026
55 checks passed
@greysonlalonde greysonlalonde deleted the gl/fix/async-export-output-converter branch May 4, 2026 10:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Do not invoke synchronous call() on LLM from asynchronous workflow in _export_output / converter

2 participants