GAI v0.6.0 – what changed since v0.5.0
Hi everyone 👋
My last devlogs were about GAI v0.5.0 and the new prompt builder, history system, and token budgeting.
I originally thought the next release would mainly contain a few fixes. But while using GAI in a real application, I kept finding places where the abstractions were still too simple.
Around 280 commits later, this turned into a much bigger release.
The most important changes
- Added full OpenAI and Anthropic providers, alongside the existing Gemini and Mistral integrations.
- Added provider-native multi-turn messages instead of putting the whole conversation into one large rendered prompt.
- Added
Workflow.RunEvents, which returns one ordered stream for tokens, retries, iterations, errors, cancellation, and completion. - Added model capability descriptors, so applications can check whether a model supports tools, structured output, reasoning, tokenization, and native messages.
- Added local request validation, so unsupported combinations fail before making a provider request.
- Added an optional OpenAI Responses API transport with streaming, tool continuation, reasoning context, usage, and better error handling.
- Added workflow middleware for things such as memory extraction, auditing, formatting, and evaluations.
- Added OpenTelemetry tracing and an optional Langfuse exporter.
- Reworked the README and added a complete runnable order-support agent example.
- Added a lot more provider, workflow, tool, streaming, and end-to-end tests.
One important problem I fixed
Previously, a model could receive tool definitions twice:
- Through the provider’s native tool API.
- As a JSON tool protocol inside the rendered prompt.
This wasted tokens and gave the model two different ways to call the same tool.
GAI now decides between native and text-based tool transport once when the workflow is created. Native models receive AIRequest.Tools, while other models receive the text fallback. The runtime tools remain executable in both cases.
The hardest part
Honestly, adding more providers was not the hardest part.
The difficult part was keeping one shared Go API without hiding useful provider-specific features.
OpenAI, Anthropic, Gemini, and Mistral all represent tools, history, reasoning, streaming, and errors differently. Making everything look identical would remove useful features, but exposing every provider detail would make the abstraction pointless.
The new capability descriptor system was my solution. A feature can be supported, unsupported, or unknown, and GAI can validate requests based on the information it actually has.
Smaller API changes
Because GAI is still pre-v1, I also cleaned up some APIs:
-
NativeMessageBuildernow returns both the compatibility prompt and native messages together. -
NativeToolModelis deprecated in favor of the more completeModelDescriber. -
Workflow.RunEventsis now the recommended API for primary-agent streaming. - The older three-channel workflow API remains for middleware compatibility.
What I learned
The biggest lesson from this release is that an abstraction should not pretend every provider works in exactly the same way.
It is better to expose capabilities clearly and fail early than to discover an unsupported combination after opening a stream or calling a tool.
GAI is still pre-v1, but it now feels much more like a real agent runtime instead of only a collection of prompt and loop helpers.
Repository:
Comments 0
No comments yet. Be the first!
Sign in to join the conversation.