Skip to content

feat: add OCI Generative AI provider — basic text completion#4959

Open
fede-kamel wants to merge 8 commits intocrewAIInc:mainfrom
fede-kamel:feat/oci-provider-core
Open

feat: add OCI Generative AI provider — basic text completion#4959
fede-kamel wants to merge 8 commits intocrewAIInc:mainfrom
fede-kamel:feat/oci-provider-core

Conversation

@fede-kamel
Copy link
Copy Markdown

@fede-kamel fede-kamel commented Mar 19, 2026

Summary

  • Add native OCI Generative AI text completion provider (OCICompletion) supporting generic (Meta, Google, OpenAI, xAI) and Cohere model families
  • Shared OCI auth utilities (utilities/oci.py) for API key, security token, instance principal, and resource principal auth
  • OCI registered as optional dependency (crewai[oci])
  • 15 unit tests (mocked SDK) + 2 parametrized integration tests (tested live against meta.llama-3.3-70b-instruct, cohere.command-r-plus-08-2024, google.gemini-2.5-flash, openai.gpt-5.2-chat-latest)

This is PR 1 of a series — follow-up PRs will add streaming, tool calling, structured output, multimodal, and embeddings support.

Supersedes #4885 (closed per reviewer feedback to split by scope).
Tracking issue: #4944

What's included

File Lines What
utilities/oci.py 72 Shared get_oci_module() + create_oci_client_kwargs()
llms/providers/oci/completion.py 505 OCICompletion(BaseLLM) — init, message building, basic call/acall
llm.py +13 Provider registration (routing, pattern matching, import)
pyproject.toml +3 oci optional dependency
Tests 491 conftest + 15 unit + 2 integration (parametrized across models)

What's NOT included (deferred to follow-up PRs)

  • Streaming (iter_stream, astream)
  • Tool calling / function calling
  • Structured output (response_model)
  • Multimodal (vision, documents, audio, video)
  • OCI embeddings provider
  • OCI tools (will be a standalone PyPI package per community tools guidelines)

Test plan

  • 15 unit tests pass (mocked OCI SDK, no credentials needed)
  • Integration tests pass against 4 model families via OCI GenAI API:
    • meta.llama-3.3-70b-instruct
    • cohere.command-r-plus-08-2024
    • google.gemini-2.5-flash
    • openai.gpt-5.2-chat-latest
  • Both sync (call) and async (acall) paths verified

Note

Medium Risk
Adds a new native LLM provider with multiple OCI authentication modes and new routing/pattern matching, which could affect model selection and introduce integration/auth edge cases. Changes are mostly additive and isolated, but involve external SDK calls and credential handling.

Overview
Adds first-class support for Oracle Cloud Infrastructure (OCI) Generative AI as a native LLM provider, including provider routing (oci/...) and model-pattern validation for OCI model IDs and dedicated endpoint OCIDs.

Introduces OCICompletion for basic synchronous/async chat-based text completion (generic + Cohere formats), plus shared OCI SDK utilities for lazy importing and building client auth kwargs (API key, security token, instance/resource principals). Also registers oci as an optional dependency (crewai[oci]) and adds mocked unit tests plus live integration tests for the new provider.

Reviewed by Cursor Bugbot for commit 7ef6c02. Bugbot is set up for automated code reviews on this repo. Configure here.

@fede-kamel
Copy link
Copy Markdown
Author

@greysonlalonde Hey! Following up on your feedback from #4885 — I split the original PR into smaller, scoped pieces. This is the first one: just the basic text completion provider for OCI GenAI (no streaming, no tools, no structured output, no multimodal, no embeddings).

I couldn't trim this one further — it's the minimal foundation (provider class + shared auth + registration) plus tests. The source code is ~600 lines and the rest is test fixtures/tests. Each follow-up PR will layer on one capability at a time.

Also, per the community tools guide you shared — the OCI tools (InvokeAgent, KnowledgeBase, ObjectStorage) will go into a standalone PyPI package (crewai-oci-tools), not into the crewAI repo.

Would appreciate a review whenever you get a chance. Thanks!

fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Mar 19, 2026
Add streaming text completion via OCI SSE events:
- stream=True in call() routes to _stream_call_impl with chunk events
- iter_stream() yields raw text chunks (sync generator)
- astream() wraps iter_stream via thread+queue for async callers
- _stream_chat_events holds client lock for full stream duration
- SSE event parsing handles both string and mapping payloads

Tested live against meta.llama-3.3-70b-instruct,
cohere.command-r-plus-08-2024, google.gemini-2.5-flash,
and openai.gpt-5.2-chat-latest.

Depends on: crewAIInc#4959
Tracking issue: crewAIInc#4944
fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Mar 19, 2026
Add native function calling for generic and Cohere model families:
- _format_tools converts CrewAI tool specs to OCI SDK format
- _extract_tool_calls normalizes responses back to CrewAI shape
- _handle_tool_calls executes tools and recurses until model finishes
- Cohere tool message handling with trailing tool results
- Tool choice control (auto/none/required/function)
- Passthrough parameter filtering via SDK introspection
- Streaming tool call accumulation from SSE fragments
- supports_function_calling() returns True

Tested live against meta.llama-3.3-70b-instruct with
raw tool call return and recursive tool execution.

Depends on: crewAIInc#4961 (streaming), crewAIInc#4959 (basic text)
Tracking issue: crewAIInc#4944
fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Mar 19, 2026
Add response_model (Pydantic) support for structured output:
- _build_response_format converts Pydantic schema to OCI
  JsonSchemaResponseFormat (generic) or CohereResponseJsonFormat
- _parse_structured_response validates and returns typed models
- response_model threaded through call, _call_impl, _stream_call_impl,
  and _handle_tool_calls for full coverage
- Handles JSON in markdown fences via base class _validate_structured_output

Tested live against meta.llama-3.3-70b-instruct and
google.gemini-2.5-flash.

Depends on: crewAIInc#4962 (tool calling), crewAIInc#4961 (streaming), crewAIInc#4959 (basic text)
Tracking issue: crewAIInc#4944
fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Mar 19, 2026
Add multimodal content handling for generic model families:
- vision.py: model lists, data URI helpers, image encoding utilities
- _build_generic_content handles image_url, document_url, video_url,
  audio_url content types mapped to OCI SDK content objects
- _message_has_multimodal_content detects non-text payloads
- Cohere models reject multimodal with clear error message
- supports_multimodal() returns True

Depends on: crewAIInc#4963, crewAIInc#4962, crewAIInc#4961, crewAIInc#4959
Tracking issue: crewAIInc#4944
fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Mar 19, 2026
Add OCI embedding support integrated with CrewAI's RAG pipeline:
- OCIEmbeddingFunction: ChromaDB-compatible embedding callable with
  batching, config serialization, image embedding support
- OCIProvider: Pydantic-based provider with alias validation for
  env vars and config keys
- Factory registration in embeddings/factory.py + types.py
- Supports text and image embeddings, output dimensions,
  custom endpoints, all 4 OCI auth modes

Tested live against cohere.embed-english-v3.0 with API_KEY auth.

Depends on: crewAIInc#4964, crewAIInc#4963, crewAIInc#4962, crewAIInc#4961, crewAIInc#4959
Tracking issue: crewAIInc#4944
fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Mar 20, 2026
Replace asyncio.to_thread wrappers with true async I/O using aiohttp
for acall() and astream(). The OCI SDK is sync-only, so we bypass it
for HTTP and use its signer for request authentication directly.

- oci_async.py: OCIAsyncClient with aiohttp, OCI request signing,
  native SSE parsing, connection pooling
- acall(): true async chat completion (no thread pool)
- astream(): true async SSE streaming (no thread+queue bridge)
- Graceful fallback to asyncio.to_thread when aiohttp unavailable
  or client is mocked (unit tests)
- aiohttp + certifi added to crewai[oci] optional deps

Temporary measure until OCI SDK ships native async support.

Tested live: acall, astream, and concurrent acall against
meta.llama-3.3-70b-instruct with API_KEY auth.

Depends on: crewAIInc#4966, crewAIInc#4964, crewAIInc#4963, crewAIInc#4962, crewAIInc#4961, crewAIInc#4959
Tracking issue: crewAIInc#4944
@fede-kamel fede-kamel force-pushed the feat/oci-provider-core branch from 105d7dd to e6b52b5 Compare March 29, 2026 16:13
fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Mar 29, 2026
Add streaming text completion via OCI SSE events:
- stream=True in call() routes to _stream_call_impl with chunk events
- iter_stream() yields raw text chunks (sync generator)
- astream() wraps iter_stream via thread+queue for async callers
- _stream_chat_events holds client lock for full stream duration
- SSE event parsing handles both string and mapping payloads

Tested live against meta.llama-3.3-70b-instruct,
cohere.command-r-plus-08-2024, google.gemini-2.5-flash,
and openai.gpt-5.2-chat-latest.

Depends on: crewAIInc#4959
Tracking issue: crewAIInc#4944
fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Mar 29, 2026
Add streaming text completion via OCI SSE events:
- stream=True in call() routes to _stream_call_impl with chunk events
- iter_stream() yields raw text chunks (sync generator)
- astream() wraps iter_stream via thread+queue for async callers
- _stream_chat_events holds client lock for full stream duration
- SSE event parsing handles both string and mapping payloads

Tested live against meta.llama-3.3-70b-instruct,
cohere.command-r-plus-08-2024, google.gemini-2.5-flash,
and openai.gpt-5.2-chat-latest.

Depends on: crewAIInc#4959
Tracking issue: crewAIInc#4944
fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Mar 29, 2026
Add native function calling for generic and Cohere model families:
- _format_tools converts CrewAI tool specs to OCI SDK format
- _extract_tool_calls normalizes responses back to CrewAI shape
- _handle_tool_calls executes tools and recurses until model finishes
- Cohere tool message handling with trailing tool results
- Tool choice control (auto/none/required/function)
- Passthrough parameter filtering via SDK introspection
- Streaming tool call accumulation from SSE fragments
- supports_function_calling() returns True

Tested live against meta.llama-3.3-70b-instruct with
raw tool call return and recursive tool execution.

Depends on: crewAIInc#4961 (streaming), crewAIInc#4959 (basic text)
Tracking issue: crewAIInc#4944
fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Mar 29, 2026
Add streaming text completion via OCI SSE events:
- stream=True in call() routes to _stream_call_impl with chunk events
- iter_stream() yields raw text chunks (sync generator)
- astream() wraps iter_stream via thread+queue for async callers
- _stream_chat_events holds client lock for full stream duration
- SSE event parsing handles both string and mapping payloads

Tested live against meta.llama-3.3-70b-instruct,
cohere.command-r-plus-08-2024, google.gemini-2.5-flash,
and openai.gpt-5.2-chat-latest.

Depends on: crewAIInc#4959
Tracking issue: crewAIInc#4944
fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Mar 29, 2026
Add native function calling for generic and Cohere model families:
- _format_tools converts CrewAI tool specs to OCI SDK format
- _extract_tool_calls normalizes responses back to CrewAI shape
- _handle_tool_calls executes tools and recurses until model finishes
- Cohere tool message handling with trailing tool results
- Tool choice control (auto/none/required/function)
- Passthrough parameter filtering via SDK introspection
- Streaming tool call accumulation from SSE fragments
- supports_function_calling() returns True

Tested live against meta.llama-3.3-70b-instruct with
raw tool call return and recursive tool execution.

Depends on: crewAIInc#4961 (streaming), crewAIInc#4959 (basic text)
Tracking issue: crewAIInc#4944
fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Mar 29, 2026
Add response_model (Pydantic) support for structured output:
- _build_response_format converts Pydantic schema to OCI
  JsonSchemaResponseFormat (generic) or CohereResponseJsonFormat
- _parse_structured_response validates and returns typed models
- response_model threaded through call, _call_impl, _stream_call_impl,
  and _handle_tool_calls for full coverage
- Handles JSON in markdown fences via base class _validate_structured_output

Tested live against meta.llama-3.3-70b-instruct and
google.gemini-2.5-flash.

Depends on: crewAIInc#4962 (tool calling), crewAIInc#4961 (streaming), crewAIInc#4959 (basic text)
Tracking issue: crewAIInc#4944
fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Mar 29, 2026
Add streaming text completion via OCI SSE events:
- stream=True in call() routes to _stream_call_impl with chunk events
- iter_stream() yields raw text chunks (sync generator)
- astream() wraps iter_stream via thread+queue for async callers
- _stream_chat_events holds client lock for full stream duration
- SSE event parsing handles both string and mapping payloads

Tested live against meta.llama-3.3-70b-instruct,
cohere.command-r-plus-08-2024, google.gemini-2.5-flash,
and openai.gpt-5.2-chat-latest.

Depends on: crewAIInc#4959
Tracking issue: crewAIInc#4944
fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Mar 29, 2026
Add native function calling for generic and Cohere model families:
- _format_tools converts CrewAI tool specs to OCI SDK format
- _extract_tool_calls normalizes responses back to CrewAI shape
- _handle_tool_calls executes tools and recurses until model finishes
- Cohere tool message handling with trailing tool results
- Tool choice control (auto/none/required/function)
- Passthrough parameter filtering via SDK introspection
- Streaming tool call accumulation from SSE fragments
- supports_function_calling() returns True

Tested live against meta.llama-3.3-70b-instruct with
raw tool call return and recursive tool execution.

Depends on: crewAIInc#4961 (streaming), crewAIInc#4959 (basic text)
Tracking issue: crewAIInc#4944
fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Mar 29, 2026
Add response_model (Pydantic) support for structured output:
- _build_response_format converts Pydantic schema to OCI
  JsonSchemaResponseFormat (generic) or CohereResponseJsonFormat
- _parse_structured_response validates and returns typed models
- response_model threaded through call, _call_impl, _stream_call_impl,
  and _handle_tool_calls for full coverage
- Handles JSON in markdown fences via base class _validate_structured_output

Tested live against meta.llama-3.3-70b-instruct and
google.gemini-2.5-flash.

Depends on: crewAIInc#4962 (tool calling), crewAIInc#4961 (streaming), crewAIInc#4959 (basic text)
Tracking issue: crewAIInc#4944
fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Mar 29, 2026
Add multimodal content handling for generic model families:
- vision.py: model lists, data URI helpers, image encoding utilities
- _build_generic_content handles image_url, document_url, video_url,
  audio_url content types mapped to OCI SDK content objects
- _message_has_multimodal_content detects non-text payloads
- Cohere models reject multimodal with clear error message
- supports_multimodal() returns True

Depends on: crewAIInc#4963, crewAIInc#4962, crewAIInc#4961, crewAIInc#4959
Tracking issue: crewAIInc#4944
fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Mar 29, 2026
Add streaming text completion via OCI SSE events:
- stream=True in call() routes to _stream_call_impl with chunk events
- iter_stream() yields raw text chunks (sync generator)
- astream() wraps iter_stream via thread+queue for async callers
- _stream_chat_events holds client lock for full stream duration
- SSE event parsing handles both string and mapping payloads

Tested live against meta.llama-3.3-70b-instruct,
cohere.command-r-plus-08-2024, google.gemini-2.5-flash,
and openai.gpt-5.2-chat-latest.

Depends on: crewAIInc#4959
Tracking issue: crewAIInc#4944
fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Mar 29, 2026
Add native function calling for generic and Cohere model families:
- _format_tools converts CrewAI tool specs to OCI SDK format
- _extract_tool_calls normalizes responses back to CrewAI shape
- _handle_tool_calls executes tools and recurses until model finishes
- Cohere tool message handling with trailing tool results
- Tool choice control (auto/none/required/function)
- Passthrough parameter filtering via SDK introspection
- Streaming tool call accumulation from SSE fragments
- supports_function_calling() returns True

Tested live against meta.llama-3.3-70b-instruct with
raw tool call return and recursive tool execution.

Depends on: crewAIInc#4961 (streaming), crewAIInc#4959 (basic text)
Tracking issue: crewAIInc#4944
fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Mar 29, 2026
Add response_model (Pydantic) support for structured output:
- _build_response_format converts Pydantic schema to OCI
  JsonSchemaResponseFormat (generic) or CohereResponseJsonFormat
- _parse_structured_response validates and returns typed models
- response_model threaded through call, _call_impl, _stream_call_impl,
  and _handle_tool_calls for full coverage
- Handles JSON in markdown fences via base class _validate_structured_output

Tested live against meta.llama-3.3-70b-instruct and
google.gemini-2.5-flash.

Depends on: crewAIInc#4962 (tool calling), crewAIInc#4961 (streaming), crewAIInc#4959 (basic text)
Tracking issue: crewAIInc#4944
fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Mar 29, 2026
Add multimodal content handling for generic model families:
- vision.py: model lists, data URI helpers, image encoding utilities
- _build_generic_content handles image_url, document_url, video_url,
  audio_url content types mapped to OCI SDK content objects
- _message_has_multimodal_content detects non-text payloads
- Cohere models reject multimodal with clear error message
- supports_multimodal() returns True

Depends on: crewAIInc#4963, crewAIInc#4962, crewAIInc#4961, crewAIInc#4959
Tracking issue: crewAIInc#4944
fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Mar 29, 2026
Add OCI embedding support integrated with CrewAI's RAG pipeline:
- OCIEmbeddingFunction: ChromaDB-compatible embedding callable with
  batching, config serialization, image embedding support
- OCIProvider: Pydantic-based provider with alias validation for
  env vars and config keys
- Factory registration in embeddings/factory.py + types.py
- Supports text and image embeddings, output dimensions,
  custom endpoints, all 4 OCI auth modes

Tested live against cohere.embed-english-v3.0 with API_KEY auth.

Depends on: crewAIInc#4964, crewAIInc#4963, crewAIInc#4962, crewAIInc#4961, crewAIInc#4959
Tracking issue: crewAIInc#4944
fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Mar 29, 2026
Add streaming text completion via OCI SSE events:
- stream=True in call() routes to _stream_call_impl with chunk events
- iter_stream() yields raw text chunks (sync generator)
- astream() wraps iter_stream via thread+queue for async callers
- _stream_chat_events holds client lock for full stream duration
- SSE event parsing handles both string and mapping payloads

Tested live against meta.llama-3.3-70b-instruct,
cohere.command-r-plus-08-2024, google.gemini-2.5-flash,
and openai.gpt-5.2-chat-latest.

Depends on: crewAIInc#4959
Tracking issue: crewAIInc#4944
fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Mar 29, 2026
Add native function calling for generic and Cohere model families:
- _format_tools converts CrewAI tool specs to OCI SDK format
- _extract_tool_calls normalizes responses back to CrewAI shape
- _handle_tool_calls executes tools and recurses until model finishes
- Cohere tool message handling with trailing tool results
- Tool choice control (auto/none/required/function)
- Passthrough parameter filtering via SDK introspection
- Streaming tool call accumulation from SSE fragments
- supports_function_calling() returns True

Tested live against meta.llama-3.3-70b-instruct with
raw tool call return and recursive tool execution.

Depends on: crewAIInc#4961 (streaming), crewAIInc#4959 (basic text)
Tracking issue: crewAIInc#4944
fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Mar 29, 2026
Add response_model (Pydantic) support for structured output:
- _build_response_format converts Pydantic schema to OCI
  JsonSchemaResponseFormat (generic) or CohereResponseJsonFormat
- _parse_structured_response validates and returns typed models
- response_model threaded through call, _call_impl, _stream_call_impl,
  and _handle_tool_calls for full coverage
- Handles JSON in markdown fences via base class _validate_structured_output

Tested live against meta.llama-3.3-70b-instruct and
google.gemini-2.5-flash.

Depends on: crewAIInc#4962 (tool calling), crewAIInc#4961 (streaming), crewAIInc#4959 (basic text)
Tracking issue: crewAIInc#4944
fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Mar 29, 2026
Add multimodal content handling for generic model families:
- vision.py: model lists, data URI helpers, image encoding utilities
- _build_generic_content handles image_url, document_url, video_url,
  audio_url content types mapped to OCI SDK content objects
- _message_has_multimodal_content detects non-text payloads
- Cohere models reject multimodal with clear error message
- supports_multimodal() returns True

Depends on: crewAIInc#4963, crewAIInc#4962, crewAIInc#4961, crewAIInc#4959
Tracking issue: crewAIInc#4944
fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Mar 29, 2026
Add OCI embedding support integrated with CrewAI's RAG pipeline:
- OCIEmbeddingFunction: ChromaDB-compatible embedding callable with
  batching, config serialization, image embedding support
- OCIProvider: Pydantic-based provider with alias validation for
  env vars and config keys
- Factory registration in embeddings/factory.py + types.py
- Supports text and image embeddings, output dimensions,
  custom endpoints, all 4 OCI auth modes

Tested live against cohere.embed-english-v3.0 with API_KEY auth.

Depends on: crewAIInc#4964, crewAIInc#4963, crewAIInc#4962, crewAIInc#4961, crewAIInc#4959
Tracking issue: crewAIInc#4944
fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Mar 29, 2026
Replace asyncio.to_thread wrappers with true async I/O using aiohttp
for acall() and astream(). The OCI SDK is sync-only, so we bypass it
for HTTP and use its signer for request authentication directly.

- oci_async.py: OCIAsyncClient with aiohttp, OCI request signing,
  native SSE parsing, connection pooling
- acall(): true async chat completion (no thread pool)
- astream(): true async SSE streaming (no thread+queue bridge)
- Graceful fallback to asyncio.to_thread when aiohttp unavailable
  or client is mocked (unit tests)
- aiohttp + certifi added to crewai[oci] optional deps

Temporary measure until OCI SDK ships native async support.

Tested live: acall, astream, and concurrent acall against
meta.llama-3.3-70b-instruct with API_KEY auth.

Depends on: crewAIInc#4966, crewAIInc#4964, crewAIInc#4963, crewAIInc#4962, crewAIInc#4961, crewAIInc#4959
Tracking issue: crewAIInc#4944
@fede-kamel
Copy link
Copy Markdown
Author

@greysonlalonde — following up on your feedback from #4885. I've split the original PR into scoped pieces per your guidance. The first one is ready for review.

PR 1 of 7 — Basic OCI text completion (this PR)

Covers only the foundation: provider class, shared auth utilities, routing registration, and tests. No streaming, tool calling, structured output, multimodal, or embeddings — all deferred to follow-up PRs.

The Bugbot-flagged supports_function_calling issue from an early commit was already addressed — the method was corrected to False and then removed entirely, so the executor correctly falls back to the ReAct loop when tools are present.

Full series (tracking issue: #4944):

  1. feat: add OCI Generative AI provider — basic text completion #4959 — Basic text completion ← this PR
  2. feat: add streaming support to OCI Generative AI provider #4961 — Streaming
  3. feat: add tool calling support to OCI Generative AI provider #4962 — Tool calling
  4. feat: add structured output support to OCI Generative AI provider #4963 — Structured output
  5. feat: add multimodal support to OCI Generative AI provider #4964 — Multimodal
  6. feat: add OCI Generative AI embeddings provider #4966 — Embeddings
  7. feat: add true async support to OCI provider via aiohttp #4982 — True async (aiohttp)

Would appreciate a review whenever you get a chance. Thanks again for the guidance on scope!

fede-kamel added a commit to fede-kamel/crewAI that referenced this pull request Apr 1, 2026
- OCICompletion(BaseLLM): sync call() and async acall() for generic
  (Meta, Google, OpenAI, xAI) and Cohere model families
- Shared OCI auth utilities (utilities/oci.py): API key, security token,
  instance principal, and resource principal auth
- Provider routing in llm.py: oci/ prefix and OCI model-id patterns
- oci registered as optional dependency (crewai[oci])
- Configurable timeout via DEFAULT_OCI_TIMEOUT constant
- Cohere and generic request/response paths fully separated

Tracking issue: crewAIInc#4944
Part 1 of series: crewAIInc#4959crewAIInc#4961crewAIInc#4962crewAIInc#4963crewAIInc#4964crewAIInc#4966crewAIInc#4982
@fede-kamel fede-kamel force-pushed the feat/oci-provider-core branch from b904813 to 7561683 Compare April 1, 2026 15:48
@fede-kamel
Copy link
Copy Markdown
Author

fede-kamel commented Apr 1, 2026

Live integration test results

Validated against a live OCI GenAI account (us-chicago-1, API key auth):

Model call() acall()
meta.llama-3.3-70b-instruct
cohere.command-r-plus-08-2024
google.gemini-2.5-flash
6 passed

All three model families (Llama, Cohere, Gemini) confirmed working against the live API, both sync and async.

@fede-kamel
Copy link
Copy Markdown
Author

Hi @greysonlalonde — just a gentle follow-up. I did everything you asked after #4885 — split the work into 7 scoped PRs, deferred streaming, tool calling, structured output, multimodal, and embeddings to separate PRs, and confirmed OCI tools will go into a standalone PyPI package.

This first PR is the minimal foundation: provider class, shared auth, routing registration, and tests. It's been validated against a live OCI GenAI account across all three model families (Llama, Cohere, Gemini) — both sync and async.

Would really appreciate a review whenever you get the chance. Happy to make any adjustments!

Add native OCI Generative AI support to CrewAI with basic text
completion for generic (Meta, Google, OpenAI, xAI) and Cohere model
families. This is the first in a series of PRs to incrementally
build out full OCI support (streaming, tool calling, structured
output, embeddings, and multimodal in follow-up PRs).

Tracking issue: crewAIInc#4944
Supersedes: crewAIInc#4885
Tool calling is not implemented in this PR. Returning True would
cause CrewAI to choose the native tools path, silently dropping
tools from agents. Flagged by Cursor Bugbot review.
Both methods are unnecessary in this PR. The base class and callers
already default correctly when the methods are absent:
- supports_function_calling: callers use getattr with False default
- supports_stop_words: base class already returns True

These will be added back in the tool calling follow-up PR.
Remove json, re imports and _OCI_SCHEMA_NAME_PATTERN regex that
are only needed for structured output (not in this PR scope).
Use model_lower instead of model in the dot check to match the
convention used by all other providers in _matches_provider_pattern.
Flagged by Cursor Bugbot.
The explicit OCI branch returned the same _matches_provider_pattern
call as the generic fallback. Removing it since it adds no distinct
logic. Flagged by Cursor Bugbot.
- Add missing empty-string fallback for bare strings in list content
- Use case-insensitive model checks consistently across all methods
- Replace over-engineered FIFO ticket queue with simple threading.Lock
…ature

- Move _normalize_messages inside llm_call_context and try/except so
  validation errors emit call_failed events consistently
- Narrow _call_impl to accept list[LLMMessage] only, removing unreachable
  str normalization path
@fede-kamel fede-kamel force-pushed the feat/oci-provider-core branch from b5130c4 to 7ef6c02 Compare April 11, 2026 22:52
@fede-kamel
Copy link
Copy Markdown
Author

Rebased on latest main (clean, no conflicts) and re-verified all tests:

Unit tests — 15/15 passed (Python 3.13, mocked OCI SDK)
Integration tests — 6/6 passed against live OCI GenAI API (us-chicago-1, API key auth)

Model call() acall()
meta.llama-3.3-70b-instruct
cohere.command-r-plus-08-2024
google.gemini-2.5-flash

Branch is clean — 8 commits rebased on current main, no merge commits.

@greysonlalonde — would really appreciate a review on this foundational PR when you get a chance. The remaining 6 PRs in the series (#4961#4982) all build on top of this one. Happy to address any feedback!

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 7ef6c02. Configure here.

models.CohereChatBotMessage(
message=self._coerce_text(content) or " ",
)
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cohere empty content handling is inconsistent across roles

Low Severity

In _build_cohere_chat_history, empty content for assistant messages is replaced with " " (a space character) via self._coerce_text(content) or " ", but empty content for user and system messages passes through self._coerce_text(content) with no fallback, yielding an empty string "". If the Cohere API rejects empty message fields on CohereUserMessage or CohereSystemMessage, this inconsistency would cause API errors for user/system messages while silently working for assistant messages.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 7ef6c02. Configure here.


def _get_oci_module() -> Any:
"""Backward-compatible module-local alias used by tests and patches."""
return get_oci_module()
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrapper function adds unnecessary indirection over direct import

Low Severity

The module-level _get_oci_module function is a trivial wrapper that delegates to get_oci_module (already imported on line 14). Its docstring says it exists for test patching, but tests could instead directly monkeypatch the imported get_oci_module reference at crewai.llms.providers.oci.completion.get_oci_module. Since create_oci_client_kwargs already receives the module explicitly via oci_module=self._oci, patching the single local reference would be sufficient.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 7ef6c02. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant