From 7e2750f83fb9406853d2d297a714ba9afcd0961b Mon Sep 17 00:00:00 2001 From: Abhishek Date: Mon, 6 Jul 2026 22:58:53 +0530 Subject: [PATCH] fix: forward billing-v2 protocol on textchat KB retrieval and node summaries (#503) Two call sites dropped the MPS billing-v2 protocol, so orgs on model config v2 got 400 "Service Key uses billing v2" from MPS: - text_chat_runner built PipecatEngine without embeddings_provider (extracted but never passed), so knowledge-base retrieval fell through to the plain OpenAI-compatible client instead of DograhEmbeddingService and sent no correlation_id/mps_billing_version metadata. Also pass endpoint/api_version for Azure BYOK parity with run_pipeline. - node_summary built its QA LLM without the run's correlation id, unlike its sibling call in qa/analysis.py. Co-authored-by: Claude Fable 5 --- api/services/workflow/qa/node_summary.py | 11 ++++++++++- api/services/workflow/text_chat_runner.py | 8 ++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/api/services/workflow/qa/node_summary.py b/api/services/workflow/qa/node_summary.py index aaeb7d30..c474abe8 100644 --- a/api/services/workflow/qa/node_summary.py +++ b/api/services/workflow/qa/node_summary.py @@ -7,6 +7,7 @@ from pipecat.processors.aggregators.llm_context import LLMContext from api.db import db_client from api.db.models import WorkflowRunModel +from api.services.managed_model_services import get_mps_correlation_id from api.services.pipecat.service_factory import create_llm_service_from_provider from api.services.workflow.dto import NodeType, QANodeData from api.services.workflow.qa.llm_config import resolve_llm_config @@ -75,7 +76,15 @@ async def ensure_node_summaries( logger.warning("No API key for node summary generation, skipping") return existing_summaries - llm = create_llm_service_from_provider(provider, model, api_key, **service_kwargs) + # Reuse the run's MPS correlation id (minted at run start, persisted on + # initial_context) so managed-model-services calls carry billing-v2 + # markers — orgs on billing v2 reject managed calls that lack them. + mps_correlation_id = get_mps_correlation_id( + getattr(workflow_run, "initial_context", None) + ) + llm = create_llm_service_from_provider( + provider, model, api_key, correlation_id=mps_correlation_id, **service_kwargs + ) updated_summaries = dict(existing_summaries) diff --git a/api/services/workflow/text_chat_runner.py b/api/services/workflow/text_chat_runner.py index 662943e6..7fa31d4a 100644 --- a/api/services/workflow/text_chat_runner.py +++ b/api/services/workflow/text_chat_runner.py @@ -532,6 +532,9 @@ async def execute_text_chat_pending_turn( embeddings_api_key = None embeddings_model = None embeddings_base_url = None + embeddings_provider = None + embeddings_endpoint = None + embeddings_api_version = None if user_config.embeddings: from api.services.configuration.ai_model_configuration import ( apply_managed_embeddings_base_url, @@ -544,6 +547,8 @@ async def execute_text_chat_pending_turn( provider=embeddings_provider, base_url=getattr(user_config.embeddings, "base_url", None), ) + embeddings_endpoint = getattr(user_config.embeddings, "endpoint", None) + embeddings_api_version = getattr(user_config.embeddings, "api_version", None) has_recordings = await db_client.has_active_recordings(workflow.organization_id) context_compaction_enabled = (workflow.workflow_configurations or {}).get( @@ -560,6 +565,9 @@ async def execute_text_chat_pending_turn( embeddings_api_key=embeddings_api_key, embeddings_model=embeddings_model, embeddings_base_url=embeddings_base_url, + embeddings_provider=embeddings_provider, + embeddings_endpoint=embeddings_endpoint, + embeddings_api_version=embeddings_api_version, has_recordings=has_recordings, context_compaction_enabled=context_compaction_enabled, )