<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Koenig Academy</title>
    <description>The latest articles on DEV Community by Koenig Academy (@koenig_academy_9a8f35ff4b).</description>
    <link>https://dev.to/koenig_academy_9a8f35ff4b</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3979379%2F3296054e-833a-472f-9954-4fd3aefdc987.png</url>
      <title>DEV Community: Koenig Academy</title>
      <link>https://dev.to/koenig_academy_9a8f35ff4b</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/koenig_academy_9a8f35ff4b"/>
    <language>en</language>
    <item>
      <title>Vercel AI SDK 6: Production Patterns for Autonomous Loops</title>
      <dc:creator>Koenig Academy</dc:creator>
      <pubDate>Thu, 09 Jul 2026 07:20:35 +0000</pubDate>
      <link>https://dev.to/koenig_academy_9a8f35ff4b/vercel-ai-sdk-6-production-patterns-for-autonomous-loops-2n6f</link>
      <guid>https://dev.to/koenig_academy_9a8f35ff4b/vercel-ai-sdk-6-production-patterns-for-autonomous-loops-2n6f</guid>
      <description>&lt;h1&gt;
  
  
  Build Vercel AI SDK 6 Loops as Bounded Systems, Not Magic Agents
&lt;/h1&gt;

&lt;p&gt;Vercel AI SDK 6 gives TypeScript teams a practical way to build autonomous loops with &lt;code&gt;ToolLoopAgent&lt;/code&gt;, typed tools, streaming output, MCP tool adapters, and OpenTelemetry hooks. The direct answer: use &lt;code&gt;ToolLoopAgent&lt;/code&gt; when the model must choose tools, observe results, and continue for multiple steps; use plain &lt;code&gt;generateText&lt;/code&gt; or &lt;code&gt;streamText&lt;/code&gt; when you only need one model call. Vercel's own AI SDK 6 announcement says the release introduces the &lt;code&gt;Agent&lt;/code&gt; interface and &lt;code&gt;ToolLoopAgent&lt;/code&gt; to simplify reusable multi-step behavior, with fewer expected breaking changes than AI SDK 5 [1].&lt;/p&gt;

&lt;p&gt;The non-obvious part is that AI SDK 6 does not make production agents safe by being "agentic." It makes them safer when you keep every loop step bounded, typed, observable, and approvable. The loop is still your runtime, your tools, your error surface, and your bill. That is why the best AI SDK 6 production architecture looks less like a chatbot demo and more like a small agent harness with step limits, schema checks, telemetry, and explicit human gates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use ToolLoopAgent when the task needs repeated tool feedback
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;ToolLoopAgent&lt;/code&gt; is the right primitive when the model needs to call a tool, inspect the result, and decide what to do next. The AI SDK agents documentation describes agents as LLMs that use tools in a loop, and says &lt;code&gt;ToolLoopAgent&lt;/code&gt; handles the loop, context management, and stopping conditions [6]. That matters because the risky part of a production loop is not the first model call; it is what happens after the third failed tool input, the seventh retry, or the accidental expensive branch.&lt;/p&gt;

&lt;p&gt;The migration guide is also a signal about the intended direction of the SDK. AI SDK 6 renames &lt;code&gt;Experimental_Agent&lt;/code&gt; to &lt;code&gt;ToolLoopAgent&lt;/code&gt;, changes &lt;code&gt;system&lt;/code&gt; to &lt;code&gt;instructions&lt;/code&gt;, and gives the default loop a &lt;code&gt;stepCountIs(20)&lt;/code&gt; safety cap [2]. Treat that default as a ceiling, not a recommendation. For customer support, data cleanup, coding-assistant, and workflow agents, start with a lower cap such as 4 to 8 steps and increase only after reviewing traces.&lt;/p&gt;

&lt;p&gt;Keep one-shot jobs out of the loop. Classification, summarization, extraction, and simple structured output usually belong in &lt;code&gt;generateText&lt;/code&gt; or &lt;code&gt;streamText&lt;/code&gt; with an output schema, not in an autonomous agent. The generating structured data docs say AI SDK 6 uses &lt;code&gt;generateText&lt;/code&gt; with &lt;code&gt;Output.object({ schema })&lt;/code&gt; for structured objects [5]. That makes simple deterministic workloads easier to test and cheaper to operate.&lt;/p&gt;

&lt;p&gt;For readers coming from the earlier &lt;a href="https://academy.kspl.tech/blog/2026-04-30-vercel-ai-sdk-6-vs-claude-agent-sdk" rel="noopener noreferrer"&gt;Vercel AI SDK 6 vs Claude Agent SDK&lt;/a&gt; comparison, this is the same architectural rule in a narrower setting: choose the runtime boundary first. Vercel AI SDK owns the orchestration helper, but you still own the execution environment for your tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Define tools as contracts, not callbacks
&lt;/h2&gt;

&lt;p&gt;AI SDK tools should be treated as public contracts between a probabilistic planner and deterministic code. The tools documentation defines a tool with a description, input schema, and optional execute function [3]. In production, the schema is not decorative. It is the first line of defense against malformed inputs, runaway calls, and ambiguous planner behavior.&lt;/p&gt;

&lt;p&gt;Use Zod, Valibot, or JSON Schema to express exactly what your tool accepts. Put constraints in the schema where possible, not only in prose. A &lt;code&gt;refundUser&lt;/code&gt; tool should not accept an arbitrary string amount if your business rule needs a positive integer in cents. A &lt;code&gt;searchDocs&lt;/code&gt; tool should constrain query length, filters, and result count. AI SDK 6 also supports per-tool &lt;code&gt;strict&lt;/code&gt; behavior and &lt;code&gt;needsApproval&lt;/code&gt;, according to the tools documentation [3]. Use those controls for actions that spend money, mutate records, send messages, or cross tenant boundaries.&lt;/p&gt;

&lt;p&gt;The uncomfortable lesson from the Vercel AI GitHub discussion on missing tool-call fields is that even a good tool schema does not eliminate invalid calls [11]. AI SDK exposes repair patterns, but repair is not the same as correctness. Use repair for syntactic recovery, then validate business rules in code. If a call still fails, return a short, model-readable error and let the loop decide whether to continue within its step budget.&lt;/p&gt;

&lt;p&gt;Here is a minimal pattern that keeps the loop explicit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ToolLoopAgent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stepCountIs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hasToolCall&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tool&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ai&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;searchDocs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Search approved internal docs for implementation details.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;inputSchema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;160&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;number&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;limit&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;vectorSearch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;limit&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;excerpt&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;excerpt&lt;/span&gt; &lt;span class="p"&gt;}))&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;requestApproval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ask a human operator to approve a high-impact action.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;inputSchema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;send_email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;update_account&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;refund&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
    &lt;span class="na"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;needsApproval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reason&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;approvedAction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reason&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;done&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Call this when the final answer is ready.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;inputSchema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;summary&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;summary&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ToolLoopAgent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;anthropic/claude-sonnet-4.5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;instructions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Answer from approved docs. Ask for approval before any account change.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;searchDocs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;requestApproval&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;done&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;stopWhen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;stepCountIs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;hasToolCall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;done&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Draft the account-update plan for ACME using current docs.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Plan drafted from approved docs. No account mutation executed without approval.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Stream user experience, but structure machine output
&lt;/h2&gt;

&lt;p&gt;AI SDK 6 makes streaming and structured output feel like one surface instead of two separate programming models. The &lt;code&gt;streamText&lt;/code&gt; documentation describes backpressure, per-chunk callbacks, and chunk types such as text, reasoning, and tool-call [4]. That is the right fit for user-facing interfaces where the app should show progress while the loop thinks, searches, calls tools, and writes.&lt;/p&gt;

&lt;p&gt;Structured output serves a different purpose. The generating structured data docs say &lt;code&gt;generateText&lt;/code&gt; can use &lt;code&gt;Output.object({ schema })&lt;/code&gt; to produce schema-constrained objects [5]. Use that for downstream machine work: route decisions, JSON payloads, checklist items, UI cards, and moderation decisions. A production system often needs both surfaces: streaming text for the person watching the task, structured output for the code that has to decide what happens next.&lt;/p&gt;

&lt;p&gt;The practical pattern is to separate "what the user sees" from "what the workflow consumes." Let the loop stream status updates and final prose. Then ask for a small typed object at the decision boundary, or make the final tool call produce the typed artifact. This avoids the common failure mode where a beautiful streamed answer has to be regex-parsed into an action.&lt;/p&gt;

&lt;p&gt;This also keeps blog-demo code from turning into production debt. Vercel Academy's AI summary app demonstrates the common path of building a Next.js app with &lt;code&gt;generateText&lt;/code&gt; and &lt;code&gt;generateObject&lt;/code&gt; style workflows [12]. In AI SDK 6, the migration direction is toward &lt;code&gt;generateText&lt;/code&gt; and &lt;code&gt;streamText&lt;/code&gt; with &lt;code&gt;output&lt;/code&gt; settings [2]. The habit to keep is the same: typed outputs belong at workflow boundaries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect MCP tools over HTTP and observe every step
&lt;/h2&gt;

&lt;p&gt;MCP is useful when your tools need to live outside the Next.js process. The AI SDK MCP docs show &lt;code&gt;createMCPClient&lt;/code&gt;, describe the &lt;code&gt;tools()&lt;/code&gt; adapter method, and call HTTP transport the recommended production option [7]. That makes MCP a reasonable boundary for shared tools such as issue trackers, internal search, billing systems, or document stores.&lt;/p&gt;

&lt;p&gt;Do not use MCP as an excuse to hide operational risk. A remote tool still needs authentication, tenant scoping, rate limits, timeout behavior, and clear error payloads. If the agent can trigger a slow MCP call on every loop step, your step cap becomes a cost-control device. If the MCP tool returns huge payloads, your model context becomes the bottleneck. Return compact, ranked, model-readable results instead of raw dumps.&lt;/p&gt;

&lt;p&gt;Observability is the other half of this boundary. AI SDK telemetry uses OpenTelemetry through &lt;code&gt;experimental_telemetry: { isEnabled: true }&lt;/code&gt;, according to the telemetry docs [8]. Langfuse's integration guide says AI SDK calls can automatically flow into Langfuse when telemetry is enabled [9]. That gives you traces for model calls, tool calls, timing, and failure analysis.&lt;/p&gt;

&lt;p&gt;For production loops, trace at least five fields: task id, tenant id, model, loop step, and tool name. Add token usage and latency if your telemetry backend captures them. You need to know whether failures come from model planning, schema validation, remote tool latency, or your own business logic. Without that, the only debugging tool is rerunning the prompt and hoping it fails the same way twice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ship with a decision checklist, not an agent manifesto
&lt;/h2&gt;

&lt;p&gt;AI SDK 6 is strongest when you use it as a TypeScript control plane for agent behavior. The Hacker News discussion captured a common community reason for adoption: developers value that the SDK abstracts across LLMs, including local or OpenAI-compatible providers, while staying thinner than heavier orchestration frameworks [10]. That portability is valuable, but only if your own tool layer is portable too.&lt;/p&gt;

&lt;p&gt;Pick &lt;code&gt;ToolLoopAgent&lt;/code&gt; when a task requires multiple tool observations, a bounded reasoning loop, and reusable agent instructions. Use &lt;code&gt;streamText&lt;/code&gt; when the user needs live progress or partial output. Use &lt;code&gt;Output.object&lt;/code&gt; when code needs a validated object, not prose. Put high-impact actions behind &lt;code&gt;needsApproval&lt;/code&gt;. Move shared or remote tools behind MCP over HTTP. Turn on telemetry before the first production pilot, not after the first incident.&lt;/p&gt;

&lt;p&gt;The checklist should read like an operating contract:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The loop has a maximum step count lower than the default until traces justify raising it.&lt;/li&gt;
&lt;li&gt;Every mutating or expensive tool has either &lt;code&gt;needsApproval&lt;/code&gt;, a hard business-rule validator, or both.&lt;/li&gt;
&lt;li&gt;Tool outputs are compact enough to fit repeated loop context without drowning the model.&lt;/li&gt;
&lt;li&gt;Structured decisions use schemas; prose is not parsed with regular expressions.&lt;/li&gt;
&lt;li&gt;MCP tools use HTTP transport in production and return small, ranked payloads.&lt;/li&gt;
&lt;li&gt;Telemetry records task id, tenant id, model, step number, tool name, latency, and failures.&lt;/li&gt;
&lt;li&gt;Invalid tool calls are repaired only when syntax is recoverable; business-rule violations fail explicitly.&lt;/li&gt;
&lt;li&gt;User-visible streaming is separated from machine-readable workflow state.&lt;/li&gt;
&lt;li&gt;The agent has a domain-specific done condition, not only a hope that the model stops.&lt;/li&gt;
&lt;li&gt;The team can explain when this should have been a one-shot &lt;code&gt;generateText&lt;/code&gt; call instead.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The takeaway for readers is direct: AI SDK 6 reduces loop boilerplate, but production quality still comes from engineering the loop boundary. If you want to build this pattern end to end with deployment, tracing, and review gates, continue with the Building Scalable Agents course at Koenig AI Academy and pair it with the existing &lt;a href="https://academy.kspl.tech/blog/2026-04-30-vercel-ai-sdk-6-vs-claude-agent-sdk" rel="noopener noreferrer"&gt;Vercel AI SDK 6 vs Claude Agent SDK&lt;/a&gt; architecture comparison.&lt;/p&gt;

&lt;h2&gt;
  
  
  Knowledge Check
&lt;/h2&gt;

&lt;p&gt;Question: Your support agent must search docs, draft a refund recommendation, and execute refunds only after human approval. Which AI SDK 6 controls should you use first?&lt;/p&gt;

&lt;p&gt;A. One unbounded ToolLoopAgent with a refund tool and no stop condition&lt;br&gt;
B. ToolLoopAgent with a low &lt;code&gt;stepCountIs&lt;/code&gt; cap, typed tools, a domain-specific &lt;code&gt;done&lt;/code&gt; tool, &lt;code&gt;needsApproval&lt;/code&gt; on refund execution, and telemetry&lt;br&gt;
C. A single prose-only &lt;code&gt;generateText&lt;/code&gt; call whose final paragraph is parsed for refund amount&lt;br&gt;
D. MCP over stdio in production with raw database rows returned to the model&lt;/p&gt;

&lt;p&gt;Answer: B. The task needs repeated tool feedback, but the production controls are the step cap, typed schemas, explicit approval, a done condition, and traces.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://academy.kspl.tech" rel="noopener noreferrer"&gt;Koenig AI Academy&lt;/a&gt; · Full article: &lt;a href="https://academy.kspl.tech/blog/vercel-ai-sdk-6-production-patterns-autonomous-loops" rel="noopener noreferrer"&gt;https://academy.kspl.tech/blog/vercel-ai-sdk-6-production-patterns-autonomous-loops&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Gemini Spark at $100/Month: Who Should Actually Pay for It (and Who Should Wait)</title>
      <dc:creator>Koenig Academy</dc:creator>
      <pubDate>Thu, 09 Jul 2026 07:16:50 +0000</pubDate>
      <link>https://dev.to/koenig_academy_9a8f35ff4b/gemini-spark-at-100month-who-should-actually-pay-for-it-and-who-should-wait-3ab1</link>
      <guid>https://dev.to/koenig_academy_9a8f35ff4b/gemini-spark-at-100month-who-should-actually-pay-for-it-and-who-should-wait-3ab1</guid>
      <description>&lt;p&gt;Gemini Spark is architecturally different from most AI assistants shipping in 2026.&lt;/p&gt;

&lt;p&gt;It runs a persistent VM across Gmail, Calendar, and Drive, follows standing instructions without re-prompting, and can keep working while your device is offline.&lt;/p&gt;

&lt;p&gt;At $99.99/month, that sounds like a clean premium-product story. It isn't.&lt;/p&gt;

&lt;p&gt;The practical verdict is narrower: Spark is worth paying for only if you're a US-based Google Workspace power user with high-volume inboxes and real cross-app workflow friction. Everyone else should wait.&lt;/p&gt;

&lt;p&gt;Why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spark is still a US-only beta. Buying Google AI Ultra outside the US does &lt;strong&gt;not&lt;/strong&gt; unlock Spark.&lt;/li&gt;
&lt;li&gt;The third-party integrations announced at I/O have not shipped yet, so Spark's action surface is still bounded by Google Workspace.&lt;/li&gt;
&lt;li&gt;The real differentiator is persistence, not "better chat". If your workflow is still mostly session-based, the ROI case weakens fast.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The full breakdown covers the architecture difference, the privacy tradeoffs, the pricing comparison with Claude Max and ChatGPT Pro, and the exact decision criteria:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://academy.kspl.tech/blog/gemini-spark-review-2026" rel="noopener noreferrer"&gt;https://academy.kspl.tech/blog/gemini-spark-review-2026&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://academy.kspl.tech" rel="noopener noreferrer"&gt;Koenig AI Academy&lt;/a&gt; · Free AI courses for developers, updated daily.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>google</category>
      <category>ai</category>
      <category>gemini</category>
      <category>agenticai</category>
    </item>
  </channel>
</rss>
