adk-go-pkg

module
v1.0.11 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 12, 2026 License: MIT

README

adk-go-pkg

Go Reference Go Report Card

Extension library for Google's ADK-Go.

adk-go-pkg provides production-ready building blocks that complement ADK-Go with capabilities it does not ship out of the box.

Features

Feature Description
OpenAI Model Provider Drop-in model.LLM adapter for any OpenAI-compatible API (OpenAI, Ollama, LiteLLM, OpenRouter, vLLM, Together AI).
Generic AG-UI Server Framework-agnostic AG-UI protocol server (agui/) with event emitter, state management, tool orchestration, middleware, and SSE handler. Zero ADK dependency.
ADK-Go AG-UI Bridge Translates ADK-Go session events to AG-UI events (aguiadk/). Thread-to-session mapping, state/message snapshots, and client tool proxy.
Planners Structured plan generation (ReAct JSON and free-form Thinking) that separates reasoning from execution.
File Artifact Service Filesystem-backed artifact.Service with automatic versioning and metadata sidecars.
Session Rewind Roll a session back to any prior event, recalculating state from replayed deltas.
Config Agent Loader Declare entire agent trees in YAML/JSON and build them at runtime via a factory registry. Now includes Agent Skills support.
Agent Skills Config Declarative skill integration via YAML/JSON. Supports filesystem sources with preload optimization and specific skill loading (wildcard or filtered by name).
Test Utilities Complete fake implementations of all ADK-Go interfaces for deterministic testing without external LLM providers. Includes FakeLLM, FakeAgent, FakeSession, and RunnerBuilder.

Installation

go get github.com/ieshan/adk-go-pkg

Quick Start

OpenAI Model Provider
package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/ieshan/adk-go-pkg/model/openai"
	"google.golang.org/adk/model"
	"google.golang.org/genai"
)

func main() {
	m, err := openai.New(openai.Config{
		Model:  "gpt-4o",
		APIKey: os.Getenv("OPENAI_API_KEY"),
	})
	if err != nil {
		log.Fatal(err)
	}

	req := &model.LLMRequest{
		Contents: []*genai.Content{
			genai.NewContentFromText("Hello!", "user"),
		},
	}

	for resp, err := range m.GenerateContent(context.Background(), req, false) {
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(resp.Content.Parts[0].Text)
	}
}

Detailed docs →

Generic AG-UI Server (agui/)
package main

import (
	"context"
	"iter"
	"log"
	"net/http"

	"github.com/ag-ui-protocol/ag-ui/sdks/community/go/pkg/core/events"
	"github.com/ag-ui-protocol/ag-ui/sdks/community/go/pkg/core/types"
	"github.com/ieshan/adk-go-pkg/agui"
)

func main() {
	agent := agui.AgentFunc(func(ctx context.Context, input types.RunAgentInput) iter.Seq2[events.Event, error] {
		ch := make(chan events.Event, 64)
		emitter := agui.NewEventEmitter(ch)
		go func() {
			defer close(ch)
			emitter.RunStarted(input.ThreadID, input.RunID)
			msgID := emitter.GenerateMessageID()
			role := "assistant"
			emitter.TextMessageStart(msgID, &role)
			emitter.TextMessageContent(msgID, "Hello from AG-UI!")
			emitter.TextMessageEnd(msgID)
			emitter.RunFinished(input.ThreadID, input.RunID)
		}()
		return agui.ChanToIter(ctx, ch)
	})

	handler, err := agui.Handler(agui.Config{Agent: agent})
	if err != nil {
		log.Fatal(err)
	}
	log.Fatal(http.ListenAndServe(":8080", handler))
}

Detailed docs →

ADK-Go AG-UI Bridge (aguiadk/)
package main

import (
	"iter"
	"log"
	"net/http"

	"github.com/ieshan/adk-go-pkg/agui"
	"github.com/ieshan/adk-go-pkg/aguiadk"
	"google.golang.org/adk/agent"
	"google.golang.org/adk/session"
	"google.golang.org/genai"
)

func main() {
	myAgent, err := agent.New(agent.Config{
		Name: "greeter",
		Run: func(ctx agent.InvocationContext) iter.Seq2[*session.Event, error] {
			return func(yield func(*session.Event, error) bool) {
				content := genai.NewContentFromText("Hello from ADK!", genai.RoleModel)
				yield(&session.Event{Author: "greeter", Content: content}, nil)
			}
		},
	})
	if err != nil {
		log.Fatal(err)
	}

	handler, err := aguiadk.Handler(
		aguiadk.Config{
			Agent:   myAgent,
			AppName: "my-chatbot",
			UserID:  "default-user",
		},
		agui.Config{},
	)
	if err != nil {
		log.Fatal(err)
	}
	http.Handle("/api/agent", handler)
	log.Fatal(http.ListenAndServe(":8080", nil))
}

Detailed docs →

Planners
package main

import (
	"context"
	"fmt"
	"log"

	"github.com/ieshan/adk-go-pkg/planner"
	"google.golang.org/adk/model"
)

func main() {
	var myLLM model.LLM // your model

	p := planner.NewPlanReAct(planner.PlanReActConfig{
		Model:    myLLM,
		MaxSteps: 5,
	})

	plan, err := p.GeneratePlan(context.Background(), &planner.PlanRequest{
		UserMessage: "Book a flight and send a confirmation email",
		ToolDescriptions: []planner.ToolDescription{
			{Name: "book_flight", Description: "Books a flight"},
			{Name: "send_email", Description: "Sends an email"},
		},
	})
	if err != nil {
		log.Fatal(err)
	}
	for i, step := range plan.Steps {
		fmt.Printf("Step %d: %s\n", i+1, step.Description)
	}
}

Detailed docs →

File Artifact Service
package main

import (
	"context"
	"fmt"
	"log"

	"github.com/ieshan/adk-go-pkg/artifact/file"
	"google.golang.org/adk/artifact"
	"google.golang.org/genai"
)

func main() {
	svc, err := file.New(file.Config{RootDir: "/tmp/artifacts"})
	if err != nil {
		log.Fatal(err)
	}

	resp, err := svc.Save(context.Background(), &artifact.SaveRequest{
		AppName:   "myapp",
		UserID:    "alice",
		SessionID: "session-1",
		FileName:  "report.txt",
		Part:      &genai.Part{Text: "quarterly report"},
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("saved version:", resp.Version)

	// Get artifact version metadata without loading content
	versionResp, err := svc.GetArtifactVersion(context.Background(), &artifact.GetArtifactVersionRequest{
		AppName:   "myapp",
		UserID:    "alice",
		SessionID: "session-1",
		FileName:  "report.txt",
		Version:   0, // 0 means latest
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("MIME type:", versionResp.ArtifactVersion.MimeType)
}

Detailed docs →

Session Rewind
package main

import (
	"context"
	"fmt"
	"log"

	"github.com/ieshan/adk-go-pkg/session/rewind"
	"google.golang.org/adk/session"
)

func main() {
	ctx := context.Background()
	svc := session.InMemoryService()

	// ... create session, append events ...

	rewound, err := rewind.RewindToIndex(ctx, svc, "my-app", "user-1", "session-abc", 2)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("events remaining:", rewound.Events().Len())
}

Detailed docs →

Config Agent Loader
package main

import (
	"context"
	"log"

	"github.com/ieshan/adk-go-pkg/config"
	"google.golang.org/adk/model"
	"google.golang.org/adk/tool"
)

func main() {
	reg := config.NewRegistry()

	reg.RegisterModel("openai", func(cfg map[string]any) (model.LLM, error) {
		// build your model from cfg["model"] and other keys
		return nil, nil
	})
	reg.RegisterTool("search", func(cfg map[string]any) (tool.Tool, error) {
		// build your tool
		return nil, nil
	})

	agent, err := config.LoadAndBuild(context.Background(), "agents/root.yaml", reg)
	if err != nil {
		log.Fatal(err)
	}
	_ = agent
}

Detailed docs →

Agent Skills Config
package main

import (
	"context"
	"log"

	"github.com/ieshan/adk-go-pkg/config"
)

func main() {
	reg := config.NewRegistry()
	// Filesystem skill factory is built-in, no registration needed

	// Load agent with skills from YAML
	agent, err := config.LoadAndBuild(context.Background(), "agents/skills-agent.yaml", reg)
	if err != nil {
		log.Fatal(err)
	}
	// Agent now has access to skills defined in ./skills/
}

Example YAML configuration:

name: skills-agent
type: llm
model: gemini/gemini-2.5-flash
instruction: "You are a helpful assistant with access to specialized skills."
skillsets:
  - name: filesystem
    config:
      path: "./skills"
    preload: complete
    # Optional: load only specific skills instead of all
    # names: ["weather", "cooking"]

Detailed docs →

Test Utilities
package main

import (
    "testing"

    "github.com/ieshan/adk-go-pkg/testutil"
    "google.golang.org/adk/agent"
    "google.golang.org/adk/llmagent"
    "google.golang.org/adk/runner"
    "google.golang.org/genai"
)

func TestMyAgent(t *testing.T) {
    // Create fake LLM with preconfigured responses
    llm := testutil.NewFakeLLM(
        testutil.NewTextResponse("I'll help you!"),
    )

    // Build agent with fake LLM
    ag, _ := llmagent.New(llmagent.Config{
        Name:  "test-agent",
        Model: llm,
        Instruction: "You are helpful.",
    })

    // Use RunnerBuilder for end-to-end testing
    r, fakes, _ := testutil.NewRunnerBuilder().
        WithAgent(ag).
        BuildWithFakes()

    // Run and collect events
    events, _ := testutil.CollectEvents(r.Run(ctx, "user-1", "session-1",
        genai.NewContentFromText("Hello", "user"), agent.RunConfig{}))

    // Assert on results and calls
    if len(events) == 0 {
        t.Error("expected events")
    }
    if fakes.SessionService.AppendEventCount() == 0 {
        t.Error("expected events to be appended")
    }
}

Detailed docs →

Compatibility

  • Go 1.26+ — Uses iter.Seq2 and range-over-func.
  • ADK-Go v1.2.0+ (google.golang.org/adk) — Required for Agent Skills support
  • GenAI v1.54.0 (google.golang.org/genai)

Recent Changes

  • Test Utilities: New testutil package with fake implementations of all ADK-Go interfaces (FakeLLM, FakeAgent, FakeSession, FakeArtifactService, FakeMemoryService, FakeSessionService, RunnerBuilder). Enables fast, deterministic testing without external LLM providers. See docs/testutil.md.
  • Agent Skills Config: New skillset support in config loader. Define skills in YAML/JSON with filesystem sources, preload optimization, and specific skill loading (wildcard or filtered by name). Requires ADK-Go v1.2.0+.
  • OpenAI Model Provider: Updated to support genai v1.54.0 FunctionResponse.Parts structure for function calling compatibility
  • File Artifact Service: Added GetArtifactVersion method for ADK-Go v1.1.0 compatibility, enabling metadata retrieval without loading full content

Dependencies

Beyond ADK-Go and google.golang.org/genai, the only additional direct dependencies are:

License

TBD

Directories

Path Synopsis
Package agui provides a generic AG-UI protocol server for Go applications.
Package agui provides a generic AG-UI protocol server for Go applications.
Package aguiadk bridges ADK-Go agents to the AG-UI protocol.
Package aguiadk bridges ADK-Go agents to the AG-UI protocol.
artifact
file
Package file provides a filesystem-backed implementation of the ADK-Go artifact.Service interface.
Package file provides a filesystem-backed implementation of the ADK-Go artifact.Service interface.
Package config provides types and utilities for loading, parsing, and translating agent configuration files in JSON or YAML format.
Package config provides types and utilities for loading, parsing, and translating agent configuration files in JSON or YAML format.
internal
jsonutil
Package jsonutil provides shared JSON utility functions for adk-go-pkg.
Package jsonutil provides shared JSON utility functions for adk-go-pkg.
model
openai
Package openai provides adapters and helpers for integrating ADK-Go agents with OpenAI-compatible APIs.
Package openai provides adapters and helpers for integrating ADK-Go agents with OpenAI-compatible APIs.
Package planner provides interfaces and types for generating structured execution plans before an agent acts.
Package planner provides interfaces and types for generating structured execution plans before an agent acts.
session
rewind
Package rewind provides utilities for truncating (rewinding) ADK sessions to a prior event, discarding all events that came after the target.
Package rewind provides utilities for truncating (rewinding) ADK sessions to a prior event, discarding all events that came after the target.
Package testutil provides fake implementations of ADK-Go interfaces for deterministic testing without external LLM providers.
Package testutil provides fake implementations of ADK-Go interfaces for deterministic testing without external LLM providers.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL