Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions .github/workflows/import-time.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
name: Import Time Guard

on:
pull_request:
paths:
- "lib/crewai/src/**"
- "lib/crewai/pyproject.toml"
- "pyproject.toml"

permissions:
contents: read

jobs:
import-time:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.12"]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- uses: astral-sh/setup-uv@v6
with:
version: "0.11.3"
enable-cache: true

- name: Install the project
run: uv sync --all-extras --no-dev
env:
UV_PYTHON: ${{ matrix.python-version }}

- name: Benchmark PR branch
id: pr
run: |
result=$(uv run python scripts/benchmark_import_time.py --runs 5 --json)
echo "result=$result" >> "$GITHUB_OUTPUT"
echo "pr_median=$(echo $result | python3 -c 'import sys,json; print(json.load(sys.stdin)["median_s"])')" >> "$GITHUB_OUTPUT"
echo "### PR Branch Import Time" >> "$GITHUB_STEP_SUMMARY"
echo "$result" | python3 -c "
import sys, json
d = json.load(sys.stdin)
print(f'- Median: {d[\"median_s\"]}s')
print(f'- Mean: {d[\"mean_s\"]}s ± {d[\"stdev_s\"]}s')
print(f'- Range: {d[\"min_s\"]}s – {d[\"max_s\"]}s')
" >> "$GITHUB_STEP_SUMMARY"
env:
UV_PYTHON: ${{ matrix.python-version }}

- name: Checkout base branch
run: git checkout ${{ github.event.pull_request.base.sha }}

- name: Install base branch
run: uv sync --all-extras --no-dev
env:
UV_PYTHON: ${{ matrix.python-version }}

- name: Benchmark base branch
id: base
run: |
result=$(uv run python scripts/benchmark_import_time.py --runs 5 --json 2>/dev/null || echo '{"median_s": 0}')
echo "result=$result" >> "$GITHUB_OUTPUT"
echo "base_median=$(echo $result | python3 -c 'import sys,json; print(json.load(sys.stdin)["median_s"])')" >> "$GITHUB_OUTPUT"
echo "### Base Branch Import Time" >> "$GITHUB_STEP_SUMMARY"
echo "$result" | python3 -c "
import sys, json
d = json.load(sys.stdin)
if d.get('median_s', 0) > 0:
print(f'- Median: {d[\"median_s\"]}s')
else:
print('- Benchmark script not present on base branch (skip comparison)')
" >> "$GITHUB_STEP_SUMMARY"
env:
UV_PYTHON: ${{ matrix.python-version }}

- name: Compare and gate
run: |
pr_median=${{ steps.pr.outputs.pr_median }}
base_median=${{ steps.base.outputs.base_median }}

python3 -c "
pr = float('$pr_median')
base = float('$base_median')

if base <= 0:
print('⏭️ No base benchmark available — skipping comparison.')
exit(0)

change_pct = ((pr - base) / base) * 100
print(f'Base: {base:.3f}s')
print(f'PR: {pr:.3f}s')
print(f'Change: {change_pct:+.1f}%')
print()

if change_pct > 5:
print(f'❌ BLOCKED: Import time regressed by {change_pct:.1f}% (threshold: 5%)')
exit(1)
elif change_pct > 0:
print(f'⚠️ Slight regression ({change_pct:.1f}%) but within 5% threshold.')
else:
print(f'✅ Import time improved by {abs(change_pct):.1f}%')
"
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ chromadb-*.lock
.crewai/memory
blogs/*
secrets/*
UNKNOWN.egg-info/
3 changes: 0 additions & 3 deletions docs/ar/guides/coding-tools/build-with-ai.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,6 @@ CrewAI AMP مُصمَّم لفرق الإنتاج. إليك ما تحصل علي
- **Factory (استضافة ذاتية)** — على بنيتك التحتية لسيطرة كاملة على البيانات
- **هجين** — دمج السحابة والاستضافة الذاتية حسب حساسية البيانات
</Accordion>
<Accordion title="كيف يعمل التسعير؟">
سجّل في [app.crewai.com](https://app.crewai.com) لمعرفة الخطط الحالية. تسعير المؤسسات وFactory متاح عند الطلب.
</Accordion>
</AccordionGroup>

<Card title="استكشف CrewAI AMP →" icon="arrow-right" href="https://app.crewai.com">
Expand Down
3 changes: 0 additions & 3 deletions docs/en/guides/coding-tools/build-with-ai.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,6 @@ CrewAI AMP is built for production teams. Here's what you get beyond deployment.
- **Factory (self-hosted)** — run on your own infrastructure for full data control
- **Hybrid** — mix cloud and self-hosted based on sensitivity requirements
</Accordion>
<Accordion title="How does pricing work?">
Sign up at [app.crewai.com](https://app.crewai.com) to see current plans. Enterprise and Factory pricing is available on request.
</Accordion>
</AccordionGroup>

<Card title="Explore CrewAI AMP →" icon="arrow-right" href="https://app.crewai.com">
Expand Down
3 changes: 0 additions & 3 deletions docs/ko/guides/coding-tools/build-with-ai.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,6 @@ CrewAI AMP는 프로덕션 팀을 위해 만들어졌습니다. 배포 외에
- **Factory(셀프 호스팅)** — 데이터 통제를 위해 자체 인프라에서 실행
- **하이브리드** — 민감도에 따라 클라우드와 셀프 호스팅을 혼합
</Accordion>
<Accordion title="가격은 어떻게 되나요?">
[app.crewai.com](https://app.crewai.com)에 가입하면 현재 요금제를 확인할 수 있습니다. 엔터프라이즈 및 Factory 가격은 문의 시 안내합니다.
</Accordion>
</AccordionGroup>

<Card title="CrewAI AMP 살펴보기 →" icon="arrow-right" href="https://app.crewai.com">
Expand Down
3 changes: 0 additions & 3 deletions docs/pt-BR/guides/coding-tools/build-with-ai.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,6 @@ O CrewAI AMP foi feito para equipes em produção. Além da implantação, você
- **Factory (self-hosted)** — na sua infraestrutura para controle total dos dados
- **Híbrido** — combine nuvem e self-hosted conforme a sensibilidade dos dados
</Accordion>
<Accordion title="Como funciona o preço?">
Cadastre-se em [app.crewai.com](https://app.crewai.com) para ver os planos atuais. Preços enterprise e Factory sob consulta.
</Accordion>
</AccordionGroup>

<Card title="Conheça o CrewAI AMP →" icon="arrow-right" href="https://app.crewai.com">
Expand Down
2 changes: 1 addition & 1 deletion lib/crewai-tools/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ github = [
]
rag = [
"python-docx>=1.1.0",
"lxml>=5.3.0,<5.4.0", # Pin to avoid etree import issues in 5.4.0
"lxml>=6.1.0,<7", # 6.1.0+ required for GHSA-vfmq-68hx-4jfw (XXE in iterparse)
]
xml = [
"unstructured[local-inference, all-docs]>=0.17.2"
Expand Down
6 changes: 4 additions & 2 deletions lib/crewai/src/crewai/agent/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,7 @@
from crewai.knowledge.source.base_knowledge_source import BaseKnowledgeSource
from crewai.lite_agent_output import LiteAgentOutput
from crewai.llms.base_llm import BaseLLM
from crewai.mcp import MCPServerConfig
from crewai.mcp.tool_resolver import MCPToolResolver
from crewai.mcp.config import MCPServerConfig
from crewai.rag.embeddings.types import EmbedderConfig
from crewai.security.fingerprint import Fingerprint
from crewai.skills.loader import activate_skill, discover_skills
Expand Down Expand Up @@ -119,6 +118,7 @@

from crewai.a2a.config import A2AClientConfig, A2AConfig, A2AServerConfig
from crewai.agents.agent_builder.base_agent import PlatformAppOrAction
from crewai.mcp.tool_resolver import MCPToolResolver
from crewai.task import Task
from crewai.tools.base_tool import BaseTool
from crewai.tools.structured_tool import CrewStructuredTool
Expand Down Expand Up @@ -1120,6 +1120,8 @@ def get_mcp_tools(self, mcps: list[str | MCPServerConfig]) -> list[BaseTool]:
Delegates to :class:`~crewai.mcp.tool_resolver.MCPToolResolver`.
"""
self._cleanup_mcp_clients()
from crewai.mcp.tool_resolver import MCPToolResolver

self._mcp_resolver = MCPToolResolver(agent=self, logger=self._logger)
return self._mcp_resolver.resolve(mcps)

Expand Down
Loading
Loading