adk-go-pkg

module
v1.0.17 Latest Latest
Warning

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

Go to latest
Published: Sep 4, 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).
Anthropic Model Provider Drop-in model.LLM adapter for Anthropic's Messages API and compatible providers (Claude, Amazon Bedrock, Google Vertex AI). Supports streaming, tool calling, images, structured output, thinking blocks, and prompt caching.
Generic AG-UI Server Framework-agnostic AG-UI protocol server (agui/) with event emitter, state management (RFC 6902 JSON Patch via evanphx/json-patch), predictive state tracker, tool orchestration, middleware, encrypted-value scrubbing, 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, streaming tool calls, client tool hand-back (NextRun, Inline, and HandBack modes), HITL runstore & resume, tool call validation, activity snapshots, suppressed tool mode, and preset configurations.
Prompt Templating text/template-based prompt rendering engine with agent context data (state, user, session, artifacts, memory), 13 built-in functions, template registry, loader (files/embed.FS), and llmagent.InstructionProvider integration.
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.
Evaluation Framework Evaluate agent performance with eval sets, built-in metrics (trajectory, response match, rubrics, safety, hallucinations), LLM-as-judge auto-raters, user simulation, and a local eval service. Mirrors ADK Python's eval package.
AG-UI MCP Support Inject MCP (Model Context Protocol) server tools into AG-UI agents. Two integration paths: MCPMiddleware for generic tool injection + server-side execution, and MCPAppsMiddleware for UI-enabled tools + proxied MCP requests. Bridge wiring via aguiadk.BuildMCPServerToolsets using ADK-Go's mcptoolset.

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/v2/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 →

Anthropic Model Provider
package main

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

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

func main() {
	m, err := anthropic.New(anthropic.Config{
		Model:  "claude-sonnet-4-20250514",
		APIKey: os.Getenv("ANTHROPIC_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.RunFinishedWithOptions(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/v2/agent"
	"google.golang.org/adk/v2/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 →

Prompt Templating
package main

import (
	"fmt"
	"log"

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

func main() {
	engine := prompt.New()
	tmpl, err := engine.Parse("greeting", "Hello {{.Input.name}}!")
	if err != nil {
		log.Fatal(err)
	}

	data := prompt.BuildData(map[string]any{"name": "world"})
	rendered, err := tmpl.Execute(data)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(rendered)
}

For llmagent.InstructionProvider integration:

provider, err := prompt.NewInstructionProvider(
	"You are {{.Agent.Name}}. User: {{.User.Text}}. Country: {{.State.Get \"country\"}}",
)
// Pass to llmagent.Config{InstructionProvider: provider}

Detailed docs →

Planners
package main

import (
	"context"
	"fmt"
	"log"

	"github.com/ieshan/adk-go-pkg/planner"
	"google.golang.org/adk/v2/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/v2/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/v2/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/v2/model"
	"google.golang.org/adk/v2/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, runCfg, liveRunCfg, ctxCacheCfg, err := config.LoadAndBuild(context.Background(), "agents/root.yaml", reg)
	if err != nil {
		log.Fatal(err)
	}
	_ = agent
	_ = runCfg       // *agent.RunConfig (may be nil)
	_ = liveRunCfg   // *agent.LiveRunConfig (may be nil)
	_ = ctxCacheCfg  // *config.ContextCacheConfig (may be nil)
}

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/
	_ = agent
}

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/v2/agent"
    "google.golang.org/adk/v2/agent/llmagent"
    "google.golang.org/adk/v2/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 →

Evaluation Framework
package main

import (
	"context"
	"encoding/json"
	"fmt"
	"log"

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

func main() {
	ctx := context.Background()

	// Create an in-memory eval sets manager and add a case.
	setsMgr := eval.NewInMemoryEvalSetsManager()
	setsMgr.CreateEvalSet(ctx, "my-app", "basic-eval")
	setsMgr.AddEvalCase(ctx, "my-app", "basic-eval", eval.EvalCase{
		EvalID: "case-1",
		Conversation: []eval.Invocation{
			{UserContent: genai.NewContentFromText("Hello", "user")},
		},
	})

	// Create an agent evaluator with your agent runner and LLM.
	var agentRunner eval.AgentRunner // your agent runner
	var llm model.LLM               // your judge LLM (optional)

	evaluator := eval.NewAgentEvaluator(
		agentRunner, setsMgr, nil, eval.DefaultMetricEvaluatorRegistry(),
		llm,
	)

	// Configure metrics with thresholds.
	config := eval.EvalConfig{
		Criteria: map[string]json.RawMessage{
			"tool_trajectory_avg_score": json.RawMessage(`{"threshold": 0.8}`),
		},
	}

	result, err := evaluator.Evaluate(ctx, "my-app", "basic-eval", config)
	if err != nil {
		log.Fatal(err)
	}
	for _, cr := range result.EvalCaseResults {
		fmt.Printf("Case %s: %s\n", cr.EvalID, cr.FinalEvalStatus)
	}
}

Detailed docs →

AG-UI MCP Support

Inject MCP server tools into any AG-UI agent and execute them server-side:

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] {
		// your agent logic
		return nil
	})

	mcpMW := agui.NewMCPMiddleware([]agui.MCPClientConfig{
		{Type: "http", URL: "https://example.com/mcp", ServerID: "srv1"},
	}, agui.MCPMiddlewareOptions{MaxIterations: 32})

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

For ADK-Go native integration, use aguiadk.BuildMCPServerToolsets to create mcptoolset.Toolset instances from MCP configs. See docs/agui-mcp.md for both integration paths, MCPAppsMiddleware for UI-enabled tools, and proxied MCP request handling.

Compatibility

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

Recent Changes

  • Prompt Templating: New prompt package with text/template-based rendering engine, agent context data (state, user, session, artifacts, memory), 13 built-in functions, thread-safe TemplateRegistry, TemplateLoader (files/embed.FS), TemplateRef tagged union, and llmagent.InstructionProvider integration. Config loader supports InstructionTemplate field for declarative templated instructions. See docs/prompt.md.
  • AG-UI ADK Bridge Gap Fix: Closed all 10 AG-UI protocol feature gaps between the agui/aguiadk packages and the AG-UI example server. New features: disconnect cancellation, client tool hand-back (NextRun, Inline, and HandBack modes via ClientToolset), streaming tool calls (progressive TOOL_CALL_* from partial FunctionCall parts), HITL runstore & resume (RunStore with TTL, atomic claim, approval interrupts), tool call validation (synthetic IDs, error TOOL_CALL_RESULT for malformed calls), suppressed tool mode (Config.SuppressToolEvents + Config.ToolToStateMapper emits STATE_DELTA instead of TOOL_CALL_*), predictive state tracker (agui.PredictiveStateTracker for ghosted /_predictive deltas), activity snapshots (tool_use and approval_request), encrypted value scrubbing in MessagesSnapshot, and preset configurations (AgenticChatPreset, HumanInTheLoopPreset, GenerativeUIPreset, SharedStatePreset, InlineToolsPreset, HandBackPreset, PredictiveStatePreset, AgenticGenerativeUIPreset). StateManager.Apply now uses evanphx/json-patch/v5 for RFC 6902 compliance. See docs/aguiadk-bridge.md.
  • Evaluation Framework: New eval package with eval sets, 13 built-in metrics, LLM-as-judge evaluators, user simulation, and local eval service. Mirrors ADK Python eval package. See docs/eval.md.
  • Anthropic Model Provider: Drop-in model.LLM adapter for Anthropic's Messages API. Supports streaming, tool calling, images, structured output, thinking blocks, and prompt caching. See docs/anthropic-model.md.
  • 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: Skillset support in config loader. Define skills in YAML/JSON with filesystem sources, preload optimization, and specific skill loading (wildcard or filtered by name).
  • OpenAI Model Provider: Supports genai FunctionResponse.Parts structure for function calling.
  • AG-UI MCP Support: MCP (Model Context Protocol) integration for AG-UI agents. MCPMiddleware injects MCP server tools and executes them server-side in an agentic loop. MCPAppsMiddleware handles UI-enabled tools (SEP-1865) and proxied MCP requests from frontends. aguiadk.BuildMCPServerToolsets bridges MCP servers to ADK-Go's native mcptoolset. See docs/agui-mcp.md.
  • File Artifact Service: GetArtifactVersion method for 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.
Package eval provides evaluation tooling for ADK Go agents.
Package eval provides evaluation tooling for ADK Go agents.
simulation
Package simulation provides user simulator implementations for generating user interactions during evaluation.
Package simulation provides user simulator implementations for generating user interactions during evaluation.
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
anthropic
Package anthropic provides adapters and helpers for integrating ADK-Go agents with Anthropic's Messages API and compatible third-party providers.
Package anthropic provides adapters and helpers for integrating ADK-Go agents with Anthropic's Messages API and compatible third-party providers.
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.
Package prompt provides text/template-based prompt rendering for ADK-Go.
Package prompt provides text/template-based prompt rendering for ADK-Go.
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