godantic

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: May 19, 2026 License: MIT Imports: 20 Imported by: 0

README

godantic

Docs

godantic is a small Go framework for building useful LLM agents without turning your app into a pile of provider glue.

Bring a model, a message store, and optional tools. godantic gives you the agent loop, streaming, tool calls, history persistence, and HTTP/WebSocket session helpers.

Documentation: https://desarso.github.io/godantic/

Current version line: v0.x. See Versioning for the release policy.

Why godantic

Most assistant backends end up solving the same problems: provider adapters, function calling, streaming, tool result feedback, chat history, WebSocket plumbing, and persistence. godantic keeps those concerns in one Go module with simple interfaces you can replace when your app needs something custom.

Features

  • One Model interface across Gemini, OpenRouter, Groq, Cerebras, Anthropic, and custom providers.
  • Request/response, streaming, SSE, and WebSocket session helpers.
  • Tool calling with JSON-schema declarations backed by ordinary Go functions.
  • SQLite and PostgreSQL conversation stores through a replaceable MessageStore interface.
  • Built-in tools for search, web fetch, file operations, shell execution, image analysis, workflows, skill files, TypeScript execution, and image generation.
  • Optional trace persistence for WebSocket tool execution.

Docs

Releases

The version is stored in VERSION. Release helpers live in the root Makefile:

make test
make docs-build
make release

make release validates the tree, creates a vX.Y.Z tag, pushes main and the tag, and creates a GitHub release using gh.

Install

go get github.com/Desarso/godantic

For local development from a parent app, use a Go replace directive:

replace github.com/Desarso/godantic => ./godantic

Environment

Set the API key for the provider you use:

Provider Default env var
Gemini GEMINI_API_KEY
OpenRouter OPENROUTER_API_KEY
Groq GROQ_API_KEY
Cerebras CEREBRAS_API_KEY
Anthropic ANTHROPIC_API_KEY

Some built-in tools require their own keys:

Tool Env var
common_tools.Brave_Search BRAVE_API_KEY
common_tools.Search PERPLEXITY_API_KEY

WebSocket TTS support uses optional ElevenLabs env vars such as ELEVEN_LABS_API_KEY, ELEVEN_LABS_TTS_VOICE_ID, and ELEVEN_LABS_TTS_MODEL_ID.

Quick Start

package main

import (
    "fmt"
    "log"

    "github.com/Desarso/godantic"
    "github.com/Desarso/godantic/models"
    "github.com/Desarso/godantic/stores"
)

func main() {
    store, err := stores.NewSQLiteStoreSimple("chat.sqlite")
    if err != nil {
        log.Fatal(err)
    }

    agent := godantic.Create_Agent(
        godantic.NewGeminiModel("gemini-2.0-flash"),
        nil,
    )

    session := godantic.NewHTTPSession("conversation-1", &agent, store)

    userMessage := models.User_Message{
        Role: "user",
        Content: models.Content{Parts: []models.User_Part{{Text: "Say hello in one sentence."}}},
    }

    response, err := session.RunSingleInteraction(userMessage)
    if err != nil {
        log.Fatal(err)
    }

    for _, part := range response.Parts {
        if part.Text != nil {
            fmt.Println(*part.Text)
        }
    }
}

Run it with:

GEMINI_API_KEY=... go run .

Models

Use the helper constructors for common providers:

agent := godantic.Create_Agent(godantic.NewGeminiModel("gemini-2.0-flash"), tools)
agent := godantic.Create_Agent(godantic.NewOpenRouterModel("openai/gpt-4o-mini"), tools)
agent := godantic.Create_Agent(godantic.NewGroqModel("llama-3.1-70b-versatile"), tools)
agent := godantic.Create_Agent(godantic.NewCerebrasModel("llama-3.3-70b"), tools)
agent := godantic.Create_Agent(godantic.NewAnthropicModel("claude-sonnet-4-20250514"), tools)

Provider-specific option helpers are also available:

temp := 0.2
maxTokens := 2048

model := godantic.NewOpenRouterModelWithOptions(
    "anthropic/claude-sonnet-4",
    &temp,
    &maxTokens,
    "https://example.com",
    "Example App",
)

OpenRouter, Groq, Cerebras, and Anthropic model structs also support custom BaseURL and APIKeyEnv fields for compatible gateways.

Sessions

HTTP

Use HTTPSession for request/response APIs, SSE endpoints, jobs, or tests.

session := godantic.NewHTTPSession("conversation-1", &agent, store)

response, err := session.RunSingleInteraction(userMessage)
stream, errs := session.RunStreamInteraction(userMessage)
history, err := session.GetChatHistory()

For clients that send the full request shape, use the Model_Request methods:

req := models.Model_Request{User_Message: &userMessage}
response, err := session.RunSingleInteractionWithRequest(req)
SSE

Implement SSEWriter and call RunSSEInteraction:

type Writer struct{}

func (Writer) WriteSSE(data string) error { return nil }
func (Writer) WriteSSEError(err error) error { return nil }
func (Writer) Flush() {}

err := session.RunSSEInteraction(userMessage, Writer{}, ctx)
WebSocket

Use AgentSession when you have a *websocket.Conn and want the built-in WebSocket protocol, tool approval flow, frontend tool support, trace streaming, and optional TTS handling.

session := godantic.NewAgentSession(
    "session-1",
    "user-1",
    conn,
    &agent,
    store,
    memoryManager,
)

if traceStore != nil {
    session.SetTraceStore(traceStore)
}

err := session.RunInteraction(req)

memoryManager can be nil. If provided, it must implement the session memory interface in sessions/types.go.

Stores

SQLite is the easiest default:

store, err := stores.NewSQLiteStoreSimple("chat.sqlite")

PostgreSQL is available by DSN or config:

store, err := stores.NewPostgresStoreSimple("host=localhost user=app password=secret dbname=chat port=5432 sslmode=disable")

You can provide your own persistence by implementing stores.MessageStore.

Tools

Tools are models.FunctionDeclaration values. Each declaration contains:

  • Name: the tool name exposed to the model.
  • Description: when the model should call it.
  • Parameters: JSON schema for arguments.
  • Callable: a Go function that returns (string, error).

The callable can take no parameters, one parameter, or multiple typed parameters. Agent.ExecuteTool maps model-provided arguments into the Go function and returns a JSON string result.

Built-In Tools

For the standard local-agent tools, use common_tools.DefaultTools():

import "github.com/Desarso/godantic/common_tools"

tools := common_tools.DefaultTools()
agent := godantic.Create_Agent(godantic.NewOpenRouterModel("openai/gpt-4o-mini"), tools)

For schema-backed built-ins, use Create_Tools with functions that have cached schemas in schemas/cached_schemas:

tools, err := godantic.Create_Tools([]interface{}{
    common_tools.Brave_Search,
    common_tools.Web_Fetch,
    common_tools.Execute_TypeScript,
})
if err != nil {
    log.Fatal(err)
}
Custom Tools

For application tools, the most portable path is to construct models.FunctionDeclaration directly:

func GetWeather(city string) (string, error) {
    return "Sunny in " + city, nil
}

weatherTool := models.FunctionDeclaration{
    Name:        "get_weather",
    Description: "Get the current weather for a city.",
    Parameters: models.Parameters{
        Type: "object",
        Properties: map[string]interface{}{
            "city": map[string]interface{}{
                "type":        "string",
                "description": "City name",
            },
        },
        Required: []string{"city"},
    },
    Callable: GetWeather,
}

agent := godantic.Create_Agent(godantic.NewGeminiModel("gemini-2.0-flash"), []models.FunctionDeclaration{weatherTool})

For multi-argument functions, keep Required in the same order as the Go function parameters.

Configuration Builder

WSConfig is a convenience builder for apps that wire controllers from config:

config := godantic.NewWSConfig().
    WithOpenRouter("openai/gpt-4o-mini").
    WithSystemPrompt("You are concise and helpful.").
    WithSQLiteStore("chat.sqlite").
    WithTools([]interface{}{common_tools.Brave_Search}).
    WithTemperature(0.2).
    WithMaxTokens(2048)

Then create tools and an agent:

tools, err := godantic.Create_Tools(config.Tools)
if err != nil {
    log.Fatal(err)
}

agent := godantic.Create_Agent_From_Config(config, tools)

Request And Response Shape

A normal user request is a models.Model_Request with a User_Message:

req := models.Model_Request{
    User_Message: &models.User_Message{
        Role: "user",
        Content: models.Content{Parts: []models.User_Part{{Text: "What can you do?"}}},
    },
}

Tool follow-up requests use Tool_Results:

req := models.Model_Request{
    Tool_Results: &[]models.Tool_Result{{
        Tool_ID:     "call_123",
        Tool_Name:   "get_weather",
        Tool_Output: `{"result":"Sunny"}`,
    }},
}

Responses are models.Model_Response values containing parts. A part may be text, a function call, thinking/reasoning content, or provider-specific metadata.

Testing

Run the module tests with:

go test ./...

License

MIT. See LICENSE.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Create_Tool

func Create_Tool(fn interface{}) (models.FunctionDeclaration, error)

tool takes a function, finds its generated JSON schema, and returns a Tool struct.

func Create_Tools

func Create_Tools(fns []interface{}) ([]models.FunctionDeclaration, error)

func NewAnthropicModel

func NewAnthropicModel(modelName string) *anthropicModel.Anthropic_Model

NewAnthropicModel creates a new Anthropic model instance

func NewAnthropicModelWithOptions

func NewAnthropicModelWithOptions(modelName string, temperature *float64, maxTokens *int, systemPrompt string) *anthropicModel.Anthropic_Model

NewAnthropicModelWithOptions creates a new Anthropic model with full configuration

func NewCerebrasModel

func NewCerebrasModel(modelName string) *cerebras.Cerebras_Model

NewCerebrasModel creates a new Cerebras model instance

func NewCerebrasModelWithOptions

func NewCerebrasModelWithOptions(modelName string, temperature *float64, maxTokens *int, systemPrompt string, topP *float64, seed *int) *cerebras.Cerebras_Model

NewCerebrasModelWithOptions creates a new Cerebras model with full configuration

func NewGeminiModel

func NewGeminiModel(modelName string) *gemini.Gemini_Model

NewGeminiModel creates a new Gemini model instance

func NewGroqModel

func NewGroqModel(modelName string) *groq.Groq_Model

NewGroqModel creates a new Groq model instance

func NewGroqModelWithOptions

func NewGroqModelWithOptions(modelName string, temperature *float64, maxTokens *int, systemPrompt string) *groq.Groq_Model

NewGroqModelWithOptions creates a new Groq model with full configuration

func NewOpenRouterModel

func NewOpenRouterModel(modelName string) *openrouter.OpenRouter_Model

NewOpenRouterModel creates a new OpenRouter model instance

func NewOpenRouterModelWithBaseURL

func NewOpenRouterModelWithBaseURL(modelName, baseURL, apiKeyEnv string, temperature *float64, maxTokens *int) *openrouter.OpenRouter_Model

NewOpenRouterModelWithBaseURL creates a new OpenRouter-compatible model with custom base URL and API key

func NewOpenRouterModelWithOptions

func NewOpenRouterModelWithOptions(modelName string, temperature *float64, maxTokens *int, siteURL, siteName string) *openrouter.OpenRouter_Model

NewOpenRouterModelWithOptions creates a new OpenRouter model with full configuration

func Tool_Approver

func Tool_Approver(tool_name string, tool_args map[string]interface{}) (bool, error)

Tool_Approver checks if a tool requires user approval. Returns true if the tool is auto-approved or if approval is granted. Returns false if approval is required but not granted.

Types

type Agent

type Agent struct {
	Model  Model
	Tools  []models.FunctionDeclaration
	Memory MemoryManager
}

func Create_Agent

func Create_Agent(model Model, tools []models.FunctionDeclaration, memory ...MemoryManager) Agent

Create_Agent creates an agent with the given model and tools

func Create_Agent_From_Config

func Create_Agent_From_Config(config *WSConfig, tools []models.FunctionDeclaration, memory ...MemoryManager) Agent

Create_Agent_From_Config creates an agent from a WSConfig

func (*Agent) ApproveTool

func (agent *Agent) ApproveTool(name string, args map[string]interface{}) (bool, error)

ApproveTool checks if a tool should be auto-approved

func (*Agent) ExecuteTool

func (agent *Agent) ExecuteTool(functionName string, functionCallArgs map[string]interface{}, sessionID string) (string, error)

ExecuteTool executes a tool dynamically by name and arguments

func (*Agent) Run

func (agent *Agent) Run(request models.Model_Request, conversationHistory []stores.Message) (models.Model_Response, error)

func (*Agent) Run_Stream

func (agent *Agent) Run_Stream(request models.Model_Request, conversationHistory []stores.Message) (<-chan models.Model_Response, <-chan error)

func (*Agent) SetHistoryWarningCallback

func (agent *Agent) SetHistoryWarningCallback(callback func(warnings []models.HistoryWarning)) bool

SetHistoryWarningCallback sets a callback for history warnings if the model supports it Returns true if the model supports warnings, false otherwise

type AgentError

type AgentError = sessions.AgentError

type AgentInterface

type AgentInterface = sessions.AgentInterface

type AgentSession

type AgentSession = sessions.AgentSession

Re-export session types for backward compatibility

func NewAgentSession

func NewAgentSession(sessionID string, userID string, conn *websocket.Conn, agent *Agent, store stores.MessageStore, memory MemoryManager) *AgentSession

Re-export constructor functions

type HTTPSession

type HTTPSession = sessions.HTTPSession

func NewHTTPSession

func NewHTTPSession(conversationID string, agent *Agent, store stores.MessageStore) *HTTPSession

type HistoryWarner

type HistoryWarner interface {
	SetHistoryWarningCallback(callback func(warnings []models.HistoryWarning))
}

HistoryWarner is an optional interface that models can implement to report warnings when adapting conversation history

type MemoryManager

type MemoryManager = sessions.MemoryManager

type Model

type Model interface {
	Model_Request(request models.Model_Request, tools []models.FunctionDeclaration, conversationHistory []stores.Message) (models.Model_Response, error)
	Stream_Model_Request(request models.Model_Request, tools []models.FunctionDeclaration, conversationHistory []stores.Message) (<-chan models.Model_Response, <-chan error)
}

type ModelProvider

type ModelProvider string

ModelProvider represents the AI model provider to use

const (
	ProviderGemini     ModelProvider = "gemini"
	ProviderOpenRouter ModelProvider = "openrouter"
	ProviderGroq       ModelProvider = "groq"
	ProviderCerebras   ModelProvider = "cerebras"
	ProviderAnthropic  ModelProvider = "anthropic"
)

type ResponseWaiter

type ResponseWaiter = sessions.ResponseWaiter

type SSEWriter

type SSEWriter = sessions.SSEWriter

type ToolExecutorFunc

type ToolExecutorFunc = sessions.ToolExecutorFunc

type WSConfig

type WSConfig struct {
	ModelName    string
	Tools        []interface{}
	Store        stores.MessageStore
	TraceStore   stores.TraceStore // Optional: Store for execution traces
	Provider     ModelProvider     // AI model provider (gemini, openrouter, groq)
	SiteURL      string            // Optional: Site URL for OpenRouter rankings
	SiteName     string            // Optional: Site name for OpenRouter rankings
	Temperature  *float64          // Optional: Temperature for model generation
	MaxTokens    *int              // Optional: Max tokens for model generation
	SystemPrompt string            // Optional: System prompt for the AI
}

WSConfig holds configuration for WebSocket controllers

func NewAnthropicConfig

func NewAnthropicConfig(model string) *WSConfig

NewAnthropicConfig creates a new configuration with Anthropic as the provider

func NewCerebrasConfig

func NewCerebrasConfig(model string) *WSConfig

NewCerebrasConfig creates a new configuration with Cerebras as the provider

func NewGroqConfig

func NewGroqConfig(model string) *WSConfig

NewGroqConfig creates a new configuration with Groq as the provider

func NewOpenRouterConfig

func NewOpenRouterConfig(model string) *WSConfig

NewOpenRouterConfig creates a new configuration with OpenRouter as the provider

func NewWSConfig

func NewWSConfig() *WSConfig

NewWSConfig creates a new WebSocket configuration with default values

func (*WSConfig) WithAnthropic

func (c *WSConfig) WithAnthropic(model string) *WSConfig

WithAnthropic sets Anthropic as the provider with the specified model

func (*WSConfig) WithCerebras

func (c *WSConfig) WithCerebras(model string) *WSConfig

WithCerebras sets Cerebras as the provider with the specified model

func (*WSConfig) WithGroq

func (c *WSConfig) WithGroq(model string) *WSConfig

WithGroq sets Groq as the provider with the specified model

func (*WSConfig) WithMaxTokens

func (c *WSConfig) WithMaxTokens(tokens int) *WSConfig

WithMaxTokens sets the max tokens for model generation

func (*WSConfig) WithModelName

func (c *WSConfig) WithModelName(modelName string) *WSConfig

WithModelName sets the model name for the configuration

func (*WSConfig) WithOpenRouter

func (c *WSConfig) WithOpenRouter(model string) *WSConfig

WithOpenRouter sets OpenRouter as the provider with the specified model

func (*WSConfig) WithPostgresStore

func (c *WSConfig) WithPostgresStore(host, user, password, dbname string, port int) *WSConfig

WithPostgresStore sets a PostgreSQL store with the specified connection parameters

func (*WSConfig) WithProvider

func (c *WSConfig) WithProvider(provider ModelProvider) *WSConfig

WithProvider sets the AI model provider

func (*WSConfig) WithSQLiteStore

func (c *WSConfig) WithSQLiteStore(dbPath string) *WSConfig

WithSQLiteStore sets a SQLite store with the specified database path

func (*WSConfig) WithSiteInfo

func (c *WSConfig) WithSiteInfo(url, name string) *WSConfig

WithSiteInfo sets the site URL and name for OpenRouter rankings

func (*WSConfig) WithStore

func (c *WSConfig) WithStore(store stores.MessageStore) *WSConfig

WithStore sets the message store for the configuration

func (*WSConfig) WithSystemPrompt

func (c *WSConfig) WithSystemPrompt(systemPrompt string) *WSConfig

WithSystemPrompt sets the system prompt for the AI

func (*WSConfig) WithTemperature

func (c *WSConfig) WithTemperature(temp float64) *WSConfig

WithTemperature sets the temperature for model generation

func (*WSConfig) WithTools

func (c *WSConfig) WithTools(tools []interface{}) *WSConfig

WithTools sets the tools for the configuration

func (*WSConfig) WithTraceStore

func (c *WSConfig) WithTraceStore(traceStore stores.TraceStore) *WSConfig

WithTraceStore sets the trace store for execution trace persistence

type WebSocketToolResultMessage

type WebSocketToolResultMessage = sessions.WebSocketToolResultMessage

type WebSocketWriter

type WebSocketWriter = sessions.WebSocketWriter

Directories

Path Synopsis
Package common_tools provides a collection of tools for AI agents.
Package common_tools provides a collection of tools for AI agents.
Package docs Code generated by swaggo/swag.
Package docs Code generated by swaggo/swag.
elevenlabs
direct_session command

Jump to

Keyboard shortcuts

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