From 604703c06466874e10253091e523a8ee64a4aa29 Mon Sep 17 00:00:00 2001 From: Otto Date: Fri, 30 Jan 2026 16:17:34 +0000 Subject: [PATCH] fix(backend): use discriminator for credential matching in run_block When executing blocks via the chat interface (run_block tool), the credential matching logic was not using the discriminator_mapping to determine the correct provider based on the selected model value. For example, when a user ran AITextGeneratorBlock with model='gpt-4o-mini': - The code matched against ALL supported providers (ollama, openai, anthropic...) - Ollama credentials were always first in the list (since they don't require API key) - So the FAKE_API_KEY from Ollama was used instead of the actual OpenAI key This fix: - Passes input_data to _check_block_credentials - Uses field_info.discriminate() to narrow to the correct provider - Matches credentials only for the discriminated provider Fixes credential mismatch errors like: 'Error code: 401 - invalid_api_key: FAKE_API_KEY' --- .../api/features/chat/tools/run_block.py | 36 ++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/autogpt_platform/backend/backend/api/features/chat/tools/run_block.py b/autogpt_platform/backend/backend/api/features/chat/tools/run_block.py index 3f57236564..2cc61fa3db 100644 --- a/autogpt_platform/backend/backend/api/features/chat/tools/run_block.py +++ b/autogpt_platform/backend/backend/api/features/chat/tools/run_block.py @@ -73,15 +73,22 @@ class RunBlockTool(BaseTool): self, user_id: str, block: Any, + input_data: dict[str, Any] | None = None, ) -> tuple[dict[str, CredentialsMetaInput], list[CredentialsMetaInput]]: """ Check if user has required credentials for a block. + Args: + user_id: User ID + block: Block to check credentials for + input_data: Input data for the block (used to determine provider via discriminator) + Returns: tuple[matched_credentials, missing_credentials] """ matched_credentials: dict[str, CredentialsMetaInput] = {} missing_credentials: list[CredentialsMetaInput] = [] + input_data = input_data or {} # Get credential field info from block's input schema credentials_fields_info = block.input_schema.get_credentials_fields_info() @@ -94,14 +101,27 @@ class RunBlockTool(BaseTool): available_creds = await creds_manager.store.get_all_creds(user_id) for field_name, field_info in credentials_fields_info.items(): - # field_info.provider is a frozenset of acceptable providers - # field_info.supported_types is a frozenset of acceptable types + # Use discriminator to narrow down provider if available + # This ensures we match credentials for the correct provider based on + # the actual model/value selected (e.g., gpt-4o-mini -> openai) + effective_field_info = field_info + if field_info.discriminator and field_info.discriminator_mapping: + discriminator_value = input_data.get(field_info.discriminator) + if discriminator_value and discriminator_value in field_info.discriminator_mapping: + effective_field_info = field_info.discriminate(discriminator_value) + logger.debug( + f"Discriminated provider for {field_name}: " + f"{discriminator_value} -> {effective_field_info.provider}" + ) + + # effective_field_info.provider is a frozenset of acceptable providers + # effective_field_info.supported_types is a frozenset of acceptable types matching_cred = next( ( cred for cred in available_creds - if cred.provider in field_info.provider - and cred.type in field_info.supported_types + if cred.provider in effective_field_info.provider + and cred.type in effective_field_info.supported_types ), None, ) @@ -115,8 +135,8 @@ class RunBlockTool(BaseTool): ) else: # Create a placeholder for the missing credential - provider = next(iter(field_info.provider), "unknown") - cred_type = next(iter(field_info.supported_types), "api_key") + provider = next(iter(effective_field_info.provider), "unknown") + cred_type = next(iter(effective_field_info.supported_types), "api_key") missing_credentials.append( CredentialsMetaInput( id=field_name, @@ -184,10 +204,10 @@ class RunBlockTool(BaseTool): logger.info(f"Executing block {block.name} ({block_id}) for user {user_id}") - # Check credentials + # Check credentials (pass input_data to use discriminator for provider selection) creds_manager = IntegrationCredentialsManager() matched_credentials, missing_credentials = await self._check_block_credentials( - user_id, block + user_id, block, input_data ) if missing_credentials: