Describe the Bug
When using Anthropic Claude models via the Orchestration API in streaming mode, OrchestrationStreamChunkResponse.getDeltaContent() returns undefined (treated as '') for every chunk, causing handleLLMNewToken to fire with empty strings. No text is ever surfaced to the LangChain streaming caller.
Root Cause
ChatDelta.content is typed as string in the generated schema (packages/orchestration/src/client/api/schema/chat-delta.ts):
export type ChatDelta = {
content: string;
// ...
};
getDeltaContent() returns it directly:
getDeltaContent(choiceIndex = 0): string | undefined {
return this.findChoiceByIndex(choiceIndex)?.delta.content;
}
However, Anthropic Claude models return delta.content as Array<{type: string, text: string}> (content blocks) in streaming chunks — not a plain string. The TypeScript type is wrong, and the method has no handling for the array case. The result is that every streaming chunk from a Claude model is silently treated as an empty token.
Steps to Reproduce
- Configure
OrchestrationClient with a Claude model (e.g. claude-3-5-sonnet)
- Enable streaming (
{ streaming: true } in langchainOptions)
- Call
streamEvents({ version: "v3" }) or iterate _streamResponseChunks
- Observe that all
handleLLMNewToken callbacks fire with content = ""
Expected Behavior
getDeltaContent() should extract and concatenate text from content-block arrays when delta.content is an array:
getDeltaContent(choiceIndex = 0): string | undefined {
const content = this.findChoiceByIndex(choiceIndex)?.delta.content;
if (Array.isArray(content)) {
return content
.filter(b => b.type === 'text')
.map(b => b.text ?? '')
.join('');
}
return content;
}
The ChatDelta type should also be widened:
export type ChatDelta = {
content: string | Array<{ type: string; text?: string; [key: string]: any }>;
// ...
};
Actual Behavior
Every streaming chunk from Claude fires handleLLMNewToken(""). The full response is only available after stream completion via the non-streaming path.
Confirmed Affected Version
@sap-ai-sdk/langchain 2.11.0 (latest at time of filing)
Workaround
Downstream consumers can subclass OrchestrationClient and override _streamResponseChunks to extract text manually from chunk._data:
const rawContent =
chunk._data?.intermediate_results?.llm?.choices?.[0]?.delta?.content ??
chunk._data?.final_result?.choices?.[0]?.delta?.content;
const text = Array.isArray(rawContent)
? rawContent.filter(b => b.type === 'text').map(b => b.text ?? '').join('')
: '';
This is the workaround we currently carry in our application. We'd like to see it fixed natively in the SDK.
Describe the Bug
When using Anthropic Claude models via the Orchestration API in streaming mode,
OrchestrationStreamChunkResponse.getDeltaContent()returnsundefined(treated as'') for every chunk, causinghandleLLMNewTokento fire with empty strings. No text is ever surfaced to the LangChain streaming caller.Root Cause
ChatDelta.contentis typed asstringin the generated schema (packages/orchestration/src/client/api/schema/chat-delta.ts):getDeltaContent()returns it directly:However, Anthropic Claude models return
delta.contentasArray<{type: string, text: string}>(content blocks) in streaming chunks — not a plain string. The TypeScript type is wrong, and the method has no handling for the array case. The result is that every streaming chunk from a Claude model is silently treated as an empty token.Steps to Reproduce
OrchestrationClientwith a Claude model (e.g.claude-3-5-sonnet){ streaming: true }inlangchainOptions)streamEvents({ version: "v3" })or iterate_streamResponseChunkshandleLLMNewTokencallbacks fire withcontent = ""Expected Behavior
getDeltaContent()should extract and concatenate text from content-block arrays whendelta.contentis an array:The
ChatDeltatype should also be widened:Actual Behavior
Every streaming chunk from Claude fires
handleLLMNewToken(""). The full response is only available after stream completion via the non-streaming path.Confirmed Affected Version
@sap-ai-sdk/langchain2.11.0 (latest at time of filing)Workaround
Downstream consumers can subclass
OrchestrationClientand override_streamResponseChunksto extract text manually fromchunk._data:This is the workaround we currently carry in our application. We'd like to see it fixed natively in the SDK.