Skip to main content

Known differences from the TypeScript AI SDK

The Go AI SDK tracks the TypeScript AI SDK (ai@7.0.127 as of v0.5.0) closely, but a few areas are intentionally different, either because the Go runtime has no equivalent primitive or because a decision was made to diverge. This page is the reference for both.

StreamObject is not lazy​

StreamObject is deprecated in both SDKs. In TypeScript, streamObject returns lazy streams immediately, before the model call completes. In Go, StreamObject returns only after the stream is fully consumed, and reports progress through OnChunk as the partial object is refined.

For incremental partial objects or array elements, use StreamText with Output (PartialOutput / ElementStream) instead — this is also what the TypeScript SDK recommends going forward.

// Not recommended: StreamObject blocks until the stream finishes.
result, err := ai.StreamObject(ctx, ai.StreamObjectOptions{
Model: model,
Prompt: "Generate a recipe",
Schema: recipeSchema,
OnChunk: func(partial interface{}) {
// Called incrementally as the partial object is refined.
},
})

// Recommended: StreamText + Output returns immediately and lets you read
// the incrementally parsed value as chunks arrive, matching TS's lazy
// streamObject.
result, err := ai.StreamText(ctx, ai.StreamTextOptions{
Model: model,
Prompt: "Generate a recipe",
Output: ai.ObjectOutput[Recipe](ai.ObjectOutputOptions{Schema: recipeSchema}),
})
for chunk := range result.Chunks() {
if chunk.Type == provider.ChunkTypeText {
partial := result.PartialOutput() // latest parsed partial value
_ = partial
}
}

Video generation webhook suspension in workflows​

TypeScript's experimental_generateVideo can durably suspend a Vercel Workflow DevKit run until a provider webhook fires, resuming the workflow from durable storage when the video finishes. This depends on the Node-only Workflow DevKit runtime and has no Go equivalent.

In Go, video generation polls until the job is done (GenerateVideo), or you drive the job yourself with ai.ExperimentalStartVideo / ai.ExperimentalGetVideoStatus, which support both polling and webhook completion (fal and Replicate) outside of a workflow.

Vercel Sandbox: no OIDC token refresh loop​

pkg/harness/sandbox/vercel (the Go port of @vercel/sandbox's harness provider) does not run a background @vercel/oidc token refresh loop. VERCEL_OIDC_TOKEN is re-read from the environment on each call instead; explicit Token / TeamID / ProjectID credentials also work and bypass OIDC entirely.

Code-mode: never-settling promises and in-flight limits​

pkg/codemode runs model-written JavaScript in a QuickJS-on-WebAssembly sandbox (wazero). Concurrent tool calls that need approval (for example inside one Promise.all) are batched into a single interrupt, as in TS. Two details differ:

  • A promise that never settles and has no pending tool call fails fast with a ProtocolError. TypeScript waits for the execution timeout.
  • MaxInFlightBridgeRequests counts the calls in an approval batch.

Features that are TypeScript-only (not ported)​

  • OpenAI Live over WebRTC — the browser transport for OpenAI's realtime API. The Go SDK only implements the server-side WebSocket transport (gpt-live-1 via ai.ConnectRealtime), which covers server-side and backend use cases; WebRTC is a browser-only transport with no Go runtime equivalent.
  • @ai-sdk/harness-cline and @ai-sdk/harness-pi — these harness adapters run vendor Node SDKs in-process (they embed a Node.js runtime and the vendor's own TypeScript SDK). There is no Go equivalent; use the TypeScript SDK for Cline or Pi harness integrations.
  • DeepSeek batch API / extra Files methods — TS's @ai-sdk/deepseek does not implement these either, so this is parity, not a gap; the existing DeepSeek file support already matches TS.

Streaming pattern: Next() instead of io.Reader​

This is a longstanding, deliberate Go-idiom difference (not new in v0.5.0): provider.TextStream exposes Next() / Err() / Close(), not an io.Reader. See the Streaming guide for the rationale.

See Also​