Issue with CrewAI Agent Output Format Validation
Hi everyone,
I’m trying to run a CrewAI really simple flow with an agent and a task, but I keep getting validation errors related to the output format, even though the agent correctly returns the expected output ("I worked!"). I’m hoping someone can point me in the right direction.
Code
import asyncio
import json
from pydantic import BaseModel
from crewai import Agent, Task
from crewai.flow.flow import Flow, start
from langchain_openai import ChatOpenAI
# ---- STATE ----
class State(BaseModel):
steps: int = 0
code: str = ""
llm: str = "gpt-3.5-turbo"
# ---- FLOW ----
class DiagramFlow(Flow[State]):
def update_steps(self):
self.state.steps += 1
@start()
def node_1(self):
class OutputFormat(BaseModel):
text: str
extra_text: str
llm_instance = ChatOpenAI(
model_name=self.state.llm,
temperature=0.7,
)
# Create an Agent
agent_name = Agent(
role="Friendly assistant",
goal="Return a message that says 'I worked!'",
backstory="Testing agent call",
tools=[],
llm=llm_instance,
verbose=False,
)
task = Task(
description="Return a string that says: 'I worked!'",
expected_output="I worked!", # Attempt to solve the problem 1
output_pydantic=OutputFormat,# Attempt to solve the problem 2
)
result = agent_name.kickoff(task, response_format=OutputFormat)
print("Raw result:", result.raw) # Kinda works
print("Parsed output:", result.pydantic.text) # Error
return result
# ---- ENTRY POINT ----
if __name__ == "__main__":
state = State()
flow = DiagramFlow(state=state)
flow.kickoff()
Error
Failed to parse output into response format: 1 validation error for OutputFormat
Invalid JSON: key must be a string at line 1 column 2
[type=json_invalid, input_value="{'type': 'json_schema', ... 'extra_text': 'Success!'}", input_type=str]
Traceback (most recent call last):
...
AttributeError: 'NoneType' object has no attribute 'text'
The agent does return:
{'text': 'I worked!', 'extra_text': 'Success!'}
…but CrewAI fails to parse it into the Pydantic model, throwing a json_invalid error.
And i can’t actually take the result from the result variable, not even using result.raw
What I’ve Tried
- Passing the Pydantic model via
output_pydanticandresponse_format. - Making sure the task description and expected output match the returned values.
- Printing the raw result to verify the agent is returning correct data.
Question
Has anyone faced this json_invalid error when using output_pydantic in CrewAI? It seems like the agent is returning a Python-style dict (' quotes) instead of proper JSON (" quotes), which prevents parsing. Could be that?
Any suggestions on how to make CrewAI accept the output format correctly?
Thanks in advance!
Also
By trying different solutions i have got this other error message, no idea what i have messed up.
Starting LLM setup...
Starting task execution...
Agent failed to reach a final answer. This is likely a bug - please report it.
An unknown error occurred. Please check the details below.
Error details: 35 validation errors for LiteAgentExecutionStartedEvent
messages.str
Input should be a valid string [type=string_type, input_value=[{'role': 'system', 'cont...trigger_context', None)], input_type=list]
For further information visit https://errors.pydantic.dev/2.12/v/string_type
messages.list[dict[str,str]].1
Input should be a valid dictionary [type=dict_type, input_value=('used_tools', 0), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].2
Input should be a valid dictionary [type=dict_type, input_value=('tools_errors', 0), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].3
Input should be a valid dictionary [type=dict_type, input_value=('delegations', 0), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].4
Input should be a valid dictionary [type=dict_type, input_value=('i18n', I18N(prompt_file=None)), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].5
Input should be a valid dictionary [type=dict_type, input_value=('name', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].6
Input should be a valid dictionary [type=dict_type, input_value=('prompt_context', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].7
Input should be a valid dictionary [type=dict_type, input_value=('description', "\n ...that says: 'I worked!'"), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].8
Input should be a valid dictionary [type=dict_type, input_value=('expected_output', 'I worked!'), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].9
Input should be a valid dictionary [type=dict_type, input_value=('config', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].10
Input should be a valid dictionary [type=dict_type, input_value=('callback', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].11
Input should be a valid dictionary [type=dict_type, input_value=('agent', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].12
Input should be a valid dictionary [type=dict_type, input_value=('context', NOT_SPECIFIED), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].13
Input should be a valid dictionary [type=dict_type, input_value=('async_execution', False), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].14
Input should be a valid dictionary [type=dict_type, input_value=('output_json', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].15
Input should be a valid dictionary [type=dict_type, input_value=('output_pydantic', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].16
Input should be a valid dictionary [type=dict_type, input_value=('response_model', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].17
Input should be a valid dictionary [type=dict_type, input_value=('output_file', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].18
Input should be a valid dictionary [type=dict_type, input_value=('create_directory', True), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].19
Input should be a valid dictionary [type=dict_type, input_value=('output', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].20
Input should be a valid dictionary [type=dict_type, input_value=('tools', []), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].21
Input should be a valid dictionary [type=dict_type, input_value=('security_config', Secur...ngerprint(metadata={}))), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].22
Input should be a valid dictionary [type=dict_type, input_value=('id', UUID('38c49b6a-f65...48e-b673-6434cf56e2fc')), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].23
Input should be a valid dictionary [type=dict_type, input_value=('human_input', False), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].24
Input should be a valid dictionary [type=dict_type, input_value=('markdown', False), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].25
Input should be a valid dictionary [type=dict_type, input_value=('converter_cls', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].26
Input should be a valid dictionary [type=dict_type, input_value=('processed_by_agents', set()), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].27
Input should be a valid dictionary [type=dict_type, input_value=('guardrail', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].28
Input should be a valid dictionary [type=dict_type, input_value=('guardrails', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].29
Input should be a valid dictionary [type=dict_type, input_value=('max_retries', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].30
Input should be a valid dictionary [type=dict_type, input_value=('guardrail_max_retries', 3), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].31
Input should be a valid dictionary [type=dict_type, input_value=('retry_count', 0), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].32
Input should be a valid dictionary [type=dict_type, input_value=('start_time', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].33
Input should be a valid dictionary [type=dict_type, input_value=('end_time', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].34
Input should be a valid dictionary [type=dict_type, input_value=('allow_crewai_trigger_context', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
Traceback (most recent call last):
File "C:\Users\Burbu\OneDrive - UPV EHU\TFG\codigo\chatllm.py", line 62, in <module>
flow.kickoff() # 👈 esto ejecuta el flujo async correctamente
^^^^^^^^^^^^^^
File "C:\Users\Burbu\OneDrive - UPV EHU\TFG\codigo\venv\Lib\site-packages\crewai\flow\flow.py", line 816, in kickoff
return asyncio.run(_run_flow())
^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Burbu\AppData\Local\Programs\Python\Python312\Lib\asyncio\runners.py", line 195, in run
return runner.run(main)
^^^^^^^^^^^^^^^^
File "C:\Users\Burbu\AppData\Local\Programs\Python\Python312\Lib\asyncio\runners.py", line 118, in run
return self._loop.run_until_complete(task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Burbu\AppData\Local\Programs\Python\Python312\Lib\asyncio\base_events.py", line 691, in run_until_complete
return future.result()
^^^^^^^^^^^^^^^
File "C:\Users\Burbu\OneDrive - UPV EHU\TFG\codigo\venv\Lib\site-packages\crewai\flow\flow.py", line 814, in _run_flow
return await self.kickoff_async(inputs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Burbu\OneDrive - UPV EHU\TFG\codigo\venv\Lib\site-packages\crewai\flow\flow.py", line 897, in kickoff_async
await asyncio.gather(*tasks)
File "C:\Users\Burbu\OneDrive - UPV EHU\TFG\codigo\venv\Lib\site-packages\crewai\flow\flow.py", line 966, in _execute_start_method
result = await self._execute_method(start_method_name, enhanced_method)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Burbu\OneDrive - UPV EHU\TFG\codigo\venv\Lib\site-packages\crewai\flow\flow.py", line 1067, in _execute_method
raise e
File "C:\Users\Burbu\OneDrive - UPV EHU\TFG\codigo\venv\Lib\site-packages\crewai\flow\flow.py", line 1032, in _execute_method
else method(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Burbu\OneDrive - UPV EHU\TFG\codigo\venv\Lib\site-packages\crewai\flow\flow.py", line 998, in enhanced_method
return original_method(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Burbu\OneDrive - UPV EHU\TFG\codigo\venv\Lib\site-packages\crewai\flow\flow_wrappers.py", line 84, in __call__
return self._meth(self._instance, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Burbu\OneDrive - UPV EHU\TFG\codigo\chatllm.py", line 51, in node_1
result = agent_name.kickoff(task, response_format=OutputFormat)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Burbu\OneDrive - UPV EHU\TFG\codigo\venv\Lib\site-packages\crewai\agent\core.py", line 1238, in kickoff
return lite_agent.kickoff(messages)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Burbu\OneDrive - UPV EHU\TFG\codigo\venv\Lib\site-packages\crewai\lite_agent.py", line 307, in kickoff
raise e
File "C:\Users\Burbu\OneDrive - UPV EHU\TFG\codigo\venv\Lib\site-packages\crewai\lite_agent.py", line 291, in kickoff
return self._execute_core(agent_info=agent_info)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Burbu\OneDrive - UPV EHU\TFG\codigo\venv\Lib\site-packages\crewai\lite_agent.py", line 313, in _execute_core
event=LiteAgentExecutionStartedEvent(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Burbu\OneDrive - UPV EHU\TFG\codigo\venv\Lib\site-packages\pydantic\main.py", line 250, in __init__
validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pydantic_core._pydantic_core.ValidationError: 35 validation errors for LiteAgentExecutionStartedEvent
messages.str
Input should be a valid string [type=string_type, input_value=[{'role': 'system', 'cont...trigger_context', None)], input_type=list]
For further information visit https://errors.pydantic.dev/2.12/v/string_type
messages.list[dict[str,str]].1
Input should be a valid dictionary [type=dict_type, input_value=('used_tools', 0), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].2
Input should be a valid dictionary [type=dict_type, input_value=('tools_errors', 0), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].3
Input should be a valid dictionary [type=dict_type, input_value=('delegations', 0), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].4
Input should be a valid dictionary [type=dict_type, input_value=('i18n', I18N(prompt_file=None)), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].5
Input should be a valid dictionary [type=dict_type, input_value=('name', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].6
Input should be a valid dictionary [type=dict_type, input_value=('prompt_context', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].7
Input should be a valid dictionary [type=dict_type, input_value=('description', "\n ...that says: 'I worked!'"), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].8
Input should be a valid dictionary [type=dict_type, input_value=('expected_output', 'I worked!'), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].9
Input should be a valid dictionary [type=dict_type, input_value=('config', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].10
Input should be a valid dictionary [type=dict_type, input_value=('callback', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].11
Input should be a valid dictionary [type=dict_type, input_value=('agent', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].12
Input should be a valid dictionary [type=dict_type, input_value=('context', NOT_SPECIFIED), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].13
Input should be a valid dictionary [type=dict_type, input_value=('async_execution', False), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].14
Input should be a valid dictionary [type=dict_type, input_value=('output_json', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].15
Input should be a valid dictionary [type=dict_type, input_value=('output_pydantic', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].16
Input should be a valid dictionary [type=dict_type, input_value=('response_model', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].17
Input should be a valid dictionary [type=dict_type, input_value=('output_file', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].18
Input should be a valid dictionary [type=dict_type, input_value=('create_directory', True), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].19
Input should be a valid dictionary [type=dict_type, input_value=('output', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].20
Input should be a valid dictionary [type=dict_type, input_value=('tools', []), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].21
Input should be a valid dictionary [type=dict_type, input_value=('security_config', Secur...ngerprint(metadata={}))), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].22
Input should be a valid dictionary [type=dict_type, input_value=('id', UUID('38c49b6a-f65...48e-b673-6434cf56e2fc')), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].23
Input should be a valid dictionary [type=dict_type, input_value=('human_input', False), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].24
Input should be a valid dictionary [type=dict_type, input_value=('markdown', False), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].25
Input should be a valid dictionary [type=dict_type, input_value=('converter_cls', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].26
Input should be a valid dictionary [type=dict_type, input_value=('processed_by_agents', set()), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].27
Input should be a valid dictionary [type=dict_type, input_value=('guardrail', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].28
Input should be a valid dictionary [type=dict_type, input_value=('guardrails', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].29
Input should be a valid dictionary [type=dict_type, input_value=('max_retries', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].30
Input should be a valid dictionary [type=dict_type, input_value=('guardrail_max_retries', 3), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].31
Input should be a valid dictionary [type=dict_type, input_value=('retry_count', 0), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].32
Input should be a valid dictionary [type=dict_type, input_value=('start_time', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].33
Input should be a valid dictionary [type=dict_type, input_value=('end_time', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
messages.list[dict[str,str]].34
Input should be a valid dictionary [type=dict_type, input_value=('allow_crewai_trigger_context', None), input_type=tuple]
For further information visit https://errors.pydantic.dev/2.12/v/dict_type
🌊 Flow: DiagramFlow
ID: 7878c5d2-a5e8-4d7b-a368-7de9f326cdb9
├── ✨ Created
├── ✅ Initialization Complete
└── ❌ Failed: node_1