<?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: anh</title>
    <description>The latest articles on DEV Community by anh (@vietanh).</description>
    <link>https://dev.to/vietanh</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F733960%2Fdac49404-42c0-470b-b225-e238402b88a2.jpeg</url>
      <title>DEV Community: anh</title>
      <link>https://dev.to/vietanh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vietanh"/>
    <language>en</language>
    <item>
      <title>Why (and How) I Built a Go AI SDK</title>
      <dc:creator>anh</dc:creator>
      <pubDate>Tue, 07 Apr 2026 13:02:49 +0000</pubDate>
      <link>https://dev.to/vietanh/why-and-how-i-built-a-go-ai-sdk-26ob</link>
      <guid>https://dev.to/vietanh/why-and-how-i-built-a-go-ai-sdk-26ob</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://goai.sh" rel="noopener noreferrer"&gt;GoAI&lt;/a&gt;, a Go (Golang) LLM library: 22+ providers, 2 dependencies, type-safe generics. v0.6.1, Go 1.25+. I built it to learn Go by adding AI to infrastructure that already runs on Go.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Go AI SDK landscape
&lt;/h2&gt;

&lt;p&gt;Python has LangChain, LlamaIndex, LiteLLM. TypeScript has the Vercel AI SDK. Go has options, but none covered all the bases.&lt;/p&gt;

&lt;h3&gt;
  
  
  What I found
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Library&lt;/th&gt;
&lt;th&gt;Stars&lt;/th&gt;
&lt;th&gt;Created&lt;/th&gt;
&lt;th&gt;Providers&lt;/th&gt;
&lt;th&gt;What's missing&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/sashabaranov/go-openai" rel="noopener noreferrer"&gt;&lt;strong&gt;go-openai&lt;/strong&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;~10.6k&lt;/td&gt;
&lt;td&gt;Aug 2020&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Single provider only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://github.com/cloudwego/eino" rel="noopener noreferrer"&gt;&lt;strong&gt;Eino&lt;/strong&gt;&lt;/a&gt; (ByteDance)&lt;/td&gt;
&lt;td&gt;~10.5k&lt;/td&gt;
&lt;td&gt;Dec 2024&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;Graph framework, different scope&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/tmc/langchaingo" rel="noopener noreferrer"&gt;&lt;strong&gt;LangChainGo&lt;/strong&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;~9k&lt;/td&gt;
&lt;td&gt;Feb 2023&lt;/td&gt;
&lt;td&gt;~14&lt;/td&gt;
&lt;td&gt;170+ deps, no MCP, no generics schema&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/google/adk-go" rel="noopener noreferrer"&gt;&lt;strong&gt;Google ADK Go&lt;/strong&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;~7.5k&lt;/td&gt;
&lt;td&gt;May 2025&lt;/td&gt;
&lt;td&gt;Gemini-first&lt;/td&gt;
&lt;td&gt;Agent framework, Gemini-optimized&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://github.com/firebase/genkit" rel="noopener noreferrer"&gt;&lt;strong&gt;Genkit Go&lt;/strong&gt;&lt;/a&gt; (Google)&lt;/td&gt;
&lt;td&gt;~5.7k*&lt;/td&gt;
&lt;td&gt;2024&lt;/td&gt;
&lt;td&gt;~6&lt;/td&gt;
&lt;td&gt;Google Cloud-heavy, 129 deps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/openai/openai-go" rel="noopener noreferrer"&gt;&lt;strong&gt;openai-go&lt;/strong&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;~3.1k&lt;/td&gt;
&lt;td&gt;Jul 2024&lt;/td&gt;
&lt;td&gt;1+Azure&lt;/td&gt;
&lt;td&gt;Single provider by design&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/anthropics/anthropic-sdk-go" rel="noopener noreferrer"&gt;&lt;strong&gt;anthropic-sdk-go&lt;/strong&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;~960&lt;/td&gt;
&lt;td&gt;Jul 2024&lt;/td&gt;
&lt;td&gt;1+Bedrock&lt;/td&gt;
&lt;td&gt;Single provider by design&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/teilomillet/gollm" rel="noopener noreferrer"&gt;&lt;strong&gt;gollm&lt;/strong&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;~570&lt;/td&gt;
&lt;td&gt;Jul 2024&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Limited tool calling, limited streaming&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/jetify-com/ai" rel="noopener noreferrer"&gt;&lt;strong&gt;Jetify AI&lt;/strong&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;~230&lt;/td&gt;
&lt;td&gt;May 2025&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Early stage, 2 providers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/jxnl/instructor-go" rel="noopener noreferrer"&gt;&lt;strong&gt;instructor-go&lt;/strong&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;~200&lt;/td&gt;
&lt;td&gt;May 2024&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Structured output only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/zendev-sh/goai" rel="noopener noreferrer"&gt;&lt;strong&gt;GoAI&lt;/strong&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;new&lt;/td&gt;
&lt;td&gt;Mar 2026&lt;/td&gt;
&lt;td&gt;22+&lt;/td&gt;
&lt;td&gt;2 deps, this post&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;*Genkit stars shared across JS, Go, and Python.&lt;/p&gt;

&lt;p&gt;The gaps I kept running into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No &lt;code&gt;SchemaFrom[T]&lt;/code&gt;&lt;/strong&gt;: generate JSON Schema from Go structs using generics. Only Genkit Go has this, but pulls in 129 dependencies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No built-in MCP&lt;/strong&gt;: &lt;a href="https://modelcontextprotocol.io/" rel="noopener noreferrer"&gt;Model Context Protocol&lt;/a&gt; connects to external tool servers (filesystem, GitHub, databases, Kubernetes APIs). For infra and edge use-cases, this is how agents interact with surrounding systems&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No provider-defined tools&lt;/strong&gt;: OpenAI has web search, code interpreter, file search. Anthropic has computer use, bash, text editor, web fetch, code execution. Google has Google Search, URL context, code execution. None of the Go LLM libraries expose these&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No prompt caching&lt;/strong&gt;: Anthropic and OpenAI support cache control to reduce cost and latency&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No streaming structured output&lt;/strong&gt;: &lt;code&gt;StreamObject[T]&lt;/code&gt; that progressively populates a Go struct as JSON arrives&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependency weight&lt;/strong&gt;: a library that handles API keys to every major AI provider is a high-value target. Fewer dependencies, smaller attack surface&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why I built GoAI
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. To learn Go.&lt;/strong&gt; Not a Go expert. Built this to learn by solving a real problem. PRs welcome.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. To learn AI-assisted development.&lt;/strong&gt; Designed by me, built with Claude Code. I'll write a separate post on the workflow, what worked, and what didn't.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. To build a foundation for agent orchestration.&lt;/strong&gt; Lightweight AI agents in CI/CD, Kubernetes, CLI, edge. GoAI is the foundation layer.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I learned from the Vercel AI SDK
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://ai-sdk.dev/" rel="noopener noreferrer"&gt;Vercel AI SDK&lt;/a&gt; is the reference. GoAI's API surface is directly inspired by it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GenerateText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StreamText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GenerateObject&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StreamObject&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Embed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EmbedMany&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GenerateImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What I took from Vercel:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unified API surface&lt;/strong&gt; across all providers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimal provider interface&lt;/strong&gt;, 2-3 methods per provider, SDK handles the rest&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool loop with MaxSteps&lt;/strong&gt;, model calls tool, execute, feed back, repeat&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Streaming-first&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retry with exponential backoff&lt;/strong&gt; and Retry-After header awareness&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Go features that solved real problems
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Go generics for type-safe LLM output.&lt;/strong&gt; &lt;code&gt;GenerateObject[T]()&lt;/code&gt; returns &lt;code&gt;ObjectResult[T]&lt;/code&gt; where &lt;code&gt;.Object&lt;/code&gt; is &lt;code&gt;T&lt;/code&gt;, not &lt;code&gt;interface{}&lt;/code&gt;. &lt;code&gt;SchemaFrom[T]()&lt;/code&gt; walks the struct via &lt;code&gt;reflect&lt;/code&gt; to generate JSON Schema, with cycle detection, embedded struct flattening, and nullable pointer fields. No schema files, no codegen. &lt;a href="https://goai.sh/getting-started/structured-output" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Recipe&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt;        &lt;span class="kt"&gt;string&lt;/span&gt;   &lt;span class="s"&gt;`json:"name"`&lt;/span&gt;
    &lt;span class="n"&gt;Ingredients&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"ingredients"`&lt;/span&gt;
    &lt;span class="n"&gt;Steps&lt;/span&gt;       &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"steps"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GenerateObject&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Recipe&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithPrompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"A simple pasta recipe"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;// result.Object is Recipe, fully typed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Functional options for composable configuration.&lt;/strong&gt; &lt;code&gt;WithX()&lt;/code&gt; pattern gives composability and extensibility without breaking changes. Separate option types (&lt;code&gt;Option&lt;/code&gt; vs &lt;code&gt;ImageOption&lt;/code&gt;) so the compiler catches misuse. Options are composable via &lt;code&gt;WithOptions()&lt;/code&gt;. &lt;a href="https://goai.sh/api/options" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GenerateText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithSystem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"You are a helpful assistant"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithPrompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithMaxSteps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;searchTool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;calculatorTool&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithMaxRetries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithOnResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseInfo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"latency=%v tokens=%d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Latency&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Usage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TotalTokens&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Interfaces for provider abstraction.&lt;/strong&gt; Three interfaces (&lt;code&gt;LanguageModel&lt;/code&gt;, &lt;code&gt;EmbeddingModel&lt;/code&gt;, &lt;code&gt;ImageModel&lt;/code&gt;), implicitly satisfied. 22+ providers conform independently. Adding a provider never touches core. &lt;a href="https://goai.sh/providers" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Goroutines and channels for streaming.&lt;/strong&gt; Background goroutine consumes the provider stream (SSE for most providers, binary EventStream for Bedrock, NDJSON for Gemini). Callers read from &lt;code&gt;&amp;lt;-chan string&lt;/code&gt;. All functions are context-aware, retries respect &lt;code&gt;ctx.Done()&lt;/code&gt;. Tool loops execute in parallel with bounded concurrency via semaphores. &lt;a href="https://goai.sh/concepts/streaming" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StreamText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithPrompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Tell me a story"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TextStream&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;sync.Map&lt;/code&gt; and &lt;code&gt;sync.Once&lt;/code&gt;.&lt;/strong&gt; Schema generation cached in &lt;code&gt;sync.Map&lt;/code&gt; by type. Stream consumption uses &lt;code&gt;sync.Once&lt;/code&gt; to start the internal goroutine exactly once.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;errors.As&lt;/code&gt; for cross-provider errors.&lt;/strong&gt; &lt;code&gt;APIError&lt;/code&gt; and &lt;code&gt;ContextOverflowError&lt;/code&gt; defined once, every provider wraps into these. &lt;code&gt;errors.As(err, &amp;amp;apiErr)&lt;/code&gt; works through any wrapping depth. &lt;a href="https://goai.sh/api/errors" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;internal/&lt;/code&gt; for encapsulation.&lt;/strong&gt; The &lt;code&gt;openaicompat&lt;/code&gt; codec lives in &lt;code&gt;internal/&lt;/code&gt;, shared across 13+ providers but invisible to users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fewer dependencies, smaller attack surface
&lt;/h2&gt;

&lt;p&gt;GoAI's core module has &lt;strong&gt;2 dependencies&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Direct: &lt;code&gt;golang.org/x/oauth2&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Indirect: &lt;code&gt;cloud.google.com/go/compute/metadata&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No HTTP frameworks, no JSON schema libraries, no third-party provider SDKs. Raw HTTP calls, parse responses directly.&lt;/p&gt;

&lt;p&gt;This was a design choice from day one (mid-March 2026). For context on why this matters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/BerriAI/litellm" rel="noopener noreferrer"&gt;LiteLLM&lt;/a&gt; (Python, 95M monthly downloads): &lt;a href="https://www.herodevs.com/blog-posts/the-litellm-supply-chain-attack-what-happened-why-it-matters-and-what-to-do-next" rel="noopener noreferrer"&gt;compromised&lt;/a&gt;, malicious versions harvested API keys and cloud credentials. 40,000+ downloads in 40 minutes.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/axios/axios" rel="noopener noreferrer"&gt;Axios&lt;/a&gt; (npm, 100M+ weekly downloads): &lt;a href="https://www.microsoft.com/en-us/security/blog/2026/04/01/mitigating-the-axios-npm-supply-chain-compromise/" rel="noopener noreferrer"&gt;compromised by a North Korean state actor&lt;/a&gt;, cross-platform RAT via fake dependency.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A multi-provider AI SDK concentrates API keys for every provider. Every dependency is an attack vector.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GoAI core:        2 dependencies
Eino:            37 dependencies
instructor-go:   41 dependencies
Genkit Go:      129 dependencies
LangChainGo:    170+ dependencies
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both Langfuse and OpenTelemetry live in separate &lt;code&gt;go.mod&lt;/code&gt; submodules. Go's &lt;a href="https://go.dev/ref/mod#go-sum-files" rel="noopener noreferrer"&gt;&lt;code&gt;go.sum&lt;/code&gt;&lt;/a&gt; checksum verification and &lt;a href="https://go.dev/ref/mod#module-proxy" rel="noopener noreferrer"&gt;GOPROXY&lt;/a&gt; transparency log help too.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi7rbwd0584ftfebzm9r7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi7rbwd0584ftfebzm9r7.png" alt="GoAI Architecture" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Three layers:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;User-facing API&lt;/strong&gt; (&lt;code&gt;generate.go&lt;/code&gt;, &lt;code&gt;object.go&lt;/code&gt;, &lt;code&gt;embed.go&lt;/code&gt;, &lt;code&gt;image.go&lt;/code&gt;): seven functions, options parsing, retry, caching, tool loops, hooks. Context-aware. Multimodal input (&lt;code&gt;PartImage&lt;/code&gt;, &lt;code&gt;PartFile&lt;/code&gt;). Token usage tracking. &lt;a href="https://goai.sh/api/core-functions" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provider interface&lt;/strong&gt; (&lt;code&gt;provider/provider.go&lt;/code&gt;): three interfaces, minimal surface, easy to mock. &lt;a href="https://goai.sh/providers" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provider implementations&lt;/strong&gt; (&lt;code&gt;provider/openai/&lt;/code&gt;, &lt;code&gt;provider/anthropic/&lt;/code&gt;, etc.): 22+ providers, separate packages. Import only what you use.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;LanguageModel&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ModelID&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;DoGenerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="n"&gt;GenerateParams&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;GenerateResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;DoStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="n"&gt;GenerateParams&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;StreamResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;EmbeddingModel&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ModelID&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;DoEmbed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="n"&gt;EmbedParams&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;EmbedResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;MaxValuesPerCall&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;ImageModel&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ModelID&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;DoGenerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="n"&gt;ImageParams&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ImageResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Providers implement &lt;code&gt;DoGenerate&lt;/code&gt; and &lt;code&gt;DoStream&lt;/code&gt;. GoAI handles retries, caching, tool execution, streaming, hooks.&lt;/p&gt;

&lt;h3&gt;
  
  
  The shared codec
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8r32ddxvjpqulhngn9a4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8r32ddxvjpqulhngn9a4.png" alt="Codec Architecture" width="800" height="588"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;13+ providers share a single codec in &lt;code&gt;internal/openaicompat/&lt;/code&gt; (BuildRequest, ParseStream, ParseResponse). Providers with unique wire formats (Anthropic Messages API, Google Gemini REST, AWS Bedrock Converse, Cohere Chat v2) have their own implementations. Azure, vLLM, and MiniMax delegate through existing providers. &lt;a href="https://goai.sh/providers" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tool calling
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F25mny92igpv0ngjqz96g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F25mny92igpv0ngjqz96g.png" alt="Tool Loop" width="800" height="318"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Two kinds: &lt;strong&gt;user-defined&lt;/strong&gt; (you write &lt;code&gt;Execute&lt;/code&gt; with &lt;code&gt;json.RawMessage&lt;/code&gt; input) and &lt;strong&gt;provider-defined&lt;/strong&gt; (runs on provider infrastructure). User-defined tools execute in parallel between steps. &lt;a href="https://goai.sh/concepts/tools" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Provider-defined tools
&lt;/h3&gt;

&lt;p&gt;Providers expose built-in tools (web search, code execution, computer use). Each returns a &lt;code&gt;provider.ToolDefinition&lt;/code&gt; that you wrap into &lt;code&gt;goai.Tool&lt;/code&gt;. &lt;a href="https://goai.sh/concepts/provider-tools" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Get the provider tool definition&lt;/span&gt;
&lt;span class="n"&gt;def&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tools&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WebSearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;anthropic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithMaxUses&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c"&gt;// Wrap into goai.Tool (provider-defined tools have no Execute func)&lt;/span&gt;
&lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tool&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;                   &lt;span class="n"&gt;def&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ProviderDefinedType&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;def&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProviderDefinedType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ProviderDefinedOptions&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;def&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProviderDefinedOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}}&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GenerateText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithPrompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Search for Go AI libraries"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Available: Anthropic (10: Computer, Bash, TextEditor, WebSearch, WebFetch, CodeExecution + versioned variants), OpenAI (4: WebSearch, CodeInterpreter, FileSearch, ImageGeneration), Google (3: GoogleSearch, URLContext, CodeExecution), xAI (2), Groq (1).&lt;/p&gt;

&lt;h3&gt;
  
  
  Go MCP client
&lt;/h3&gt;

&lt;p&gt;Built-in MCP client. &lt;a href="https://goai.sh/concepts/mcp" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;transport&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;mcp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewStdioTransport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"@modelcontextprotocol/server-filesystem"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/tmp"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;mcp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"myapp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mcp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTransport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;mcpTools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListTools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;mcp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConvertTools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mcpTools&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tools&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GenerateText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithPrompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"List files in /tmp"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithMaxSteps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Stdio, SSE, and HTTP transports.&lt;/p&gt;

&lt;h3&gt;
  
  
  Observability
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://goai.sh/concepts/observability" rel="noopener noreferrer"&gt;Langfuse&lt;/a&gt;&lt;/strong&gt;: trace-based observability, token counting, error tracking (separate &lt;code&gt;go.mod&lt;/code&gt;, contributed by &lt;a href="https://github.com/oscarbc96" rel="noopener noreferrer"&gt;@oscarbc96&lt;/a&gt; in &lt;a href="https://github.com/zendev-sh/goai/pull/24" rel="noopener noreferrer"&gt;#24&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://goai.sh/concepts/observability" rel="noopener noreferrer"&gt;OpenTelemetry&lt;/a&gt;&lt;/strong&gt;: distributed tracing and metrics (separate &lt;code&gt;go.mod&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both hook into &lt;code&gt;OnRequest&lt;/code&gt;, &lt;code&gt;OnResponse&lt;/code&gt;, &lt;code&gt;OnToolCall&lt;/code&gt;, &lt;code&gt;OnToolCallStart&lt;/code&gt;, &lt;code&gt;OnStepFinish&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Also supported:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://goai.sh/concepts/prompt-caching" rel="noopener noreferrer"&gt;Prompt caching&lt;/a&gt; via &lt;code&gt;WithPromptCaching()&lt;/code&gt;, implements &lt;a href="https://arxiv.org/abs/2601.06007v2" rel="noopener noreferrer"&gt;arxiv 2601.06007v2&lt;/a&gt;: cache system prompts only (41-80% cost, 13-31% latency savings for agentic workloads). Cache token tracking normalized across Anthropic, OpenAI, Google, Bedrock&lt;/li&gt;
&lt;li&gt;Reasoning tokens, supported for models that expose them&lt;/li&gt;
&lt;li&gt;Citations, &lt;code&gt;result.Sources&lt;/code&gt; for providers that return source annotations&lt;/li&gt;
&lt;li&gt;Auto-batched embeddings, &lt;code&gt;EmbedMany&lt;/code&gt; with bounded parallelism&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://goai.sh/concepts/tools" rel="noopener noreferrer"&gt;&lt;code&gt;WithToolChoice&lt;/code&gt;&lt;/a&gt;, &lt;code&gt;WithTimeout&lt;/code&gt;, &lt;code&gt;WithProviderOptions&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ToolCallIDFromContext&lt;/code&gt; for execution tracing&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://goai.sh/providers/compat" rel="noopener noreferrer"&gt;&lt;code&gt;compat&lt;/code&gt; provider&lt;/a&gt; for any OpenAI-compatible endpoint&lt;/li&gt;
&lt;li&gt;90%+ test coverage with mock HTTP servers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://goai.sh" rel="noopener noreferrer"&gt;Full docs&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go get github.com/zendev-sh/goai
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"gpt-4o"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GenerateText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;goai&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithPrompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Explain Go interfaces in 3 sentences"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&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;Switch providers, same code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"claude-sonnet-4-20250514"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;google&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"gemini-2.0-flash"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;bedrock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"anthropic.claude-sonnet-4-20250514-v1:0"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ollama&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"llama3"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;compat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"my-model"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;compat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithBaseURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://my-api.com/v1"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;More: &lt;a href="https://goai.sh/getting-started/structured-output" rel="noopener noreferrer"&gt;structured output&lt;/a&gt;, &lt;a href="https://goai.sh/concepts/streaming" rel="noopener noreferrer"&gt;streaming&lt;/a&gt;, &lt;a href="https://goai.sh/concepts/tools" rel="noopener noreferrer"&gt;tool calling&lt;/a&gt;, &lt;a href="https://goai.sh/concepts/mcp" rel="noopener noreferrer"&gt;MCP&lt;/a&gt;, &lt;a href="https://goai.sh/api/core-functions" rel="noopener noreferrer"&gt;embeddings&lt;/a&gt;, &lt;a href="https://goai.sh/api/core-functions" rel="noopener noreferrer"&gt;image generation&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Benchmarks
&lt;/h2&gt;

&lt;p&gt;Apple M2, 3 runs, in-process mock servers, identical SSE fixtures (50KB payload). &lt;a href="https://github.com/zendev-sh/goai/tree/main/bench" rel="noopener noreferrer"&gt;Source&lt;/a&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;GoAI&lt;/th&gt;
&lt;th&gt;Vercel AI SDK&lt;/th&gt;
&lt;th&gt;Delta&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cold start&lt;/td&gt;
&lt;td&gt;569us&lt;/td&gt;
&lt;td&gt;13.89ms&lt;/td&gt;
&lt;td&gt;24x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Time to first chunk&lt;/td&gt;
&lt;td&gt;320us&lt;/td&gt;
&lt;td&gt;412us&lt;/td&gt;
&lt;td&gt;1.3x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Streaming throughput&lt;/td&gt;
&lt;td&gt;1.46ms/op&lt;/td&gt;
&lt;td&gt;1.62ms/op&lt;/td&gt;
&lt;td&gt;1.1x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GenerateText&lt;/td&gt;
&lt;td&gt;55.7us/op&lt;/td&gt;
&lt;td&gt;79.0us/op&lt;/td&gt;
&lt;td&gt;1.4x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory (1 stream)&lt;/td&gt;
&lt;td&gt;220KB&lt;/td&gt;
&lt;td&gt;676KB&lt;/td&gt;
&lt;td&gt;3x less&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Schema generation&lt;/td&gt;
&lt;td&gt;3.6us/op&lt;/td&gt;
&lt;td&gt;3.5us/op&lt;/td&gt;
&lt;td&gt;~parity&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;First commit was March 18. 18 releases in 3 weeks, now at v0.6.1. The SDK covers the provider layer: unified API, streaming, tool calling, structured output, MCP, observability. Next up is an agent orchestration layer on top of GoAI for CI/CD, Kubernetes, and CLI workflows.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/zendev-sh/goai" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://goai.sh" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://goai.sh/examples" rel="noopener noreferrer"&gt;Examples&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/zendev-sh/goai/issues" rel="noopener noreferrer"&gt;Issues&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>mcp</category>
      <category>go</category>
    </item>
  </channel>
</rss>
