docs: update changelog and version for v1.14.2a4

This commit is contained in:
Alex (CrewAI)
2026-04-15 06:17:15 -07:00
committed by Joao Moura
parent 160e25c1a9
commit 31f480aac0
7 changed files with 334 additions and 530 deletions

View File

@@ -4,137 +4,6 @@ description: "تحديثات المنتج والتحسينات وإصلاحات
icon: "clock"
mode: "wide"
---
<Update label="22 أبريل 2026">
## v1.14.3a2
[عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.3a2)
## ما الذي تغير
### الميزات
- إضافة دعم لـ bedrock V4
- إضافة أدوات Daytona sandbox لوظائف محسّنة
- إضافة صفحة "البناء باستخدام الذكاء الاصطناعي" — مستندات أصلية للذكاء الاصطناعي لوكلاء البرمجة
- إضافة "البناء باستخدام الذكاء الاصطناعي" إلى التنقل في صفحة "البدء" وملفات الصفحات لجميع اللغات (en, ko, pt-BR, ar)
### إصلاحات الأخطاء
- إصلاح انتشار أسماء @CrewBase الضمنية إلى أحداث الطاقم
- حل مشكلة تكرار تهيئة الدفعات في دمج بيانات التنفيذ الوصفية
- إصلاح تسلسل حقول مرجع فئة Task لعمليات التحقق من النقاط
- التعامل مع نتيجة BaseModel في حلقة إعادة المحاولة للحدود
- تحديث python-dotenv إلى الإصدار >=1.2.2 للامتثال الأمني
### الوثائق
- تحديث سجل التغييرات والإصدار لـ v1.14.3a1
- تحديث الأوصاف وتطبيق الترجمات الفعلية
## المساهمون
@MatthiasHowellYopp, @github-actions[bot], @greysonlalonde, @iris-clawd, @lorenzejay, @renatonitta
</Update>
<Update label="21 أبريل 2026">
## v1.14.3a1
[عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.3a1)
## ما الذي تغير
### الميزات
- إضافة دعم نقاط التحقق والفروع لوكلاء مستقلين
### إصلاحات الأخطاء
- الحفاظ على thought_signature في استدعاءات أداة البث Gemini
- إصدار task_started عند استئناف الفرع وإعادة تصميم واجهة المستخدم النصية لنقاط التحقق
- تصحيح ترتيب التشغيل الجاف ومعالجة الفرع القديم الذي تم التحقق منه في إصدار أدوات التطوير
- استخدام تواريخ مستقبلية في اختبارات تقليم نقاط التحقق لمنع الفشل المعتمد على الوقت (#5543)
### الوثائق
- تحديث سجل التغييرات والإصدار لـ v1.14.2
## المساهمون
@alex-clawd, @greysonlalonde
</Update>
<Update label="17 أبريل 2026">
## v1.14.2
[عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.2)
## ما الذي تغير
### الميزات
- إضافة أوامر استئناف النقاط التفتيش، والاختلاف، والتنظيف مع تحسين إمكانية الاكتشاف.
- إضافة معلمة `from_checkpoint` إلى `Agent.kickoff` والطرق ذات الصلة.
- إضافة أوامر إدارة القوالب لقوالب المشاريع.
- إضافة تلميحات استئناف إلى إصدار أدوات المطور عند الفشل.
- إضافة واجهة سطر الأوامر للتحقق من النشر وتعزيز سهولة استخدام تهيئة LLM.
- إضافة تقسيم النقاط التفتيشية مع تتبع النسب.
- إثراء تتبع رموز LLM مع رموز الاستدلال ورموز إنشاء التخزين المؤقت.
### إصلاحات الأخطاء
- إصلاح المطالبة بشأن تعارضات الفروع القديمة في إصدار أدوات المطور.
- تصحيح الثغرات في `authlib` و `langchain-text-splitters` و `pypdf`.
- تحديد نطاق معالجات البث لمنع تلوث أجزاء التشغيل المتقاطعة.
- إرسال نقاط التفتيش عبر واجهات Flow في TUI.
- استخدام نمط البحث المتكرر لاكتشاف نقاط التفتيش بتنسيق JSON.
- التعامل مع مخططات JSON الدائرية في أداة حل MCP.
- الحفاظ على معلمات استدعاء أداة Bedrock من خلال إزالة القيمة الافتراضية الصحيحة.
- إصدار حدث flow_finished بعد استئناف HITL.
- إصلاح ثغرات متنوعة من خلال تحديث التبعيات، بما في ذلك `requests` و `cryptography` و `pytest`.
- إصلاح لإيقاف تمرير وضع صارم إلى واجهة برمجة التطبيقات Bedrock Converse.
### الوثائق
- توثيق المعلمات المفقودة وإضافة قسم النقاط التفتيشية.
- تحديث سجل التغييرات والإصدار للإصدار v1.14.2 ومرشحي الإصدار السابقين.
- إضافة توثيق ميزة A2A الخاصة بالشركات وتحديث وثائق A2A المفتوحة المصدر.
## المساهمون
@Yanhu007، @alex-clawd، @github-actions[bot]، @greysonlalonde، @iris-clawd، @lorenzejay، @lucasgomide
</Update>
<Update label="16 أبريل 2026">
## v1.14.2rc1
[عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.2rc1)
## ما الذي تغير
### إصلاحات الأخطاء
- إصلاح معالجة مخططات JSON الدائرية في أداة MCP
- إصلاح ثغرة أمنية من خلال تحديث python-multipart إلى 0.0.26
- إصلاح ثغرة أمنية من خلال تحديث pypdf إلى 6.10.1
### الوثائق
- تحديث سجل التغييرات والإصدار لـ v1.14.2a5
## المساهمون
@greysonlalonde
</Update>
<Update label="15 أبريل 2026">
## v1.14.2a5
[عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.2a5)
## ما الذي تغير
### الوثائق
- تحديث سجل التغييرات والإصدار لـ v1.14.2a4
## المساهمون
@greysonlalonde
</Update>
<Update label="15 أبريل 2026">
## v1.14.2a4

View File

@@ -4,137 +4,6 @@ description: "Product updates, improvements, and bug fixes for CrewAI"
icon: "clock"
mode: "wide"
---
<Update label="Apr 22, 2026">
## v1.14.3a2
[View release on GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.3a2)
## What's Changed
### Features
- Add support for bedrock V4
- Add Daytona sandbox tools for enhanced functionality
- Add 'Build with AI' page — AI-native docs for coding agents
- Add Build with AI to Get Started navigation and page files for all languages (en, ko, pt-BR, ar)
### Bug Fixes
- Fix propagation of implicit @CrewBase names to crew events
- Resolve issue with duplicate batch initialization in execution metadata merge
- Fix serialization of Task class-reference fields for checkpointing
- Handle BaseModel result in guardrail retry loop
- Bump python-dotenv to version >=1.2.2 for security compliance
### Documentation
- Update changelog and version for v1.14.3a1
- Update descriptions and apply actual translations
## Contributors
@MatthiasHowellYopp, @github-actions[bot], @greysonlalonde, @iris-clawd, @lorenzejay, @renatonitta
</Update>
<Update label="Apr 21, 2026">
## v1.14.3a1
[View release on GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.3a1)
## What's Changed
### Features
- Add checkpoint and fork support to standalone agents
### Bug Fixes
- Preserve thought_signature in Gemini streaming tool calls
- Emit task_started on fork resume and redesign checkpoint TUI
- Correct dry-run order and handle checked-out stale branch in devtools release
- Use future dates in checkpoint prune tests to prevent time-dependent failures (#5543)
### Documentation
- Update changelog and version for v1.14.2
## Contributors
@alex-clawd, @greysonlalonde
</Update>
<Update label="Apr 17, 2026">
## v1.14.2
[View release on GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.2)
## What's Changed
### Features
- Add checkpoint resume, diff, and prune commands with improved discoverability.
- Add `from_checkpoint` parameter to `Agent.kickoff` and related methods.
- Add template management commands for project templates.
- Add resume hints to devtools release on failure.
- Add deploy validation CLI and enhance LLM initialization ergonomics.
- Add checkpoint forking with lineage tracking.
- Enrich LLM token tracking with reasoning tokens and cache creation tokens.
### Bug Fixes
- Fix prompt on stale branch conflicts in devtools release.
- Patch vulnerabilities in `authlib`, `langchain-text-splitters`, and `pypdf`.
- Scope streaming handlers to prevent cross-run chunk contamination.
- Dispatch Flow checkpoints through Flow APIs in TUI.
- Use recursive glob for JSON checkpoint discovery.
- Handle cyclic JSON schemas in MCP tool resolution.
- Preserve Bedrock tool call arguments by removing truthy default.
- Emit flow_finished event after HITL resume.
- Fix various vulnerabilities by updating dependencies, including `requests`, `cryptography`, and `pytest`.
- Fix to stop forwarding strict mode to Bedrock Converse API.
### Documentation
- Document missing parameters and add Checkpointing section.
- Update changelog and version for v1.14.2 and previous release candidates.
- Add enterprise A2A feature documentation and update OSS A2A docs.
## Contributors
@Yanhu007, @alex-clawd, @github-actions[bot], @greysonlalonde, @iris-clawd, @lorenzejay, @lucasgomide
</Update>
<Update label="Apr 16, 2026">
## v1.14.2rc1
[View release on GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.2rc1)
## What's Changed
### Bug Fixes
- Fix handling of cyclic JSON schemas in MCP tool resolution
- Fix vulnerability by bumping python-multipart to 0.0.26
- Fix vulnerability by bumping pypdf to 6.10.1
### Documentation
- Update changelog and version for v1.14.2a5
## Contributors
@greysonlalonde
</Update>
<Update label="Apr 15, 2026">
## v1.14.2a5
[View release on GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.2a5)
## What's Changed
### Documentation
- Update changelog and version for v1.14.2a4
## Contributors
@greysonlalonde
</Update>
<Update label="Apr 15, 2026">
## v1.14.2a4

View File

@@ -4,137 +4,6 @@ description: "CrewAI의 제품 업데이트, 개선 사항 및 버그 수정"
icon: "clock"
mode: "wide"
---
<Update label="2026년 4월 22일">
## v1.14.3a2
[GitHub 릴리스 보기](https://github.com/crewAIInc/crewAI/releases/tag/1.14.3a2)
## 변경 사항
### 기능
- 베드록 V4 지원 추가
- 향상된 기능을 위한 데이토나 샌드박스 도구 추가
- 'AI와 함께 빌드' 페이지 추가 — 코딩 에이전트를 위한 AI 네이티브 문서
- 모든 언어(en, ko, pt-BR, ar)에 대한 시작하기 탐색 및 페이지 파일에 AI와 함께 빌드 추가
### 버그 수정
- 크루 이벤트에 대한 암묵적 @CrewBase 이름 전파 수정
- 실행 메타데이터 병합에서 중복 배치 초기화 문제 해결
- 체크포인트를 위한 Task 클래스 참조 필드 직렬화 수정
- 가드레일 재시도 루프에서 BaseModel 결과 처리
- 보안 준수를 위해 python-dotenv를 버전 >=1.2.2로 업데이트
### 문서
- v1.14.3a1에 대한 변경 로그 및 버전 업데이트
- 설명 업데이트 및 실제 번역 적용
## 기여자
@MatthiasHowellYopp, @github-actions[bot], @greysonlalonde, @iris-clawd, @lorenzejay, @renatonitta
</Update>
<Update label="2026년 4월 21일">
## v1.14.3a1
[GitHub 릴리스 보기](https://github.com/crewAIInc/crewAI/releases/tag/1.14.3a1)
## 변경 사항
### 기능
- 독립형 에이전트에 체크포인트 및 포크 지원 추가
### 버그 수정
- Gemini 스트리밍 도구 호출에서 thought_signature 보존
- 포크 재개 시 task_started 방출 및 체크포인트 TUI 재설계
- dry-run 순서 수정 및 devtools 릴리스에서 체크아웃된 오래된 브랜치 처리
- 체크포인트 가지치기 테스트에서 미래 날짜 사용하여 시간 의존성 실패 방지 (#5543)
### 문서
- v1.14.2에 대한 변경 로그 및 버전 업데이트
## 기여자
@alex-clawd, @greysonlalonde
</Update>
<Update label="2026년 4월 17일">
## v1.14.2
[GitHub 릴리스 보기](https://github.com/crewAIInc/crewAI/releases/tag/1.14.2)
## 변경 사항
### 기능
- 체크포인트 재개, 차이(diff), 및 가지치기(prune) 명령을 추가하여 가시성을 개선했습니다.
- `Agent.kickoff` 및 관련 메서드에 `from_checkpoint` 매개변수를 추가했습니다.
- 프로젝트 템플릿을 위한 템플릿 관리 명령을 추가했습니다.
- 실패 시 개발 도구 릴리스에 재개 힌트를 추가했습니다.
- 배포 검증 CLI를 추가하고 LLM 초기화의 사용 편의성을 향상시켰습니다.
- 계보 추적이 가능한 체크포인트 포킹을 추가했습니다.
- 추론 토큰 및 캐시 생성 토큰으로 LLM 토큰 추적을 풍부하게 했습니다.
### 버그 수정
- 개발 도구 릴리스에서 오래된 브랜치 충돌에 대한 프롬프트를 수정했습니다.
- `authlib`, `langchain-text-splitters`, 및 `pypdf`의 취약점을 패치했습니다.
- 스트리밍 핸들러의 범위를 설정하여 교차 실행 청크 오염을 방지했습니다.
- TUI에서 Flow API를 통해 Flow 체크포인트를 전송했습니다.
- JSON 체크포인트 발견을 위해 재귀적 글로브를 사용했습니다.
- MCP 도구 해상도에서 순환 JSON 스키마를 처리했습니다.
- 진리값이 있는 기본값을 제거하여 Bedrock 도구 호출 인수를 보존했습니다.
- HITL 재개 후 flow_finished 이벤트를 발생시켰습니다.
- `requests`, `cryptography`, 및 `pytest`를 포함한 종속성을 업데이트하여 다양한 취약점을 수정했습니다.
- Bedrock Converse API에 엄격 모드를 전달하지 않도록 수정했습니다.
### 문서
- 누락된 매개변수를 문서화하고 체크포인팅 섹션을 추가했습니다.
- v1.14.2 및 이전 릴리스 후보에 대한 변경 로그 및 버전을 업데이트했습니다.
- 기업 A2A 기능 문서를 추가하고 OSS A2A 문서를 업데이트했습니다.
## 기여자
@Yanhu007, @alex-clawd, @github-actions[bot], @greysonlalonde, @iris-clawd, @lorenzejay, @lucasgomide
</Update>
<Update label="2026년 4월 16일">
## v1.14.2rc1
[GitHub 릴리스 보기](https://github.com/crewAIInc/crewAI/releases/tag/1.14.2rc1)
## 변경 사항
### 버그 수정
- MCP 도구 해상도에서 순환 JSON 스키마 처리 수정
- python-multipart를 0.0.26으로 업데이트하여 취약점 수정
- pypdf를 6.10.1로 업데이트하여 취약점 수정
### 문서
- v1.14.2a5에 대한 변경 로그 및 버전 업데이트
## 기여자
@greysonlalonde
</Update>
<Update label="2026년 4월 15일">
## v1.14.2a5
[GitHub 릴리스 보기](https://github.com/crewAIInc/crewAI/releases/tag/1.14.2a5)
## 변경 사항
### 문서
- v1.14.2a4의 변경 로그 및 버전 업데이트
## 기여자
@greysonlalonde
</Update>
<Update label="2026년 4월 15일">
## v1.14.2a4

View File

@@ -4,137 +4,6 @@ description: "Atualizações de produto, melhorias e correções do CrewAI"
icon: "clock"
mode: "wide"
---
<Update label="22 abr 2026">
## v1.14.3a2
[Ver release no GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.3a2)
## O que mudou
### Recursos
- Adicionar suporte para bedrock V4
- Adicionar ferramentas de sandbox Daytona para funcionalidade aprimorada
- Adicionar página 'Construir com IA' — documentação nativa de IA para agentes de codificação
- Adicionar Construir com IA à navegação Começar e arquivos de página para todos os idiomas (en, ko, pt-BR, ar)
### Correções de Bugs
- Corrigir a propagação de nomes implícitos @CrewBase para eventos da equipe
- Resolver problema com inicialização de lote duplicada na mesclagem de metadados de execução
- Corrigir a serialização de campos de referência de classe Task para checkpointing
- Lidar com o resultado BaseModel no loop de repetição de guardrail
- Atualizar python-dotenv para a versão >=1.2.2 para conformidade de segurança
### Documentação
- Atualizar changelog e versão para v1.14.3a1
- Atualizar descrições e aplicar traduções reais
## Contributors
@MatthiasHowellYopp, @github-actions[bot], @greysonlalonde, @iris-clawd, @lorenzejay, @renatonitta
</Update>
<Update label="21 abr 2026">
## v1.14.3a1
[Ver release no GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.3a1)
## O que Mudou
### Funcionalidades
- Adicionar suporte a checkpoint e fork para agentes autônomos
### Correções de Bugs
- Preservar thought_signature nas chamadas da ferramenta de streaming Gemini
- Emitir task_started na retomada do fork e redesenhar a TUI de checkpoint
- Corrigir a ordem do dry-run e lidar com branch desatualizada em release do devtools
- Usar datas futuras nos testes de poda de checkpoint para evitar falhas dependentes do tempo (#5543)
### Documentação
- Atualizar changelog e versão para v1.14.2
## Contribuidores
@alex-clawd, @greysonlalonde
</Update>
<Update label="17 abr 2026">
## v1.14.2
[Ver release no GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.2)
## O que Mudou
### Recursos
- Adicionar comandos de retomar, diferenciar e podar checkpoints com melhor descobribilidade.
- Adicionar o parâmetro `from_checkpoint` ao `Agent.kickoff` e métodos relacionados.
- Adicionar comandos de gerenciamento de templates para templates de projeto.
- Adicionar dicas de retomar na liberação de devtools em caso de falha.
- Adicionar CLI de validação de implantação e melhorar a ergonomia da inicialização do LLM.
- Adicionar bifurcação de checkpoints com rastreamento de linhagem.
- Enriquecer o rastreamento de tokens do LLM com tokens de raciocínio e tokens de criação de cache.
### Correções de Bugs
- Corrigir prompt em conflitos de branch obsoletos na liberação de devtools.
- Corrigir vulnerabilidades em `authlib`, `langchain-text-splitters` e `pypdf`.
- Restringir manipuladores de streaming para evitar contaminação de chunks entre execuções.
- Despachar checkpoints de Flow através das APIs de Flow na TUI.
- Usar glob recursivo para descoberta de checkpoints JSON.
- Lidar com esquemas JSON cíclicos na resolução de ferramentas MCP.
- Preservar os argumentos de chamada da ferramenta Bedrock removendo o padrão truthy.
- Emitir evento flow_finished após retomar HITL.
- Corrigir várias vulnerabilidades atualizando dependências, incluindo `requests`, `cryptography` e `pytest`.
- Corrigir para parar de encaminhar o modo estrito para a API Bedrock Converse.
### Documentação
- Documentar parâmetros ausentes e adicionar seção de Checkpointing.
- Atualizar changelog e versão para v1.14.2 e candidatos a liberação anteriores.
- Adicionar documentação da funcionalidade A2A empresarial e atualizar a documentação A2A OSS.
## Contribuidores
@Yanhu007, @alex-clawd, @github-actions[bot], @greysonlalonde, @iris-clawd, @lorenzejay, @lucasgomide
</Update>
<Update label="16 abr 2026">
## v1.14.2rc1
[Ver release no GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.2rc1)
## O que Mudou
### Correções de Bugs
- Corrigir o manuseio de esquemas JSON cíclicos na resolução da ferramenta MCP
- Corrigir vulnerabilidade atualizando python-multipart para 0.0.26
- Corrigir vulnerabilidade atualizando pypdf para 6.10.1
### Documentação
- Atualizar o changelog e a versão para v1.14.2a5
## Contribuidores
@greysonlalonde
</Update>
<Update label="15 abr 2026">
## v1.14.2a5
[Ver release no GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.2a5)
## O que Mudou
### Documentação
- Atualizar changelog e versão para v1.14.2a4
## Contribuidores
@greysonlalonde
</Update>
<Update label="15 abr 2026">
## v1.14.2a4

View File

@@ -94,6 +94,7 @@ google-genai = [
]
azure-ai-inference = [
"azure-ai-inference~=1.0.0b9",
"azure-identity>=1.17.0,<2",
]
anthropic = [
"anthropic~=0.73.0",

View File

@@ -35,6 +35,7 @@ try:
)
from azure.core.credentials import (
AzureKeyCredential,
TokenCredential,
)
from azure.core.exceptions import (
HttpResponseError,
@@ -88,6 +89,8 @@ class AzureCompletion(BaseLLM):
response_format: type[BaseModel] | None = None
is_openai_model: bool = False
is_azure_openai_endpoint: bool = False
azure_tenant_id: str | None = None
azure_client_id: str | None = None
_client: Any = PrivateAttr(default=None)
_async_client: Any = PrivateAttr(default=None)
@@ -115,6 +118,8 @@ class AzureCompletion(BaseLLM):
data["api_version"] = (
data.get("api_version") or os.getenv("AZURE_API_VERSION") or "2024-06-01"
)
data["azure_tenant_id"] = data.get("azure_tenant_id") or os.getenv("AZURE_TENANT_ID")
data["azure_client_id"] = data.get("azure_client_id") or os.getenv("AZURE_CLIENT_ID")
# Credentials and endpoint are validated lazily in `_init_clients`
# so the LLM can be constructed before deployment env vars are set.
@@ -183,24 +188,89 @@ class AzureCompletion(BaseLLM):
AzureCompletion._is_azure_openai_endpoint(self.endpoint)
)
if not self.api_key:
raise ValueError(
"Azure API key is required. Set AZURE_API_KEY environment "
"variable or pass api_key parameter."
)
# Re-read identity env vars for deferred builds
if not self.azure_tenant_id:
self.azure_tenant_id = os.getenv("AZURE_TENANT_ID")
if not self.azure_client_id:
self.azure_client_id = os.getenv("AZURE_CLIENT_ID")
if not self.endpoint:
raise ValueError(
"Azure endpoint is required. Set AZURE_ENDPOINT environment "
"variable or pass endpoint parameter."
)
credential = self._resolve_credential()
client_kwargs: dict[str, Any] = {
"endpoint": self.endpoint,
"credential": AzureKeyCredential(self.api_key),
"credential": credential,
}
if self.api_version:
client_kwargs["api_version"] = self.api_version
return client_kwargs
def _resolve_credential(self) -> AzureKeyCredential | TokenCredential:
"""Resolve the Azure credential using a priority chain.
1. OIDC federation (WorkloadIdentityCredential) — auto-discovered
from AZURE_FEDERATED_TOKEN_FILE + AZURE_TENANT_ID + AZURE_CLIENT_ID
2. Client secret (ClientSecretCredential) — explicit SP credentials
3. Default chain (DefaultAzureCredential) — Managed Identity et al.
4. API key fallback (AzureKeyCredential) — existing path
"""
federated_token_file = os.getenv("AZURE_FEDERATED_TOKEN_FILE")
client_secret = os.getenv("AZURE_CLIENT_SECRET")
# Path 1: OIDC Workload Identity Federation
if federated_token_file and self.azure_tenant_id and self.azure_client_id:
try:
from azure.identity import WorkloadIdentityCredential
return WorkloadIdentityCredential(
tenant_id=self.azure_tenant_id,
client_id=self.azure_client_id,
token_file_path=federated_token_file,
)
except ImportError:
raise ImportError(
"azure-identity is required for workload identity federation. "
'Install with: uv add "crewai[azure-ai-inference]"'
) from None
# Path 2: Client Secret (Service Principal)
if client_secret and self.azure_tenant_id and self.azure_client_id:
try:
from azure.identity import ClientSecretCredential
return ClientSecretCredential(
tenant_id=self.azure_tenant_id,
client_id=self.azure_client_id,
client_secret=client_secret,
)
except ImportError:
raise ImportError(
"azure-identity is required for service principal authentication. "
'Install with: uv add "crewai[azure-ai-inference]"'
) from None
# Path 3: DefaultAzureCredential (Managed Identity, Azure CLI, etc.)
# Only attempt if azure-identity is installed and no API key is available
if not self.api_key:
try:
from azure.identity import DefaultAzureCredential
return DefaultAzureCredential()
except ImportError:
raise ValueError(
"Azure API key is required when azure-identity is not installed. "
"Set AZURE_API_KEY environment variable, pass api_key parameter, "
'or install azure-identity: uv add "crewai[azure-ai-inference]"'
) from None
# Path 4: API Key (existing path)
return AzureKeyCredential(self.api_key)
def _get_sync_client(self) -> Any:
if self._client is None:
self._client = self._build_sync_client()

View File

@@ -0,0 +1,257 @@
"""Tests for Azure credential resolution chain in AzureCompletion.
Covers the four credential paths:
1. WorkloadIdentityCredential (OIDC federation)
2. ClientSecretCredential (Service Principal)
3. DefaultAzureCredential (Managed Identity / CLI fallback)
4. AzureKeyCredential (API key - existing path)
"""
import os
from unittest.mock import patch, MagicMock
import pytest
ENDPOINT = "https://test.openai.azure.com"
@pytest.fixture
def _clear_azure_env(monkeypatch):
"""Remove all Azure env vars to start clean."""
for key in [
"AZURE_API_KEY", "AZURE_ENDPOINT", "AZURE_OPENAI_ENDPOINT",
"AZURE_API_BASE", "AZURE_API_VERSION", "AZURE_TENANT_ID",
"AZURE_CLIENT_ID", "AZURE_CLIENT_SECRET", "AZURE_FEDERATED_TOKEN_FILE",
]:
monkeypatch.delenv(key, raising=False)
@pytest.mark.usefixtures("_clear_azure_env")
class TestCredentialResolution:
"""Tests for AzureCompletion._resolve_credential."""
def test_api_key_credential_when_api_key_set(self):
"""Path 4: API key produces AzureKeyCredential."""
from crewai.llms.providers.azure.completion import AzureCompletion
from azure.core.credentials import AzureKeyCredential
completion = AzureCompletion(
model="gpt-4",
api_key="test-key",
endpoint=ENDPOINT,
)
cred = completion._resolve_credential()
assert isinstance(cred, AzureKeyCredential)
def test_api_key_from_env(self, monkeypatch):
"""Path 4: api_key picked up from AZURE_API_KEY env var."""
from crewai.llms.providers.azure.completion import AzureCompletion
from azure.core.credentials import AzureKeyCredential
monkeypatch.setenv("AZURE_API_KEY", "env-key")
monkeypatch.setenv("AZURE_ENDPOINT", ENDPOINT)
completion = AzureCompletion(model="gpt-4")
cred = completion._resolve_credential()
assert isinstance(cred, AzureKeyCredential)
def test_workload_identity_credential(self, monkeypatch, tmp_path):
"""Path 1: OIDC federation via WorkloadIdentityCredential."""
from crewai.llms.providers.azure.completion import AzureCompletion
token_file = tmp_path / "token.txt"
token_file.write_text("eyJhbGciOiJSUzI1NiJ9.test")
monkeypatch.setenv("AZURE_FEDERATED_TOKEN_FILE", str(token_file))
monkeypatch.setenv("AZURE_ENDPOINT", ENDPOINT)
mock_wi_cred = MagicMock()
with patch(
"azure.identity.WorkloadIdentityCredential",
return_value=mock_wi_cred,
) as mock_cls:
completion = AzureCompletion(
model="gpt-4",
azure_tenant_id="tenant-123",
azure_client_id="client-456",
)
cred = completion._resolve_credential()
assert cred is mock_wi_cred
mock_cls.assert_called_once_with(
tenant_id="tenant-123",
client_id="client-456",
token_file_path=str(token_file),
)
def test_workload_identity_from_env_vars(self, monkeypatch, tmp_path):
"""Path 1: All WI fields discovered from environment."""
from crewai.llms.providers.azure.completion import AzureCompletion
token_file = tmp_path / "token.txt"
token_file.write_text("eyJhbGciOiJSUzI1NiJ9.test")
monkeypatch.setenv("AZURE_FEDERATED_TOKEN_FILE", str(token_file))
monkeypatch.setenv("AZURE_TENANT_ID", "env-tenant")
monkeypatch.setenv("AZURE_CLIENT_ID", "env-client")
monkeypatch.setenv("AZURE_ENDPOINT", ENDPOINT)
mock_wi_cred = MagicMock()
with patch(
"azure.identity.WorkloadIdentityCredential",
return_value=mock_wi_cred,
) as mock_cls:
completion = AzureCompletion(model="gpt-4")
cred = completion._resolve_credential()
assert cred is mock_wi_cred
mock_cls.assert_called_once_with(
tenant_id="env-tenant",
client_id="env-client",
token_file_path=str(token_file),
)
def test_client_secret_credential(self, monkeypatch):
"""Path 2: Service Principal with client secret."""
from crewai.llms.providers.azure.completion import AzureCompletion
monkeypatch.setenv("AZURE_CLIENT_SECRET", "sp-secret")
monkeypatch.setenv("AZURE_ENDPOINT", ENDPOINT)
mock_cs_cred = MagicMock()
with patch(
"azure.identity.ClientSecretCredential",
return_value=mock_cs_cred,
) as mock_cls:
completion = AzureCompletion(
model="gpt-4",
azure_tenant_id="tenant-123",
azure_client_id="client-456",
)
cred = completion._resolve_credential()
assert cred is mock_cs_cred
mock_cls.assert_called_once_with(
tenant_id="tenant-123",
client_id="client-456",
client_secret="sp-secret",
)
def test_default_azure_credential_when_no_api_key(self, monkeypatch):
"""Path 3: DefaultAzureCredential when no api_key and no SP/WI vars."""
from crewai.llms.providers.azure.completion import AzureCompletion
monkeypatch.setenv("AZURE_ENDPOINT", ENDPOINT)
mock_default_cred = MagicMock()
with patch(
"azure.identity.DefaultAzureCredential",
return_value=mock_default_cred,
):
completion = AzureCompletion(model="gpt-4")
cred = completion._resolve_credential()
assert cred is mock_default_cred
def test_workload_identity_takes_priority_over_api_key(self, monkeypatch, tmp_path):
"""WI credential should take priority even when api_key is also set."""
from crewai.llms.providers.azure.completion import AzureCompletion
token_file = tmp_path / "token.txt"
token_file.write_text("eyJhbGciOiJSUzI1NiJ9.test")
monkeypatch.setenv("AZURE_FEDERATED_TOKEN_FILE", str(token_file))
monkeypatch.setenv("AZURE_API_KEY", "should-not-use-this")
monkeypatch.setenv("AZURE_ENDPOINT", ENDPOINT)
mock_wi_cred = MagicMock()
with patch(
"azure.identity.WorkloadIdentityCredential",
return_value=mock_wi_cred,
):
completion = AzureCompletion(
model="gpt-4",
azure_tenant_id="tenant-123",
azure_client_id="client-456",
)
cred = completion._resolve_credential()
assert cred is mock_wi_cred
def test_client_secret_takes_priority_over_api_key(self, monkeypatch):
"""SP credential should take priority over API key."""
from crewai.llms.providers.azure.completion import AzureCompletion
monkeypatch.setenv("AZURE_CLIENT_SECRET", "sp-secret")
monkeypatch.setenv("AZURE_API_KEY", "should-not-use-this")
monkeypatch.setenv("AZURE_ENDPOINT", ENDPOINT)
mock_cs_cred = MagicMock()
with patch(
"azure.identity.ClientSecretCredential",
return_value=mock_cs_cred,
):
completion = AzureCompletion(
model="gpt-4",
azure_tenant_id="tenant-123",
azure_client_id="client-456",
)
cred = completion._resolve_credential()
assert cred is mock_cs_cred
def test_raises_when_no_api_key_and_no_azure_identity(self, monkeypatch):
"""ValueError when no api_key and azure-identity not installed."""
from crewai.llms.providers.azure.completion import AzureCompletion
monkeypatch.setenv("AZURE_ENDPOINT", ENDPOINT)
with patch.dict("sys.modules", {"azure.identity": None}):
completion = AzureCompletion(model="gpt-4")
with pytest.raises(ValueError, match="Azure API key is required"):
completion._resolve_credential()
def test_endpoint_still_required(self, monkeypatch, tmp_path):
"""Endpoint is always required regardless of credential type."""
from crewai.llms.providers.azure.completion import AzureCompletion
token_file = tmp_path / "token.txt"
token_file.write_text("test-jwt")
monkeypatch.setenv("AZURE_FEDERATED_TOKEN_FILE", str(token_file))
monkeypatch.setenv("AZURE_TENANT_ID", "tenant-123")
monkeypatch.setenv("AZURE_CLIENT_ID", "client-456")
completion = AzureCompletion(model="gpt-4")
with pytest.raises(ValueError, match="Azure endpoint is required"):
completion._make_client_kwargs()
def test_deferred_build_picks_up_wi_env_vars(self, monkeypatch, tmp_path):
"""Env vars set after construction are picked up on deferred build."""
from crewai.llms.providers.azure.completion import AzureCompletion
# Construct with endpoint only — no credentials yet
monkeypatch.setenv("AZURE_ENDPOINT", ENDPOINT)
completion = AzureCompletion(model="gpt-4")
# Now set WI env vars (simulating WI manager setting them before crew run)
token_file = tmp_path / "token.txt"
token_file.write_text("eyJhbGciOiJSUzI1NiJ9.deferred")
monkeypatch.setenv("AZURE_FEDERATED_TOKEN_FILE", str(token_file))
monkeypatch.setenv("AZURE_TENANT_ID", "deferred-tenant")
monkeypatch.setenv("AZURE_CLIENT_ID", "deferred-client")
mock_wi_cred = MagicMock()
with patch(
"azure.identity.WorkloadIdentityCredential",
return_value=mock_wi_cred,
):
kwargs = completion._make_client_kwargs()
assert kwargs["credential"] is mock_wi_cred
def test_make_client_kwargs_includes_api_version(self, monkeypatch):
"""api_version is included in client kwargs."""
from crewai.llms.providers.azure.completion import AzureCompletion
monkeypatch.setenv("AZURE_API_KEY", "test-key")
monkeypatch.setenv("AZURE_ENDPOINT", ENDPOINT)
completion = AzureCompletion(model="gpt-4", api_version="2025-01-01")
kwargs = completion._make_client_kwargs()
assert kwargs["api_version"] == "2025-01-01"
assert kwargs["endpoint"] == ENDPOINT