You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
-**Caching Mechanism**: Features intelligent caching to optimize performance and reduce redundant operations.
41
41
-**Asynchronous Support**: Handles both synchronous and asynchronous tools, enabling non-blocking operations.
42
-
-**Typed Outputs**: Optionally validates tool results with Pydantic models and sends agents a JSON-safe representation while preserving the raw Python value for direct calls and hooks.
42
+
-**Typed Outputs**: Uses optional Pydantic models to give agents clear JSON fields while direct Python calls still receive the tool's normal return value.
43
43
44
44
## Using CrewAI Tools
45
45
@@ -187,48 +187,52 @@ class MyCustomTool(BaseTool):
187
187
188
188
### Typed Tool Outputs
189
189
190
-
As a best practice, define a Pydantic output model when a tool returns structured data. CrewAI keeps `tool.run(...)` unchanged: it returns the raw Python value from `_run`. During agent execution, CrewAI validates that raw value against the tool's `output_schema` and sends the agent a JSON string.
190
+
When a tool returns structured data, define a Pydantic output model. This gives the agent field names it can trust, such as `sku`, `quantity`, or `needs_reorder`.
191
+
192
+
Direct Python calls still receive the value your tool returns. When an agent uses the tool, CrewAI sends the agent a JSON string based on the output model.
191
193
192
194
```python Code
193
195
from crewai.tools import BaseTool
194
196
from pydantic import BaseModel
195
197
196
-
classSearchResult(BaseModel):
197
-
query: str
198
-
score: float
198
+
classInventoryResult(BaseModel):
199
+
sku: str
200
+
quantity: int
201
+
needs_reorder: bool
199
202
200
-
classSearchTool(BaseTool):
201
-
name: str="Search"
202
-
description: str="Searches for a query and returns the top match score."
203
+
classInventoryTool(BaseTool):
204
+
name: str="Inventory Check"
205
+
description: str="Checks current stock for a product SKU."
To send a custom representation to the agent, such as Markdown, override `format_output_for_agent` on your `BaseTool` subclass. This does not change direct execution: `tool.run(...)` still returns the raw Python value.
218
+
To send Markdown or another short text format to the agent, override `format_output_for_agent`. Direct calls to `tool.run(...)` still return the normal Python value.
215
219
216
220
```python Code
217
-
classSearchTool(BaseTool):
218
-
name: str="Search"
219
-
description: str="Searches for a query and returns the top match score."
221
+
classInventoryTool(BaseTool):
222
+
name: str="Inventory Check"
223
+
description: str="Checks current stock for a product SKU."
If you do not override `format_output_for_agent`, CrewAI uses the default typed-output behavior: Pydantic outputs become JSON for the agent, and untyped outputs use `str(raw_result)`.
230
-
231
-
If validation or serialization fails during agent execution, CrewAI emits a runtime warning and falls back to `str(raw_result)` for the agent-facing text. Direct tool calls still receive the raw result.
235
+
If you do not override `format_output_for_agent`, typed outputs are sent to the agent as JSON. Plain string results work as before.
Copy file name to clipboardExpand all lines: docs/edge/en/guides/tools/publish-custom-tools.mdx
+13-11Lines changed: 13 additions & 11 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -106,11 +106,11 @@ Explicit schemas are recommended for published tools — they produce better age
106
106
107
107
### Optional: Typed Outputs with `output_schema`
108
108
109
-
If your tool returns structured data, define a Pydantic output model. This is a best practice for published tools because it gives agents a predictable JSON shape while preserving the raw Python value for direct users of your package.
109
+
If your tool returns structured data, define a Pydantic output model. This is a good default for published tools because users and agents can rely on named fields.
110
110
111
-
CrewAI keeps direct execution unchanged: `tool.run(...)` returns the raw value from your tool. During agent execution, CrewAI validates that raw value against the output schema and sends the agent a JSON string. If validation or serialization fails, CrewAI warns and falls back to `str(raw_result)` for the agent-facing text.
111
+
Direct Python calls still receive the value your tool returns. When an agent uses the tool, CrewAI sends the agent JSON based on the output model.
112
112
113
-
You can let CrewAI infer the output schema from a Pydantic return annotation:
113
+
CrewAI can infer the output schema from a Pydantic return annotation:
114
114
115
115
```python
116
116
from crewai.tools import BaseTool
@@ -127,10 +127,12 @@ class GeolocateTool(BaseTool):
127
127
description: str="Converts a street address into latitude/longitude coordinates."
If agents should receive a custom text format instead of JSON, override `format_output_for_agent` on your `BaseTool` subclass. This is useful when the best agent-facing representation is Markdown, a terse summary, or another format derived from the same raw result.
149
+
If agents should receive a short text summary instead of JSON, override `format_output_for_agent` on your `BaseTool` subclass.
146
150
147
151
```python
148
152
classGeolocateTool(BaseTool):
149
153
name: str="Geolocate"
150
154
description: str="Converts a street address into latitude/longitude coordinates."
When a tool returns structured data, define the output as a Pydantic model. This is optional, but recommended because it gives CrewAI a clear contract for the data your tool returns.
58
+
When a tool returns structured data, define a Pydantic output model. This helps the agent read the result as clear fields instead of guessing from plain text.
59
59
60
-
Typed outputs create a clear split between direct Python usage and agent execution:
60
+
Typed outputs are useful for results with stable fields, such as IDs, status values, scores, prices, or lists. Plain strings are still fine for short prose results.
61
61
62
-
-`tool.run(...)` returns the raw Python value from your tool.
63
-
- Agent execution validates the raw value with the tool's output schema and sends the agent an LLM-safe string.
64
-
- Valid Pydantic outputs are serialized to JSON for the agent.
65
-
- If validation or serialization fails, CrewAI emits a runtime warning and falls back to `str(raw_result)` only for the agent-facing text.
62
+
Direct Python calls still receive the value your tool returns. When an agent uses a typed tool, CrewAI sends the agent JSON based on the output model.
66
63
67
64
#### Return a Pydantic Model
68
65
69
-
CrewAI infers the output schema when your `BaseTool`or `@tool` function has a Pydantic return annotation.
66
+
CrewAI infers the output schema when your `BaseTool` has a Pydantic return annotation.
70
67
71
68
```python Code
72
69
from crewai.tools import BaseTool
73
70
from pydantic import BaseModel, Field
74
71
75
-
classSentimentResult(BaseModel):
76
-
label: str= Field(description="The sentiment label, such as positive, neutral, or negative.")
77
-
confidence: float= Field(description="Confidence score from 0 to 1.")
This is easier for the agent to reason over than a Python object representation.
102
-
103
-
#### Use `output_schema` for Dictionary Results
104
-
105
-
If your implementation naturally returns a dictionary, set `output_schema` explicitly. CrewAI validates the dictionary and serializes the validated result to JSON for the agent.
106
-
107
-
```python Code
108
-
from crewai.tools import BaseTool
109
-
from pydantic import BaseModel, Field
110
-
111
-
classProductLookupResult(BaseModel):
112
-
sku: str= Field(description="The product SKU.")
113
-
name: str= Field(description="The product name.")
114
-
in_stock: bool= Field(description="Whether the product is available.")
115
-
116
-
classProductLookupTool(BaseTool):
117
-
name: str="Product Lookup"
118
-
description: str="Look up product availability by SKU."
By default, typed tool outputs are sent to the agent as JSON. If your agent should receive Markdown, XML, or a compact human-readable summary instead, subclass `BaseTool` and override `format_output_for_agent`.
153
-
154
-
This only changes the agent-facing text. Direct calls to `tool.run(...)` still return the raw Python value from `_run`.
128
+
By default, typed tool outputs are sent to the agent as JSON. If the agent should receive a short summary instead, subclass `BaseTool` and override `format_output_for_agent`.
155
129
156
130
```python Code
157
131
from crewai.tools import BaseTool
158
132
from pydantic import BaseModel, Field
159
133
160
-
classProductLookupResult(BaseModel):
134
+
classInventoryResult(BaseModel):
161
135
sku: str= Field(description="The product SKU.")
162
-
name: str= Field(description="The product name.")
163
-
in_stock: bool= Field(description="Whether the product is available.")
# Direct Python calls receive the raw Pydantic object.
189
-
print(result.name)
156
+
print(result.quantity)
190
157
```
191
158
192
-
When an agent calls `ProductLookupTool`, it receives the Markdown returned by `format_output_for_agent`. When you do not override this method, CrewAI uses the default behavior: validate typed outputs and serialize them to JSON, or use `str(raw_result)` for untyped outputs.
193
-
194
-
Use typed outputs for tool results that have stable fields, nested data, lists, IDs, status values, scores, or any structure the agent should interpret precisely. Plain strings are still fine for simple prose results.
159
+
The override only changes what the agent sees. Direct calls to `tool.run(...)` still return the normal Python value.
Copy file name to clipboardExpand all lines: docs/edge/en/learn/execution-hooks.mdx
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -199,7 +199,7 @@ class ToolCallHookContext:
199
199
raw_tool_result: Any |None# Raw Python result (after hooks)
200
200
```
201
201
202
-
For typed tool outputs, `tool_result` is the JSON string sent to the agent, while`raw_tool_result` is the original Python value returned by the tool.
202
+
For typed tool outputs, `tool_result` is the string the agent sees. By default, this is JSON. If the tool uses custom formatting, it can be Markdown or another string.`raw_tool_result` is the original Python value returned by the tool.
Copy file name to clipboardExpand all lines: docs/edge/en/learn/tool-hooks.mdx
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -64,7 +64,7 @@ class ToolCallHookContext:
64
64
raw_tool_result: Any |None# Raw Python result (after hooks only)
65
65
```
66
66
67
-
For typed tool outputs, `tool_result` is the JSON string sent to the agent, while `raw_tool_result`is the original Python value returned by the tool. Use `raw_tool_result` when your hook needs the typed object or dictionary; return a string from the hook only when you want to change the agent-facing result.
67
+
For typed tool outputs, `tool_result` is the string the agent sees. By default, this is JSON. If the tool uses custom formatting, it can be Markdown or another string. Use `raw_tool_result` when your hook needs the typed object or dictionary.
0 commit comments