fix(examples): keep the Vercel AI SDK route on the team topology (#589)

Anyone following this example got a blank article back. The route read
the team's answer from agentResults.get('coordinator'), but a goal this
short is routed to the single-agent path, where the orchestrator
publishes the answer under the winning agent's own name instead. The
lookup returned undefined, the ?? '' fallback swallowed it, and the app
streamed an empty Team Output section.

- Pass an explicit mode: 'team' so the demo runs the topology this
  example teaches. Explicit mode outranks the router.
- Read the terminal agent as a fallback so the route returns the article
  under either topology.
- Check success before streaming. A plan validation failure leaves the
  coordinator's unparsed plan under the 'coordinator' key, so testing
  for an empty string would stream planning scratch as the article.
- Raise maxDuration to 360 and say "a few minutes" in the placeholder,
  to match the measured team path: seven runs on deepseek-v4-flash took
  137 to 311 seconds, median 217, from one machine.
This commit is contained in:
Jack Chen authored and GitHub committed 2026-09-07 18:04:52 +08:00
1 parent 71ac67a42f
commit f62c7edbc3
2 files changed
+24 -3

No files matched your search

@@ -3,7 +3,7 @@ import { createOpenAICompatible } from '@ai-sdk/openai-compatible'
import { OpenMultiAgent } from '@open-multi-agent/core'
import type { AgentConfig } from '@open-multi-agent/core'
export const maxDuration = 120
export const maxDuration = 360
// --- DeepSeek via OpenAI-compatible API ---
const DEEPSEEK_BASE_URL = 'https://api.deepseek.com'
@@ -69,9 +69,30 @@ export async function POST(req: Request) {
const teamResult = await orchestrator.runTeam(
team,
`Research and write an article about: ${lastText}`,
// Execution routing sends a short goal down the single-agent path. An
// explicit mode outranks the router, so this keeps the demo on the
// researcher + writer team topology.
{ mode: 'team' },
)
const teamOutput = teamResult.agentResults.get('coordinator')?.output ?? ''
// The team path publishes the synthesized answer under 'coordinator'; the
// single-agent path publishes it under the winning agent's own name. Read
// both so this route survives whichever topology runs.
const teamOutput =
teamResult.agentResults.get('coordinator')?.output
?? teamResult.agentResults.get('writer')?.output
?? ''
// A failed run still leaves the coordinator's unparsed plan under
// 'coordinator', so check `success` rather than testing for an empty string.
if (!teamResult.success || teamOutput === '') {
return new Response(
`The agent team did not produce an article: ${
teamResult.errorInfo?.message ?? teamResult.status?.code ?? 'unknown error'
}`,
{ status: 500 },
)
}
// --- Phase 2: Stream result via Vercel AI SDK ---
const result = streamText({
@@ -50,7 +50,7 @@ export default function Home() {
{isLoading && status === 'submitted' && (
<div style={{ color: '#888', fontSize: 14, padding: '8px 0' }}>
Agents are collaborating &mdash; this may take a minute...
Agents are collaborating &mdash; this takes a few minutes...
</div>
)}