Skip to content

fix(agent): keep guardrail retries on the async path in kickoff_async - #7292

Open
bunnysayzz wants to merge 1 commit into
crewAIInc:mainfrom
bunnysayzz:fix/kickoff-async-guardrail-retry-7252
Open

fix(agent): keep guardrail retries on the async path in kickoff_async#7292
bunnysayzz wants to merge 1 commit into
crewAIInc:mainfrom
bunnysayzz:fix/kickoff-async-guardrail-retry-7252

Conversation

@bunnysayzz

Copy link
Copy Markdown

Agent.kickoff_async() with a guardrail routes retries through the sync executor.invoke(). Under a running event loop that hands back an unawaited coroutine instead of a result dict, and _build_output_from_result crashes on result.get("output", "").

Fix: async variants _finalize_kickoff_async / _process_kickoff_guardrail_async that re-execute via _execute_and_build_output_async. To avoid duplicating the whole guardrail flow, the guardrail resolution and result-folding steps are extracted into shared helpers (_resolve_guardrail_callable, _apply_guardrail_result) used by both the sync and async paths; sync behavior is unchanged.

Tests: new test_agent_kickoff_guardrail_async.py — a fail-once guardrail over kickoff_async with the sync execute path rigged to explode proves the retry stays async (fails pre-fix), plus retry-exhaustion still raising. Existing sync guardrail tests (6) still pass.

Fixes #7252 (I was assigned this issue; opening alongside #7289 so maintainers can pick).

@coderabbitai

coderabbitai Bot commented Sep 6, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: 1e6f0b83-35fa-405b-ab09-23d70082ebfe

📥 Commits

Reviewing files that changed from the base of the PR and between 143e902 and 4332800.

📒 Files selected for processing (2)
  • lib/crewai/src/crewai/agent/core.py
  • lib/crewai/tests/agents/test_agent_kickoff_guardrail_async.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • lib/crewai/tests/agents/test_agent_kickoff_guardrail_async.py
  • lib/crewai/src/crewai/agent/core.py

Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review.


📝 Walkthrough

Walkthrough

The agent now uses dedicated asynchronous finalization and guardrail retry paths for kickoff_async. Shared helpers handle guardrail resolution and accepted results. Tests cover successful retries and retry exhaustion.

Changes

Async guardrail retry

Layer / File(s) Summary
Async guardrail finalization and retry
lib/crewai/src/crewai/agent/core.py
kickoff_async now finalizes through asynchronous guardrail processing. Rejected outputs retry with _execute_and_build_output_async. Shared helpers resolve guardrails and apply accepted results.
Async guardrail retry validation
lib/crewai/tests/agents/test_agent_kickoff_guardrail_async.py
Tests verify that retries use the async execution method and that exhausted retries raise the expected ValueError.

Sequence Diagram(s)

sequenceDiagram
  participant Agent
  participant Guardrail as _process_kickoff_guardrail_async
  participant Executor as _execute_and_build_output_async
  Agent->>Guardrail: evaluate kickoff output
  Guardrail->>Executor: retry rejected output asynchronously
  Executor-->>Guardrail: return retried output
  Guardrail->>Guardrail: evaluate guardrail again
  Guardrail-->>Agent: return accepted output or validation error
Loading

Merge Risk: ⚪ Minimal · up to c78bc

Async guardrail retries now await the asynchronous execution path, allowing later valid outputs to succeed and retry exhaustion to raise the expected validation error. No current merge-blocking risk is identified.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 78.57% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 14 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: keeping guardrail retries on the asynchronous path for kickoff_async.
Description check ✅ Passed The description identifies issue #7252, explains the cause and fix, and describes the added tests. It does not reproduce every template heading or checkbox, but it provides the required information in…
Linked Issues check ✅ Passed The changes satisfy issue #7252 by adding asynchronous guardrail finalization and retry processing through _execute_and_build_output_async. The tests cover successful retry, retry exhaustion, and pr…
Out of Scope Changes check ✅ Passed The modified production code and new tests are directly related to asynchronous guardrail retry handling and the linked issue. No unrelated changes are shown.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@bunnysayzz
bunnysayzz force-pushed the fix/kickoff-async-guardrail-retry-7252 branch from 6a375e6 to 4332800 Compare September 6, 2026 06:11
@coderabbitai

coderabbitai Bot commented Sep 6, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@bunnysayzz
bunnysayzz force-pushed the fix/kickoff-async-guardrail-retry-7252 branch from 4332800 to c760d9e Compare September 8, 2026 03:05
@bunnysayzz
bunnysayzz force-pushed the fix/kickoff-async-guardrail-retry-7252 branch from c760d9e to c78bcc4 Compare September 8, 2026 11:28
@bunnysayzz

Copy link
Copy Markdown
Author

Rebased onto latest main, no conflicts. The async guardrail tests (24 across the async kickoff and task guardrail suites) all pass on the rebased head.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Agent.kickoff_async guardrail retry calls sync invoke inside event loop

1 participant