Files
crewAI/docs
João MouraandClaude Opus 5.5 75808b0eca
Nightly Canary Release / Check for new commits (push) Has been cancelled
Nightly Canary Release / Build nightly packages (push) Has been cancelled
Nightly Canary Release / Publish nightly to PyPI (push) Has been cancelled
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Check Documentation Broken Links / Check broken links (push) Has been cancelled
Vulnerability Scan / Detect changes (push) Has been cancelled
Vulnerability Scan / pip-audit (push) Has been cancelled
fix(flow): learn from resumed human feedback and keep the reviewed output's type (#8142)
* fix(flow): learn from human feedback that resumes a paused flow

With learn=True, lessons were distilled only when the reply arrived
during the same run. A reply that resumes a paused flow (resume /
resume_async after from_pending, which is how async providers such as
AMP's email review work) went through outcome collapse and routing but
never reached _distill_and_store_lessons, so it taught nothing.

Resume now stores lessons under the same conditions as an in-run reply:
memory available, non-empty feedback, the method's learn_source and
learn_strict, and the persisted LLM config. Both paths share one helper.
A strict distillation failure fails the resume before the pending review
is cleared, so it can be retried.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(flow): undo the recorded reply when strict learning fails on resume

_finalize_human_feedback appends the reply to human_feedback_history and
sets last_human_feedback before lessons are stored. With learn_strict, a
distillation failure re-raises and the review stays pending, so a retry
on the same instance recorded the reply twice. Restore both on failure.
Lesson storage stays after outcome collapse, so a collapse failure never
leaves lessons behind to be stored again on retry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(flow): keep the reviewed output's type when learn=True pre-reviews it

Pre-review always returned PreReviewResult.improved_output, a str, so a
method returning a Pydantic model or a dict reached the reviewer, and
last_human_feedback.output, as a repr string. Text output is still
rewritten as text; a Pydantic model is now rewritten as the same model
(response_model=type(output)); other outputs are shown unchanged.

LiteLLM-routed models return structured output as a JSON string, which
PreReviewResult/DistilledLessons.model_validate rejected, so pre-review
and lesson storage silently did nothing for them. One parser now accepts
an instance, a JSON string, or a dict.

Docs (en, ar, ko, pt-BR): drop the nonexistent learn_limit, document
learn_source and learn_strict, say lessons are also learned from replies
that resume a paused flow, how each output type is pre-reviewed, and that
downstream steps should read last_human_feedback.output. Correct the
HumanFeedbackResult.output docstring and the learn/learn_strict field
descriptions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(flow): keep pre-review failures and unseen fields from leaking into the output

model_dump_json() ran before the pre-review try, so a Pydantic output that
cannot be serialized failed the feedback step even with learn_strict off.
It now runs inside the try and falls back to the original output.

A reviewed Pydantic model is rebuilt from what the LLM saw, so a SecretStr
(sent masked) or an excluded field (not sent) came back as the mask or the
default. Fields the review left unchanged now keep their original values.

Also pin that a retry after a persistence failure that follows lesson
storage offers the lessons to memory again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(flow): keep nested hidden values when pre-review edits sibling fields

The unchanged-field restore only looked at top-level fields, so editing a
sibling inside a nested model, or one item of a list of models, kept the
LLM's masked secret and default excluded values for that whole object.
The restore now recurses into nested models and same-length lists of
models.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(flow): skip pre-review for models holding secrets or excluded fields

Restoring hidden values after the review kept growing edge cases: aliased
fields compared by name discarded the review's edit, dicts of models were
not recursed, and reordered lists paired the wrong items, which could
copy one account's secret onto another. Drop the merge. A Pydantic output
is pre-reviewed only when the LLM sees all of it; one holding a Secret,
SecretStr, SecretBytes or Field(exclude=True) value at any depth reaches
the reviewer unchanged. Docs updated in en, ar, ko and pt-BR.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(flow): say a resumed review's Pydantic output arrives as a dict

PendingFeedbackContext persists method_output as JSON, so after
from_pending and resume, last_human_feedback.output is a dict even when
the method returned a model. The docstring and docs said "same type"
without that qualification. Also say learn_strict covers distillation
and submitting lessons, not the background memory write. Pin the dict
behavior with a pause/resume test. Docs in en, ar, ko and pt-BR.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 03:05:26 +00:00
..