mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-10-20 00:45:04 +02:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aee571b775 | ||
|
|
cb46a1c4ba | ||
|
|
d9046b98dd |
No files matched your search
@@ -4,6 +4,54 @@ description: "تحديثات المنتج والتحسينات وإصلاحات
|
||||
icon: "clock"
|
||||
mode: "wide"
|
||||
---
|
||||
<Update label="25 أبريل 2026">
|
||||
## v1.14.3
|
||||
|
||||
[عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.3)
|
||||
|
||||
## ما الذي تغير
|
||||
|
||||
### الميزات
|
||||
- إضافة أحداث دورة الحياة لعمليات نقطة التحقق
|
||||
- إضافة دعم لـ e2b
|
||||
- الرجوع إلى DefaultAzureCredential عند عدم توفير مفتاح API في تكامل Azure
|
||||
- إضافة دعم Bedrock V4
|
||||
- إضافة أدوات Daytona sandbox لوظائف محسّنة
|
||||
- إضافة دعم نقطة التحقق والتفرع للوكلاء المستقلين
|
||||
|
||||
### إصلاحات الأخطاء
|
||||
- إصلاح execution_id ليكون منفصلًا عن state.id
|
||||
- حل مشكلة إعادة تشغيل أحداث الطريقة المسجلة عند استئناف نقطة التحقق
|
||||
- إصلاح تسلسل مراجع class initial_state كـ JSON schema
|
||||
- الحفاظ على مهارات الوكلاء التي تحتوي على بيانات وصفية فقط
|
||||
- تمرير أسماء @CrewBase الضمنية إلى أحداث الطاقم
|
||||
- دمج بيانات التنفيذ عند تهيئة دفعة مكررة
|
||||
- إصلاح تسلسل حقول مراجع class Task لنقاط التحقق
|
||||
- التعامل مع نتيجة BaseModel في حلقة إعادة المحاولة guardrail
|
||||
- الحفاظ على thought_signature في استدعاءات أدوات Gemini للبث
|
||||
- إصدار task_started عند استئناف التفرع وإعادة تصميم واجهة المستخدم النصية لنقطة التحقق
|
||||
- استخدام تواريخ مستقبلية في اختبارات تقليم نقطة التحقق لمنع الفشل المعتمد على الوقت
|
||||
- إصلاح ترتيب التشغيل الجاف والتعامل مع الفرع القديم الذي تم التحقق منه في إصدار أدوات التطوير
|
||||
- ترقية lxml إلى >=6.1.0 لرقعة الأمان
|
||||
- رفع python-dotenv إلى >=1.2.2 لرقعة الأمان
|
||||
|
||||
### الوثائق
|
||||
- تحديث سجل التغييرات والإصدار لـ v1.14.3
|
||||
- إضافة صفحة "بناء باستخدام الذكاء الاصطناعي" وتحديث التنقل لجميع اللغات
|
||||
- إزالة الأسئلة الشائعة حول التسعير من صفحة البناء باستخدام الذكاء الاصطناعي عبر جميع المواقع
|
||||
|
||||
### الأداء
|
||||
- تحسين MCP SDK وأنواع الأحداث لتقليل بدء التشغيل البارد بنسبة ~29%
|
||||
|
||||
### إعادة الهيكلة
|
||||
- إعادة هيكلة مساعدي نقطة التحقق للقضاء على التكرار وتشديد تلميحات نوع الحالة
|
||||
|
||||
## المساهمون
|
||||
|
||||
@MatthiasHowellYopp, @akaKuruma, @alex-clawd, @github-actions[bot], @github-advanced-security[bot], @greysonlalonde, @iris-clawd, @lorenzejay, @mattatcha, @renatonitta
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="23 أبريل 2026">
|
||||
## v1.14.3a3
|
||||
|
||||
|
||||
+1881
-4
File diff suppressed because it is too large.
Load diff
@@ -4,6 +4,54 @@ description: "Product updates, improvements, and bug fixes for CrewAI"
|
||||
icon: "clock"
|
||||
mode: "wide"
|
||||
---
|
||||
<Update label="Apr 25, 2026">
|
||||
## v1.14.3
|
||||
|
||||
[View release on GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.3)
|
||||
|
||||
## What's Changed
|
||||
|
||||
### Features
|
||||
- Add lifecycle events for checkpoint operations
|
||||
- Add support for e2b
|
||||
- Fall back to DefaultAzureCredential when no API key is provided in Azure integration
|
||||
- Add Bedrock V4 support
|
||||
- Add Daytona sandbox tools for enhanced functionality
|
||||
- Add checkpoint and fork support to standalone agents
|
||||
|
||||
### Bug Fixes
|
||||
- Fix execution_id to be separate from state.id
|
||||
- Resolve replay of recorded method events on checkpoint resume
|
||||
- Fix serialization of initial_state class references as JSON schema
|
||||
- Preserve metadata-only agent skills
|
||||
- Propagate implicit @CrewBase names to crew events
|
||||
- Merge execution metadata on duplicate batch initialization
|
||||
- Fix serialization of Task class-reference fields for checkpointing
|
||||
- Handle BaseModel result in guardrail retry loop
|
||||
- Preserve thought_signature in Gemini streaming tool calls
|
||||
- Emit task_started on fork resume and redesign checkpoint TUI
|
||||
- Use future dates in checkpoint prune tests to prevent time-dependent failures
|
||||
- Fix dry-run order and handle checked-out stale branch in devtools release
|
||||
- Upgrade lxml to >=6.1.0 for security patch
|
||||
- Bump python-dotenv to >=1.2.2 for security patch
|
||||
|
||||
### Documentation
|
||||
- Update changelog and version for v1.14.3
|
||||
- Add 'Build with AI' page and update navigation for all languages
|
||||
- Remove pricing FAQ from build-with-ai page across all locales
|
||||
|
||||
### Performance
|
||||
- Optimize MCP SDK and event types to reduce cold start by ~29%
|
||||
|
||||
### Refactoring
|
||||
- Refactor checkpoint helpers to eliminate duplication and tighten state type hints
|
||||
|
||||
## Contributors
|
||||
|
||||
@MatthiasHowellYopp, @akaKuruma, @alex-clawd, @github-actions[bot], @github-advanced-security[bot], @greysonlalonde, @iris-clawd, @lorenzejay, @mattatcha, @renatonitta
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="Apr 23, 2026">
|
||||
## v1.14.3a3
|
||||
|
||||
|
||||
@@ -4,6 +4,54 @@ description: "CrewAI의 제품 업데이트, 개선 사항 및 버그 수정"
|
||||
icon: "clock"
|
||||
mode: "wide"
|
||||
---
|
||||
<Update label="2026년 4월 25일">
|
||||
## v1.14.3
|
||||
|
||||
[GitHub 릴리스 보기](https://github.com/crewAIInc/crewAI/releases/tag/1.14.3)
|
||||
|
||||
## 변경 사항
|
||||
|
||||
### 기능
|
||||
- 체크포인트 작업을 위한 생명주기 이벤트 추가
|
||||
- e2b 지원 추가
|
||||
- Azure 통합에서 API 키가 제공되지 않을 경우 DefaultAzureCredential로 대체
|
||||
- Bedrock V4 지원 추가
|
||||
- 향상된 기능을 위한 Daytona 샌드박스 도구 추가
|
||||
- 독립형 에이전트에 체크포인트 및 포크 지원 추가
|
||||
|
||||
### 버그 수정
|
||||
- execution_id를 state.id와 분리되도록 수정
|
||||
- 체크포인트 재개 시 기록된 메서드 이벤트 재생 문제 해결
|
||||
- initial_state 클래스 참조의 JSON 스키마 직렬화 수정
|
||||
- 메타데이터 전용 에이전트 기술 보존
|
||||
- 암묵적인 @CrewBase 이름을 크루 이벤트로 전파
|
||||
- 중복 배치 초기화 시 실행 메타데이터 병합
|
||||
- 체크포인트를 위한 Task 클래스 참조 필드의 직렬화 수정
|
||||
- 가드레일 재시도 루프에서 BaseModel 결과 처리
|
||||
- Gemini 스트리밍 도구 호출에서 thought_signature 보존
|
||||
- 포크 재개 시 task_started 방출 및 체크포인트 TUI 재설계
|
||||
- 체크포인트 가지치기 테스트에서 미래 날짜 사용하여 시간 의존적 실패 방지
|
||||
- 드라이 런 주문 수정 및 devtools 릴리스에서 체크아웃된 오래된 브랜치 처리
|
||||
- 보안 패치를 위해 lxml을 >=6.1.0으로 업그레이드
|
||||
- 보안 패치를 위해 python-dotenv를 >=1.2.2로 업그레이드
|
||||
|
||||
### 문서
|
||||
- v1.14.3에 대한 변경 로그 및 버전 업데이트
|
||||
- 'AI로 빌드하기' 페이지 추가 및 모든 언어에 대한 내비게이션 업데이트
|
||||
- 모든 로케일에서 build-with-ai 페이지의 가격 FAQ 제거
|
||||
|
||||
### 성능
|
||||
- MCP SDK 및 이벤트 유형 최적화하여 콜드 스타트를 약 29% 감소
|
||||
|
||||
### 리팩토링
|
||||
- 중복 제거 및 상태 유형 힌트를 강화하기 위해 체크포인트 헬퍼 리팩토링
|
||||
|
||||
## 기여자
|
||||
|
||||
@MatthiasHowellYopp, @akaKuruma, @alex-clawd, @github-actions[bot], @github-advanced-security[bot], @greysonlalonde, @iris-clawd, @lorenzejay, @mattatcha, @renatonitta
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026년 4월 23일">
|
||||
## v1.14.3a3
|
||||
|
||||
|
||||
@@ -4,6 +4,54 @@ description: "Atualizações de produto, melhorias e correções do CrewAI"
|
||||
icon: "clock"
|
||||
mode: "wide"
|
||||
---
|
||||
<Update label="25 abr 2026">
|
||||
## v1.14.3
|
||||
|
||||
[Ver release no GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.3)
|
||||
|
||||
## O que Mudou
|
||||
|
||||
### Recursos
|
||||
- Adicionar eventos de ciclo de vida para operações de checkpoint
|
||||
- Adicionar suporte para e2b
|
||||
- Reverter para DefaultAzureCredential quando nenhuma chave de API for fornecida na integração com o Azure
|
||||
- Adicionar suporte ao Bedrock V4
|
||||
- Adicionar ferramentas de sandbox Daytona para funcionalidade aprimorada
|
||||
- Adicionar suporte a checkpoint e fork para agentes autônomos
|
||||
|
||||
### Correções de Bugs
|
||||
- Corrigir execution_id para ser separado de state.id
|
||||
- Resolver a reprodução de eventos de método gravados na retomada do checkpoint
|
||||
- Corrigir a serialização de referências de classe initial_state como esquema JSON
|
||||
- Preservar habilidades de agente somente de metadados
|
||||
- Propagar nomes implícitos @CrewBase para eventos da equipe
|
||||
- Mesclar metadados de execução na inicialização de lote duplicado
|
||||
- Corrigir a serialização de campos de referência de classe Task para checkpointing
|
||||
- Lidar com o resultado BaseModel no loop de retry do guardrail
|
||||
- Preservar thought_signature em chamadas de ferramentas de streaming Gemini
|
||||
- Emitir task_started na retomada do fork e redesenhar TUI de checkpoint
|
||||
- Usar datas futuras em testes de poda de checkpoint para evitar falhas dependentes do tempo
|
||||
- Corrigir a ordem de dry-run e lidar com branch obsoleta verificada na liberação do devtools
|
||||
- Atualizar lxml para >=6.1.0 para patch de segurança
|
||||
- Aumentar python-dotenv para >=1.2.2 para patch de segurança
|
||||
|
||||
### Documentação
|
||||
- Atualizar changelog e versão para v1.14.3
|
||||
- Adicionar página 'Construir com IA' e atualizar navegação para todos os idiomas
|
||||
- Remover FAQ de preços da página construir-com-ia em todos os locais
|
||||
|
||||
### Desempenho
|
||||
- Otimizar MCP SDK e tipos de eventos para reduzir o tempo de inicialização a frio em ~29%
|
||||
|
||||
### Refatoração
|
||||
- Refatorar auxiliares de checkpoint para eliminar duplicação e apertar dicas de tipo de estado
|
||||
|
||||
## Contribuidores
|
||||
|
||||
@MatthiasHowellYopp, @akaKuruma, @alex-clawd, @github-actions[bot], @github-advanced-security[bot], @greysonlalonde, @iris-clawd, @lorenzejay, @mattatcha, @renatonitta
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="23 abr 2026">
|
||||
## v1.14.3a3
|
||||
|
||||
|
||||
@@ -152,4 +152,4 @@ __all__ = [
|
||||
"wrap_file_source",
|
||||
]
|
||||
|
||||
__version__ = "1.14.3a3"
|
||||
__version__ = "1.14.3"
|
||||
@@ -10,7 +10,7 @@ requires-python = ">=3.10, <3.14"
|
||||
dependencies = [
|
||||
"pytube~=15.0.0",
|
||||
"requests>=2.33.0,<3",
|
||||
"crewai==1.14.3a3",
|
||||
"crewai==1.14.3",
|
||||
"tiktoken~=0.8.0",
|
||||
"beautifulsoup4~=4.13.4",
|
||||
"python-docx~=1.2.0",
|
||||
|
||||
@@ -321,4 +321,4 @@ __all__ = [
|
||||
"ZapierActionTools",
|
||||
]
|
||||
|
||||
__version__ = "1.14.3a3"
|
||||
__version__ = "1.14.3"
|
||||
@@ -55,7 +55,7 @@ Repository = "https://github.com/crewAIInc/crewAI"
|
||||
|
||||
[project.optional-dependencies]
|
||||
tools = [
|
||||
"crewai-tools==1.14.3a3",
|
||||
"crewai-tools==1.14.3",
|
||||
]
|
||||
embeddings = [
|
||||
"tiktoken~=0.8.0"
|
||||
|
||||
@@ -48,7 +48,7 @@ def _suppress_pydantic_deprecation_warnings() -> None:
|
||||
|
||||
_suppress_pydantic_deprecation_warnings()
|
||||
|
||||
__version__ = "1.14.3a3"
|
||||
__version__ = "1.14.3"
|
||||
|
||||
_LAZY_IMPORTS: dict[str, tuple[str, str]] = {
|
||||
"Memory": ("crewai.memory.unified_memory", "Memory"),
|
||||
@@ -94,10 +94,16 @@ try:
|
||||
}
|
||||
|
||||
from crewai.tools.base_tool import BaseTool as _BaseTool
|
||||
from crewai.tools.flow_tool import (
|
||||
FlowTool as _FlowTool,
|
||||
create_flow_tools as _create_flow_tools,
|
||||
)
|
||||
from crewai.tools.structured_tool import CrewStructuredTool as _CrewStructuredTool
|
||||
|
||||
_base_namespace["BaseTool"] = _BaseTool
|
||||
_base_namespace["CrewStructuredTool"] = _CrewStructuredTool
|
||||
_base_namespace["FlowTool"] = _FlowTool
|
||||
_base_namespace["create_flow_tools"] = _create_flow_tools # type: ignore[assignment]
|
||||
|
||||
try:
|
||||
from crewai.a2a.config import (
|
||||
|
||||
@@ -85,6 +85,7 @@ from crewai.skills.loader import activate_skill, discover_skills
|
||||
from crewai.skills.models import INSTRUCTIONS, Skill as SkillModel
|
||||
from crewai.state.checkpoint_config import CheckpointConfig, apply_checkpoint
|
||||
from crewai.tools.agent_tools.agent_tools import AgentTools
|
||||
from crewai.tools.flow_tool import create_flow_tools
|
||||
from crewai.types.callback import SerializableCallable
|
||||
from crewai.utilities.agent_utils import (
|
||||
get_tool_names,
|
||||
@@ -305,6 +306,10 @@ class Agent(BaseAgent):
|
||||
Can be a single A2AConfig/A2AClientConfig/A2AServerConfig, or a list of any number of A2AConfig/A2AClientConfig with a single A2AServerConfig.
|
||||
""",
|
||||
)
|
||||
flows: list[Any] | None = Field(
|
||||
default=None,
|
||||
description="Flow classes that the agent can invoke as tools. Each entry is a Flow subclass (not an instance).",
|
||||
)
|
||||
agent_executor: CrewAgentExecutor | AgentExecutor | None = Field(
|
||||
default=None, description="An instance of the CrewAgentExecutor class."
|
||||
)
|
||||
@@ -347,6 +352,7 @@ class Agent(BaseAgent):
|
||||
)
|
||||
|
||||
self.set_skills()
|
||||
self._set_flow_tools()
|
||||
|
||||
if self.reasoning and self.planning_config is None:
|
||||
warnings.warn(
|
||||
@@ -459,6 +465,16 @@ class Agent(BaseAgent):
|
||||
|
||||
self.skills = resolved if resolved else None
|
||||
|
||||
def _set_flow_tools(self) -> None:
|
||||
"""Convert Flow classes in ``self.flows`` to tools and merge them."""
|
||||
if not self.flows:
|
||||
return
|
||||
flow_tools = create_flow_tools(self.flows)
|
||||
if flow_tools:
|
||||
if self.tools is None:
|
||||
self.tools = []
|
||||
self.tools.extend(flow_tools)
|
||||
|
||||
def _is_any_available_memory(self) -> bool:
|
||||
"""Check if unified memory is available (agent or crew)."""
|
||||
if getattr(self, "memory", None):
|
||||
|
||||
@@ -5,7 +5,7 @@ description = "{{name}} using crewAI"
|
||||
authors = [{ name = "Your Name", email = "you@example.com" }]
|
||||
requires-python = ">=3.10,<3.14"
|
||||
dependencies = [
|
||||
"crewai[tools]==1.14.3a3"
|
||||
"crewai[tools]==1.14.3"
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
|
||||
@@ -5,7 +5,7 @@ description = "{{name}} using crewAI"
|
||||
authors = [{ name = "Your Name", email = "you@example.com" }]
|
||||
requires-python = ">=3.10,<3.14"
|
||||
dependencies = [
|
||||
"crewai[tools]==1.14.3a3"
|
||||
"crewai[tools]==1.14.3"
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
|
||||
@@ -5,7 +5,7 @@ description = "Power up your crews with {{folder_name}}"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10,<3.14"
|
||||
dependencies = [
|
||||
"crewai[tools]==1.14.3a3"
|
||||
"crewai[tools]==1.14.3"
|
||||
]
|
||||
|
||||
[tool.crewai]
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
"""Wrap Flow classes as callable tools so agents can invoke them."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from typing import Any
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from crewai.tools.base_tool import BaseTool
|
||||
from crewai.utilities.string_utils import sanitize_tool_name
|
||||
|
||||
|
||||
class FlowToolInputSchema(BaseModel):
|
||||
"""Default input schema for a FlowTool."""
|
||||
|
||||
inputs: str = Field(
|
||||
default="{}",
|
||||
description=(
|
||||
"JSON string of key-value pairs to pass as inputs to the flow. "
|
||||
"Use '{}' if the flow requires no inputs."
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class FlowTool(BaseTool):
|
||||
"""Wraps a Flow class as a BaseTool so an agent can invoke it.
|
||||
|
||||
The tool instantiates the Flow, calls ``kickoff(inputs=...)`` and returns
|
||||
the result as a string.
|
||||
"""
|
||||
|
||||
name: str = ""
|
||||
description: str = ""
|
||||
flow_class: Any = Field(
|
||||
default=None,
|
||||
description="The Flow class (not instance) to wrap.",
|
||||
exclude=True,
|
||||
)
|
||||
args_schema: Any = FlowToolInputSchema
|
||||
|
||||
def _run(self, inputs: str = "{}") -> str:
|
||||
"""Instantiate the Flow, run kickoff, and return the result."""
|
||||
try:
|
||||
parsed_inputs = json.loads(inputs) if isinstance(inputs, str) else inputs
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
parsed_inputs = {}
|
||||
|
||||
if not isinstance(parsed_inputs, dict):
|
||||
parsed_inputs = {}
|
||||
|
||||
flow_instance = self.flow_class()
|
||||
result = flow_instance.kickoff(inputs=parsed_inputs if parsed_inputs else None)
|
||||
return str(result)
|
||||
|
||||
|
||||
def create_flow_tools(flows: list[type] | None) -> list[BaseTool]:
|
||||
"""Convert a list of Flow classes into BaseTool wrappers.
|
||||
|
||||
Args:
|
||||
flows: Flow classes (not instances) to wrap as tools.
|
||||
|
||||
Returns:
|
||||
A list of FlowTool instances ready for agent use.
|
||||
"""
|
||||
if not flows:
|
||||
return []
|
||||
|
||||
tools: list[BaseTool] = []
|
||||
for flow_cls in flows:
|
||||
name = sanitize_tool_name(flow_cls.__name__)
|
||||
docstring = (flow_cls.__doc__ or "").strip()
|
||||
description = docstring if docstring else f"Run the {flow_cls.__name__} flow."
|
||||
|
||||
tools.append(
|
||||
FlowTool(
|
||||
name=name,
|
||||
description=description,
|
||||
flow_class=flow_cls,
|
||||
)
|
||||
)
|
||||
return tools
|
||||
@@ -0,0 +1,185 @@
|
||||
"""Tests for Flow-as-tool functionality."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from crewai.flow.flow import Flow, start
|
||||
from crewai.tools.flow_tool import FlowTool, create_flow_tools
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Test Flow classes
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class SimpleFlow(Flow):
|
||||
"""A simple flow that greets the user."""
|
||||
|
||||
@start()
|
||||
def greet(self) -> str:
|
||||
return "Hello from SimpleFlow!"
|
||||
|
||||
|
||||
class MathFlow(Flow):
|
||||
"""Performs basic math operations."""
|
||||
|
||||
@start()
|
||||
def compute(self) -> str:
|
||||
return "42"
|
||||
|
||||
|
||||
class NoDocFlow(Flow):
|
||||
@start()
|
||||
def run_it(self) -> str:
|
||||
return "no doc"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# FlowTool unit tests
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class TestFlowTool:
|
||||
def test_wrap_simple_flow(self) -> None:
|
||||
tool = FlowTool(
|
||||
name="simple_flow",
|
||||
description="A simple flow that greets the user.",
|
||||
flow_class=SimpleFlow,
|
||||
)
|
||||
assert tool.name == "simple_flow"
|
||||
assert "greets the user" in tool.description
|
||||
|
||||
def test_run_invokes_kickoff(self) -> None:
|
||||
mock_flow = MagicMock()
|
||||
mock_flow.return_value = mock_flow # __init__ returns self
|
||||
mock_flow.kickoff.return_value = "mocked result"
|
||||
|
||||
tool = FlowTool(
|
||||
name="test_flow",
|
||||
description="test",
|
||||
flow_class=mock_flow,
|
||||
)
|
||||
result = tool._run(inputs="{}")
|
||||
assert result == "mocked result"
|
||||
mock_flow.kickoff.assert_called_once()
|
||||
|
||||
def test_run_with_json_inputs(self) -> None:
|
||||
mock_flow = MagicMock()
|
||||
mock_flow.return_value = mock_flow
|
||||
mock_flow.kickoff.return_value = "result with inputs"
|
||||
|
||||
tool = FlowTool(
|
||||
name="test_flow",
|
||||
description="test",
|
||||
flow_class=mock_flow,
|
||||
)
|
||||
result = tool._run(inputs='{"key": "value"}')
|
||||
assert result == "result with inputs"
|
||||
mock_flow.kickoff.assert_called_once_with(inputs={"key": "value"})
|
||||
|
||||
def test_run_with_invalid_json_defaults_to_empty(self) -> None:
|
||||
mock_flow = MagicMock()
|
||||
mock_flow.return_value = mock_flow
|
||||
mock_flow.kickoff.return_value = "ok"
|
||||
|
||||
tool = FlowTool(
|
||||
name="test_flow",
|
||||
description="test",
|
||||
flow_class=mock_flow,
|
||||
)
|
||||
result = tool._run(inputs="not valid json")
|
||||
assert result == "ok"
|
||||
mock_flow.kickoff.assert_called_once_with(inputs=None)
|
||||
|
||||
def test_run_returns_string(self) -> None:
|
||||
mock_flow = MagicMock()
|
||||
mock_flow.return_value = mock_flow
|
||||
mock_flow.kickoff.return_value = 42
|
||||
|
||||
tool = FlowTool(
|
||||
name="test_flow",
|
||||
description="test",
|
||||
flow_class=mock_flow,
|
||||
)
|
||||
result = tool._run()
|
||||
assert result == "42"
|
||||
assert isinstance(result, str)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# create_flow_tools tests
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class TestCreateFlowTools:
|
||||
def test_creates_tools_from_flow_classes(self) -> None:
|
||||
tools = create_flow_tools([SimpleFlow, MathFlow])
|
||||
assert len(tools) == 2
|
||||
names = {t.name for t in tools}
|
||||
assert "simple_flow" in names
|
||||
assert "math_flow" in names
|
||||
|
||||
def test_description_from_docstring(self) -> None:
|
||||
tools = create_flow_tools([SimpleFlow])
|
||||
assert len(tools) == 1
|
||||
assert "greets the user" in tools[0].description
|
||||
|
||||
def test_description_fallback_when_no_docstring(self) -> None:
|
||||
tools = create_flow_tools([NoDocFlow])
|
||||
assert len(tools) == 1
|
||||
assert "NoDocFlow" in tools[0].description
|
||||
|
||||
def test_empty_list_returns_empty(self) -> None:
|
||||
assert create_flow_tools([]) == []
|
||||
|
||||
def test_none_returns_empty(self) -> None:
|
||||
assert create_flow_tools(None) == []
|
||||
|
||||
def test_tools_are_base_tool_instances(self) -> None:
|
||||
from crewai.tools.base_tool import BaseTool
|
||||
|
||||
tools = create_flow_tools([SimpleFlow])
|
||||
for tool in tools:
|
||||
assert isinstance(tool, BaseTool)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Agent integration tests
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class TestAgentFlowIntegration:
|
||||
def test_agent_with_flows_has_flow_tools(self) -> None:
|
||||
from crewai.agent.core import Agent
|
||||
|
||||
agent = Agent(
|
||||
role="Test Agent",
|
||||
goal="Test flows",
|
||||
backstory="I test things",
|
||||
flows=[SimpleFlow, MathFlow],
|
||||
)
|
||||
tool_names = {t.name for t in (agent.tools or [])}
|
||||
assert "simple_flow" in tool_names
|
||||
assert "math_flow" in tool_names
|
||||
|
||||
def test_agent_without_flows_no_extra_tools(self) -> None:
|
||||
from crewai.agent.core import Agent
|
||||
|
||||
agent = Agent(
|
||||
role="Test Agent",
|
||||
goal="Test",
|
||||
backstory="I test things",
|
||||
)
|
||||
# Should not have any flow tools
|
||||
flow_tool_names = {
|
||||
t.name for t in (agent.tools or []) if isinstance(t, FlowTool)
|
||||
}
|
||||
assert len(flow_tool_names) == 0
|
||||
|
||||
def test_flow_tool_executes_real_flow(self) -> None:
|
||||
"""Test that a FlowTool actually runs the Flow's kickoff."""
|
||||
tools = create_flow_tools([SimpleFlow])
|
||||
tool = tools[0]
|
||||
result = tool.run(inputs="{}")
|
||||
assert "Hello from SimpleFlow" in result
|
||||
@@ -1,3 +1,3 @@
|
||||
"""CrewAI development tools."""
|
||||
|
||||
__version__ = "1.14.3a3"
|
||||
__version__ = "1.14.3"
|
||||
Reference in new issue
Block a user