Skip to content

fix(azure): add azure-anthropic support to router, evaluator, copilot, and tokenization#3157

Closed
waleedlatif1 wants to merge 3 commits intostagingfrom
fix/azure
Closed

fix(azure): add azure-anthropic support to router, evaluator, copilot, and tokenization#3157
waleedlatif1 wants to merge 3 commits intostagingfrom
fix/azure

Conversation

@waleedlatif1
Copy link
Collaborator

Summary

  • Add azure-anthropic to getProviderCredentialSubBlocks() so router and evaluator blocks show the Azure endpoint field
  • Forward azureEndpoint in router and evaluator handlers for azure-anthropic provider
  • Add azure-anthropic to copilot valid providers, types, and chat route
  • Add azure-anthropic to tokenization constants and estimator (uses Anthropic tokenizer)

Type of Change

  • Bug fix

Testing

Tested manually

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel
Copy link

vercel bot commented Feb 6, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Feb 6, 2026 8:49pm

Request Review

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 6, 2026

Greptile Overview

Greptile Summary

  • Adds azure-anthropic support across Copilot (chat route env config, provider allowlist, request types) and tokenization (config + estimator maps).
  • Updates block credential UI to show an Azure endpoint field for both Azure OpenAI and Azure Anthropic models.
  • Extends router and evaluator handlers to forward azureEndpoint for azure-anthropic provider requests (and azureApiVersion only for azure-openai).
  • Refactors the Azure OpenAI provider implementation to support Responses API vs Chat Completions based on apiVersion, including streaming + tool-call loops; currently contains a runtime-breaking scoping bug that must be fixed before merge.

Confidence Score: 2/5

  • Not safe to merge as-is due to a definite runtime error in the Azure OpenAI provider.
  • Most azure-anthropic wiring changes are straightforward, but the refactor in apps/sim/providers/azure-openai/index.ts introduces a ReferenceError (assignment to hasUsedForcedTool before initialization) that will break Azure OpenAI tool-call execution paths at runtime.
  • apps/sim/providers/azure-openai/index.ts

Important Files Changed

Filename Overview
apps/sim/providers/azure-openai/index.ts Adds Responses API support and broad refactor of Azure OpenAI provider streaming/tool execution; introduces a definite runtime ReferenceError due to writing to hasUsedForcedTool before its declaration.
apps/sim/app/api/copilot/chat/route.ts Adds env-based azure-anthropic provider config so Copilot chat can route through Azure-hosted Anthropic; change is localized to provider selection.
apps/sim/blocks/utils.ts Updates provider credential subblocks to show a generic Azure endpoint for both azure-openai and azure-anthropic models; only UI metadata/conditions changed.
apps/sim/executor/handlers/evaluator/evaluator-handler.ts Forwards azureEndpoint for azure-anthropic in evaluator provider requests (keeps apiVersion only for azure-openai).
apps/sim/executor/handlers/router/router-handler.ts Forwards azureEndpoint for azure-anthropic in both legacy router and router_v2 requests (keeps apiVersion only for azure-openai).
apps/sim/lib/copilot/config.ts Adds azure-anthropic to Copilot provider ID allowlist used for env validation.
apps/sim/lib/copilot/types.ts Extends CopilotProviderConfig union with an azure-anthropic variant and excludes it from the generic ProviderId branch.
apps/sim/lib/tokenization/constants.ts Adds tokenization config entry for azure-anthropic mirroring Anthropic defaults.
apps/sim/lib/tokenization/estimators.ts Routes azure-anthropic token estimation to the Anthropic heuristic estimator.

Sequence Diagram

sequenceDiagram
  autonumber
  participant UI as Block UI (Router/Evaluator)
  participant EX as Router/Evaluator Handler
  participant API as /api/providers
  participant AZ as azure-openai provider
  participant AOAI as Azure OpenAI SDK
  participant TOOLS as Tool Registry

  UI->>EX: Execute block with inputs (model, apiKey, azureEndpoint, azureApiVersion?)
  EX->>EX: providerId = getProviderFromModel(model)
  alt providerId == azure-openai
    EX->>API: POST providerRequest + azureEndpoint + azureApiVersion
  else providerId == azure-anthropic
    EX->>API: POST providerRequest + azureEndpoint
  else other provider
    EX->>API: POST providerRequest
  end

  API->>AZ: dispatch executeRequest(request)
  AZ->>AZ: azureEndpoint/apiVersion from request or env
  AZ->>AOAI: new AzureOpenAI({endpoint, apiVersion, apiKey})

  alt apiVersion startsWith 2025-
    AZ->>AOAI: responses.create(payload)
    loop tool iterations
      AOAI-->>AZ: response output (function_call items)
      AZ->>TOOLS: executeTool(name, args)
      TOOLS-->>AZ: tool result
      AZ->>AOAI: responses.create(nextPayload with function_call_output)
    end
    alt stream
      AZ->>AOAI: responses.create(stream:true)
      AOAI-->>AZ: streaming deltas
    end
  else 2024- or earlier
    AZ->>AOAI: chat.completions.create(payload)
    loop tool iterations
      AOAI-->>AZ: tool_calls
      AZ->>TOOLS: executeTool(name, args)
      TOOLS-->>AZ: tool result
      AZ->>AOAI: chat.completions.create(nextPayload)
    end
    alt stream
      AZ->>AOAI: chat.completions.create(stream:true)
      AOAI-->>AZ: streaming deltas
    end
  end

  AZ-->>API: ProviderResponse or StreamingExecution
  API-->>EX: result
  EX-->>UI: block output
Loading

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

9 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines +798 to +801
const checkForForcedToolUsage = (
response: any,
toolChoice: string | { type: string; function?: { name: string }; name?: string; any?: any }
) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Undeclared variable usage

checkForForcedToolUsage assigns to hasUsedForcedTool, but hasUsedForcedTool is declared later (let hasUsedForcedTool = false) inside the same try block. This will throw a ReferenceError: Cannot access 'hasUsedForcedTool' before initialization on the first call to checkForForcedToolUsage(...), breaking Azure OpenAI tool-call flows.

Fix by declaring hasUsedForcedTool (and any other captured vars) before defining/using checkForForcedToolUsage (or have the helper return the updated state instead of mutating an outer binding).

Copy link

@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 4 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

prompt: currentResponse.usage?.input_tokens || 0,
completion: currentResponse.usage?.output_tokens || 0,
total:
(currentResponse.usage?.input_tokens || 0) + (currentResponse.usage?.output_tokens || 0),
Copy link

Choose a reason for hiding this comment

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

Token fields use wrong property names causing cost calculation to fail

High Severity

The tokens object uses prompt and completion as property names, but the ProviderResponse type and its consumers expect input and output. The cost calculation in executeProviderRequest destructures { input: promptTokens, output: completionTokens } from response.tokens, so the new property names result in both values defaulting to 0, causing incorrect cost calculations.

Additional Locations (1)

Fix in Cursor Fix in Web

const toolCalls: any[] = []
const toolResults: any[] = []
let iterationCount = 0
const MAX_ITERATIONS = 10
Copy link

Choose a reason for hiding this comment

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

MAX_ITERATIONS reduced from project standard of 20 to 10

Medium Severity

The local MAX_ITERATIONS = 10 constant is inconsistent with the project-wide MAX_TOOL_ITERATIONS = 20 used by other providers like Anthropic and Bedrock. This could prematurely cut off tool call iterations for Azure OpenAI requests, causing unexpected behavior when workflows require more than 10 iterations.

Additional Locations (1)

Fix in Cursor Fix in Web

role: 'tool',
tool_call_id: toolCall.id,
content: JSON.stringify(resultContent),
})
Copy link

Choose a reason for hiding this comment

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

Tool handling creates incorrect message structure for multi-tool responses

High Severity

When multiple tool calls are returned in a single response, the code creates a separate assistant message for each tool call inside the loop instead of one assistant message containing all tool calls. The OpenAI Chat Completions API expects a single assistant message with all tool_calls followed by individual tool result messages. This incorrect message structure will likely cause API errors or incorrect behavior when multiple tools are called simultaneously.

Fix in Cursor Fix in Web

const remainingTools = forcedTools.filter((tool) => !usedForcedTools.includes(tool))

if (remainingTools.length > 0) {
nextPayload.tool_choice = {
Copy link

Choose a reason for hiding this comment

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

Responses API path missing forced tool tracking for iterations

Medium Severity

The Responses API path (2025+ API versions) always sets tool_choice: 'auto' for subsequent requests, completely ignoring any remaining forced tools. Unlike the Chat Completions path which tracks usedForcedTools and hasUsedForcedTool and properly enforces remaining forced tools on subsequent iterations (lines 943-956), the Responses API path has no such tracking. Users configuring multiple tools with usageControl: 'force' will only have the initial tool_choice enforced; subsequent iterations will not force the remaining tools.

Fix in Cursor Fix in Web

@waleedlatif1 waleedlatif1 deleted the fix/azure branch February 6, 2026 22:41
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