Overview
First off, thank you for creating agentswarm! It's a powerful library for building multi-agent systems.
I am building a Next.js application using agentswarm on the backend and the Vercel AI SDK's useChat hook on the frontend. While the library is incredibly capable, I've run into an issue regarding the direct integration between agentswarm's streamText output and the data stream expected by useChat, especially when using models that produce reasoning chunks (like Google's Gemini 2.5 Pro).
The core problem is that swarm.streamText() returns a custom result object, and its fullStream of ExtendedTextStreamPart objects is not directly compatible with the Vercel AI SDK's useChat hook without a manual transformation layer.
My Workaround and The Problem
To make this work, I've implemented a custom stream transformer (toDataStreamInternal) that manually converts each ExtendedTextStreamPart from agentswarm into the DataStreamString format that the Vercel AI SDK's createDataStreamResponse helper expects.
Here is my current implementation:
app/api/chat/route.ts
import { createDataStreamResponse } from 'ai'; // Vercel AI SDK Helper
// ... other imports for agentswarm
// This is my handler for POST requests
export async function POST(req: Request) {
try {
const { messages } = await req.json();
// Use the streamText method from the swarm
const result = swarm.streamText({
messages,
experimental_toolCallStreaming: true,
});
// Pipe the raw output from agentswarm through our new transformer
const transformedStream = toDataStreamInternal(result.fullStream, {
getErrorMessage: (error: unknown) => {
console.error('[getErrorMessage] error:', error);
return 'An error occurred.';
},
sendReasoning: true, // I want to process reasoning chunks
sendUsage: true,
sendSources: false,
experimental_sendFinish: true,
});
// Use the standard Vercel AI SDK helper to create the response
return createDataStreamResponse({
status: 200,
statusText: 'OK',
execute: dataStream => {
dataStream.merge(transformedStream);
},
onError: (error: unknown) => {
console.error('[onError] error:', error);
return 'An error occurred.';
},
});
} catch (error) {
console.error('Error in AI Agent streaming endpoint:', error);
return Response.json({ message: 'Internal server error' }, { status: 500 });
}
}
// Custom transformer to bridge agentswarm's stream with Vercel's stream protocol
function toDataStreamInternal(
fullStream: ReadableStream<any>,
{
// ... options
}: {
// ... options
}
): ReadableStream<DataStreamString> {
return fullStream.pipeThrough(
new TransformStream<ExtendedTextStreamPart<any>, DataStreamString>({
transform: async (chunk, controller) => {
const chunkType = chunk.type;
// This switch handles all the different chunk types from agentswarm
switch (chunkType) {
case 'text-delta': {
controller.enqueue(formatDataStreamPart('text', chunk.textDelta));
break;
}
// This case specifically handles the reasoning chunk
case 'reasoning': {
if (sendReasoning) {
controller.enqueue(
formatDataStreamPart('reasoning', chunk.textDelta)
);
}
break;
}
// ... other cases for tool calls, finish, etc.
case 'tool-call': {
controller.enqueue(formatDataStreamPart('tool_call', { /*...*/ }));
break;
}
// ...
default: {
const exhaustiveCheck: never = chunkType;
throw new Error(`Unknown chunk type: ${exhaustiveCheck}`);
}
}
},
})
);
}
This workaround functions correctly for standard text and tool calls.
However, when using a model that produces reasoning chunks (e.g., Gemini 2.5 Pro), the stream fails with the following error logged from the onError callback of createDataStreamResponse:
[onError] error [Error: Unhandled chunk type: reasoning]
Root Cause Analysis
The error message Unhandled chunk type: reasoning strongly suggests that the issue lies within the Vercel AI SDK's server-side helpers (createDataStreamResponse and its internal stream merging logic).
My custom transformer, toDataStreamInternal, correctly identifies the { type: 'reasoning', ... } chunk from agentswarm's fullStream and attempts to enqueue it as a 'reasoning' data part for the client. However, it appears the standard Vercel AI SDK server helpers do not natively recognize or know how to process this 'reasoning' data part type, causing them to throw the "Unhandled chunk type" error.
This means that while my transformer is doing its job, the underlying Vercel helper can't handle the data it's being given.
Suggested Solution & Feature Request
Manually maintaining a transformer like the one above is complex and brittle. As agentswarm and the Vercel AI SDK evolve, this transformer will need constant updates to handle new chunk types and potential breaking changes.
The ideal solution would be for agentswarm to provide a native helper function that correctly transforms its fullStream into a Response object that is fully compatible with useChat.
This would significantly improve the developer experience and make the library more robust. A hypothetical helper could look something like this:
// Desired API
export async function POST(req: Request) {
const { messages } = await req.json();
const swarmResult = swarm.streamText({
messages,
experimental_toolCallStreaming: true,
});
// This helper would handle all the transformation logic internally
return swarmResult.toDataStreamResponse({
sendReasoning: true, // allow options to be passed
});
}
This is similar to how the base Vercel AI SDK's streamText works and would make agentswarm a seamless drop-in for developers already familiar with that ecosystem.
Thank you for considering this feature request. I believe it would make an already great library even better.
Overview
First off, thank you for creating
agentswarm! It's a powerful library for building multi-agent systems.I am building a Next.js application using
agentswarmon the backend and the Vercel AI SDK'suseChathook on the frontend. While the library is incredibly capable, I've run into an issue regarding the direct integration betweenagentswarm'sstreamTextoutput and the data stream expected byuseChat, especially when using models that produce reasoning chunks (like Google's Gemini 2.5 Pro).The core problem is that
swarm.streamText()returns a custom result object, and itsfullStreamofExtendedTextStreamPartobjects is not directly compatible with the Vercel AI SDK'suseChathook without a manual transformation layer.My Workaround and The Problem
To make this work, I've implemented a custom stream transformer (
toDataStreamInternal) that manually converts eachExtendedTextStreamPartfromagentswarminto theDataStreamStringformat that the Vercel AI SDK'screateDataStreamResponsehelper expects.Here is my current implementation:
app/api/chat/route.tsThis workaround functions correctly for standard text and tool calls.
However, when using a model that produces
reasoningchunks (e.g., Gemini 2.5 Pro), the stream fails with the following error logged from theonErrorcallback ofcreateDataStreamResponse:Root Cause Analysis
The error message
Unhandled chunk type: reasoningstrongly suggests that the issue lies within the Vercel AI SDK's server-side helpers (createDataStreamResponseand its internal stream merging logic).My custom transformer,
toDataStreamInternal, correctly identifies the{ type: 'reasoning', ... }chunk fromagentswarm'sfullStreamand attempts to enqueue it as a'reasoning'data part for the client. However, it appears the standard Vercel AI SDK server helpers do not natively recognize or know how to process this'reasoning'data part type, causing them to throw the "Unhandled chunk type" error.This means that while my transformer is doing its job, the underlying Vercel helper can't handle the data it's being given.
Suggested Solution & Feature Request
Manually maintaining a transformer like the one above is complex and brittle. As
agentswarmand the Vercel AI SDK evolve, this transformer will need constant updates to handle new chunk types and potential breaking changes.The ideal solution would be for
agentswarmto provide a native helper function that correctly transforms itsfullStreaminto aResponseobject that is fully compatible withuseChat.This would significantly improve the developer experience and make the library more robust. A hypothetical helper could look something like this:
This is similar to how the base Vercel AI SDK's
streamTextworks and would makeagentswarma seamless drop-in for developers already familiar with that ecosystem.Thank you for considering this feature request. I believe it would make an already great library even better.