From 3349cfcb92610e2cc47044a5cb225982f0424396 Mon Sep 17 00:00:00 2001 From: lorenzejay Date: Thu, 21 May 2026 16:11:15 -0700 Subject: [PATCH] addressing comments --- .../structured_output_with_tools_runner.py | 46 +++++++++++++++++++ lib/crewai/src/crewai/agent/core.py | 4 +- lib/crewai/src/crewai/lite_agent.py | 3 +- 3 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 lib/crewai/scripts/structured_output_with_tools_runner.py diff --git a/lib/crewai/scripts/structured_output_with_tools_runner.py b/lib/crewai/scripts/structured_output_with_tools_runner.py new file mode 100644 index 000000000..9b6f77ec5 --- /dev/null +++ b/lib/crewai/scripts/structured_output_with_tools_runner.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +"""Minimal Flow runner: Agent.kickoff() + response_format + tool. + + cd lib/crewai + uv run python scripts/structured_output_with_tools_runner.py +""" + +from pydantic import BaseModel, Field + +from crewai import Agent +from crewai.flow import Flow, start +from crewai.tools import tool + + +class CalculationResult(BaseModel): + operation: str = Field(description="Operation performed") + result: int = Field(description="Numeric result") + explanation: str = Field(description="Short explanation") + + +@tool +def add_numbers(a: int, b: int) -> int: + """Add two integers.""" + return a + b + + +class StructuredOutputFlow(Flow): + @start() + def run(self): + agent = Agent( + role="Calculator", + goal="Use tools and return structured results", + backstory="Compute with tools, then answer in the required schema.", + tools=[add_numbers], + verbose=True, + llm='anthropic/claude-sonnet-4-6' + ) + return agent.kickoff( + "Use add_numbers to compute 15 + 27.", + response_format=CalculationResult, + ) + + +if __name__ == "__main__": + result = StructuredOutputFlow().kickoff() + print(result.pydantic) diff --git a/lib/crewai/src/crewai/agent/core.py b/lib/crewai/src/crewai/agent/core.py index d257cc6f5..0214f6bd5 100644 --- a/lib/crewai/src/crewai/agent/core.py +++ b/lib/crewai/src/crewai/agent/core.py @@ -1694,7 +1694,8 @@ class Agent(BaseAgent): try: formatted_result = response_format.model_validate_json(raw_output) except ValidationError: - pass + # Direct JSON validation failed; fall back to converter-based parsing below. + formatted_result = None if formatted_result is None: try: @@ -1715,6 +1716,7 @@ class Agent(BaseAgent): if isinstance(conversion_result, BaseModel): formatted_result = conversion_result except ConverterError: + # Conversion failure is non-fatal; raw output is preserved below. pass else: raw_output = str(output) if not isinstance(output, str) else output diff --git a/lib/crewai/src/crewai/lite_agent.py b/lib/crewai/src/crewai/lite_agent.py index c68b803ec..a809af703 100644 --- a/lib/crewai/src/crewai/lite_agent.py +++ b/lib/crewai/src/crewai/lite_agent.py @@ -644,7 +644,8 @@ class LiteAgent(FlowTrackable, BaseModel): str(agent_finish.output) ) except ValidationError: - pass + # Direct JSON validation failed; fall back to converter-based parsing below. + formatted_result = None if formatted_result is None: try: