agent

package module
v0.0.0-...-9f72101 Latest Latest
Warning

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

Go to latest
Published: Apr 17, 2026 License: MIT Imports: 14 Imported by: 0

README

go-agent

A Go library for building LLM-powered agents with tool use, multi-turn conversation, and multi-agent handoffs.

Installation

go get github.com/eolymp/go-agent

Quick Start

import (
    agent "github.com/eolymp/go-agent"
    "github.com/eolymp/go-agent/anthropic"
)

// Set the default completer once at startup
agent.SetChatCompleter(anthropic.New(
    option.WithAPIKey("your-api-key"),
))

// Create an agent
a := agent.New("assistant",
    agent.WithModel("claude-sonnet-4-5"),
    agent.WithSystemMessage("You are a helpful assistant."),
)

// Add a user message and run
_ = a.Append(ctx, agent.NewUserMessage("What is 2+2?"))

reply, err := a.Run(ctx)
if err != nil {
	panic(err)
}

fmt.Println(reply.Text())

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Complete

func Complete[T any](ctx context.Context, a *Agent, opts ...Option) (out T, err error)
Example
ctx := context.Background()

type Output struct {
	Answer int    `json:"answer"`
	Unit   string `json:"unit"`
}

a := agent.New("assistant",
	agent.WithModel("claude-sonnet-4-5"),
	agent.WithSystemMessage("You are a helpful assistant. Communicate your final answer using `complete_task` tool."),
	agent.WithAutoApproveAll(),
)

_ = a.Append(ctx, agent.NewUserMessage("How many days are in a year?"))

out, err := agent.Complete[Output](ctx, a)
if err != nil {
	panic(err)
}

fmt.Printf("%d %s\n", out.Answer, out.Unit)

func SetChatCompleter

func SetChatCompleter(c ChatCompleter)

Types

type Agent

type Agent struct {
	// contains filtered or unexported fields
}

func New

func New(name string, opts ...Option) *Agent

func (Agent) Append

func (a Agent) Append(ctx context.Context, msg Message) error

func (Agent) Ask

func (a Agent) Ask(ctx context.Context, opts ...Option) (err error)

Ask is deprecated, use Run instead.

func (Agent) Memory

func (a Agent) Memory() Memory

func (Agent) Name

func (a Agent) Name() string

func (Agent) Run

func (a Agent) Run(ctx context.Context, opts ...Option) (reply AssistantMessage, err error)
Example (QuickStart)
package main

import (
	"context"
	"fmt"

	"github.com/anthropics/anthropic-sdk-go/option"
	agent "github.com/eolymp/go-agent"
	"github.com/eolymp/go-agent/anthropic"
)

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

	agent.SetChatCompleter(anthropic.New(
		option.WithAPIKey("your-api-key"),
	))

	a := agent.New("assistant",
		agent.WithModel("claude-sonnet-4-5"),
		agent.WithSystemMessage("You are a helpful assistant."),
	)

	_ = a.Append(ctx, agent.NewUserMessage("What is 2+2?"))

	reply, err := a.Run(ctx)
	if err != nil {
		panic(err)
	}

	fmt.Println(reply.Text())
}
Example (WithToolApproval)
package main

import (
	"context"
	"errors"
	"fmt"

	agent "github.com/eolymp/go-agent"
)

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

	type Input struct {
		A int `json:"a"`
		B int `json:"b"`
	}

	a := agent.New("calculator",
		agent.WithModel("claude-sonnet-4-5"),
		agent.WithSystemMessage("You are a calculator."),
		agent.WithInlineTool("add", "Add two numbers", func(ctx context.Context, in Input) (int, error) {
			return in.A + in.B, nil
		}),
	)

	_ = a.Append(ctx, agent.NewUserMessage("What is 123 + 456?"))

	var approved, rejected []string
	for {
		reply, err := a.Run(ctx, agent.WithApprovals(approved...), agent.WithRejections(rejected...))

		approved, rejected = nil, nil

		var req agent.ToolApprovalRequest
		if errors.As(err, &req) {
			for _, call := range req.Calls {
				fmt.Printf("Approve tool call %q? (y/n): ", call.Name)
				var input string
				fmt.Scan(&input)
				if input == "y" {
					approved = append(approved, call.ID)
				} else {
					rejected = append(rejected, call.ID)
				}
			}

			continue
		}

		if err != nil {
			panic(err)
		}

		fmt.Println(reply.Text())
		break
	}
}
Example (WithTools)
package main

import (
	"context"
	"fmt"

	agent "github.com/eolymp/go-agent"
)

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

	type Input struct {
		A int `json:"a"`
		B int `json:"b"`
	}

	a := agent.New("calculator",
		agent.WithModel("claude-sonnet-4-5"),
		agent.WithSystemMessage("You are a calculator."),
		agent.WithAutoApproveAll(),
		agent.WithInlineTool("add", "Add two numbers", func(ctx context.Context, in Input) (int, error) {
			return in.A + in.B, nil
		}),
	)

	_ = a.Append(ctx, agent.NewUserMessage("What is 123 + 456?"))

	reply, err := a.Run(ctx)
	if err != nil {
		panic(err)
	}

	fmt.Println(reply.Text())
}

type AssistantMessage

type AssistantMessage struct {
	Content []MessageBlock `json:"content"`
}

func LastMessageAsAssistant

func LastMessageAsAssistant(memory Memory) (AssistantMessage, bool)

func NewAssistantMessage

func NewAssistantMessage(text ...string) AssistantMessage

func (AssistantMessage) Reasoning

func (m AssistantMessage) Reasoning() string

func (AssistantMessage) Text

func (m AssistantMessage) Text() string

func (AssistantMessage) Unmarshal

func (m AssistantMessage) Unmarshal(v any) error

type ChatCompleter

type ChatCompleter interface {
	// Complete performs a chat completion request and returns the response.
	Complete(ctx context.Context, req CompletionRequest) (*CompletionResponse, error)
}

ChatCompleter defines the interface for chat completion operations. This abstraction allows for different LLM providers (OpenAI, Anthropic, Google, etc.)

type Chunk

type Chunk struct {
	Type         StreamChunkType
	Index        int
	Text         string      // For text and thinking deltas
	Call         *ToolCall   // For tool calls (both user and server tools)
	Signature    string      // For thinking signature
	Result       *ToolResult // For inline tool results
	Usage        *CompletionUsage
	FinishReason FinishReason
}

type CompletionRequest

type CompletionRequest struct {
	Model             string
	Messages          []Message
	Tools             []Tool
	ToolChoice        ToolChoice
	ParallelToolCalls bool
	MaxTokens         *int64
	Temperature       *float32
	TopP              *float32
	TopK              *int32
	UseCache          *bool
	Container         *Container
	Betas             []string
	Reasoning         *Reasoning
	StreamCallback    func(ctx context.Context, chunk Chunk) error
}

type CompletionResponse

type CompletionResponse struct {
	Content      []MessageBlock
	FinishReason FinishReason
	Usage        CompletionUsage
	Model        string
}

CompletionResponse represents a provider-agnostic chat completion response.

type CompletionUsage

type CompletionUsage struct {
	PromptTokens       int `json:"prompt_tokens,omitempty"`
	CompletionTokens   int `json:"completion_tokens,omitempty"`
	ThinkingTokens     int `json:"thinking_tokens,omitempty"`
	TotalTokens        int `json:"total_tokens,omitempty"`
	CachedPromptTokens int `json:"cached_prompt_tokens,omitempty"`
}

CompletionUsage represents token usage information for a completion.

type Container

type Container struct {
	ID     string
	Skills []Skill
}

type FinishReason

type FinishReason int

FinishReason indicates why the model stopped generating.

const (
	// FinishReasonStop indicates natural stop point
	FinishReasonStop FinishReason = iota
	// FinishReasonLength indicates max tokens reached
	FinishReasonLength
	// FinishReasonToolCalls indicates model wants to call tools
	FinishReasonToolCalls
	// FinishReasonContentFilter indicates content was filtered
	FinishReasonContentFilter
)

func (FinishReason) String

func (f FinishReason) String() string

String returns the string representation of FinishReason for debugging.

type ForgetfulMemory

type ForgetfulMemory struct {
	// contains filtered or unexported fields
}

ForgetfulMemory keeps memory for the last user message, every new user message erases all memories.

func NewForgetfulMemory

func NewForgetfulMemory() *ForgetfulMemory

func (*ForgetfulMemory) Append

func (m *ForgetfulMemory) Append(ctx context.Context, msg Message) error

func (*ForgetfulMemory) List

func (m *ForgetfulMemory) List(ctx context.Context) ([]Message, error)

type Handoff

type Handoff struct {
	Agent *Agent
}

Handoff error communicates the agent has decided to handover conversation to another agent This is a sentinel error which stops agentic loop to restart it using another agent.

func (Handoff) Error

func (Handoff) Error() string

type InMemoryStorage

type InMemoryStorage struct {
	// contains filtered or unexported fields
}

func NewInMemoryStorage

func NewInMemoryStorage() *InMemoryStorage

func (*InMemoryStorage) Delete

func (s *InMemoryStorage) Delete(ctx context.Context, filename string) error

func (*InMemoryStorage) Exists

func (s *InMemoryStorage) Exists(ctx context.Context, filename string) (bool, error)

func (*InMemoryStorage) Read

func (s *InMemoryStorage) Read(ctx context.Context, filename string) ([]byte, error)

func (*InMemoryStorage) Write

func (s *InMemoryStorage) Write(ctx context.Context, filename string, content []byte) error

type Memory

type Memory interface {
	List() []Message
	Append(ctx context.Context, m Message) error
}

Memory provides a memorization capability for an agent.

type Message

type Message interface {
	// contains filtered or unexported methods
}

func LastMessage

func LastMessage(memory Memory) (Message, bool)

type MessageBlock

type MessageBlock struct {
	Type       MessageBlockType `json:"type"`
	Text       string           `json:"text,omitempty"`
	Signature  string           `json:"signature,omitempty"`
	ToolCall   *ToolCall        `json:"toolcall,omitempty"`
	ToolResult *ToolResult      `json:"tool_result,omitempty"`
}

type MessageBlockType

type MessageBlockType string
const (
	MessageBlockTypeText           MessageBlockType = "text"
	MessageBlockTypeToolCall       MessageBlockType = "tool_call"
	MessageBlockTypeReasoning      MessageBlockType = "reasoning"
	MessageBlockTypeSignature      MessageBlockType = "signature"
	MessageBlockTypeServerToolCall MessageBlockType = "server_tool_call"
	MessageBlockTypeToolResult     MessageBlockType = "tool_result"
)

type Option

type Option func(*Agent)

func SystemPrompt

func SystemPrompt(text string) Option

SystemPrompt is for backwards compatibility Deprecated, use WithSystemMessage instead

func WithApprovals

func WithApprovals(calls ...string) Option

WithApprovals creates approver which approves specific calls

func WithApprover

func WithApprover(aa ...func(call ToolCall) ToolCallApproval) Option

func WithAssistantMessage

func WithAssistantMessage(text string) Option

func WithAutoApproveAll

func WithAutoApproveAll() Option

WithAutoApproveAll creates approver which approves all calls automatically

func WithAutoApproveTools

func WithAutoApproveTools(names ...string) Option

WithAutoApproveTools creates approver which approves calls for specific tools automatically

func WithBetas

func WithBetas(betas ...string) Option

func WithBuiltinTool

func WithBuiltinTool(name, kind string) Option

func WithChatCompleter

func WithChatCompleter(completer ChatCompleter) Option

func WithContainer

func WithContainer(container *Container) Option

func WithDescription

func WithDescription(desc string) Option

func WithFinalizer

func WithFinalizer(ff ...func(*AssistantMessage) error) Option

func WithHandoffTool

func WithHandoffTool(agents ...*Agent) Option

func WithInlineTool

func WithInlineTool[In any, Out any](name, desc string, fn func(context.Context, In) (Out, error)) Option

func WithMaxTokens

func WithMaxTokens(maxTokens int64) Option

func WithMemory

func WithMemory(memory Memory) Option

func WithMessages

func WithMessages(messages []Message) Option

func WithMetadata

func WithMetadata(key string, value any) Option

func WithModel

func WithModel(model string) Option

func WithModelMapper

func WithModelMapper(fn func(string) string) Option

func WithModelMapping

func WithModelMapping(mapping map[string]string) Option

func WithOptionLoader

func WithOptionLoader(loaders ...OptionLoader) Option

func WithOptions

func WithOptions(opts ...Option) Option

func WithOrchestratorTool

func WithOrchestratorTool(agents ...*Agent) Option

func WithOutputTool

func WithOutputTool[T any]() Option

func WithReasoning

func WithReasoning(config *Reasoning) Option

func WithRejections

func WithRejections(calls ...string) Option

WithRejections creates approver which rejects specific calls

func WithSpecialistTool

func WithSpecialistTool(agents ...*Agent) Option

func WithStorageReadTool

func WithStorageReadTool(storage Storage) Option

func WithStorageTools

func WithStorageTools(storage Storage) Option

func WithStructuredOutput

func WithStructuredOutput() Option

func WithSystemMessage

func WithSystemMessage(text string) Option

func WithTag

func WithTag(tags ...string) Option

func WithTemperature

func WithTemperature(temperature float32) Option

func WithTool

func WithTool(tool Tool, fn func(context.Context, []byte) (any, error)) Option

func WithToolParallelism

func WithToolParallelism(limit int) Option

func WithToolset

func WithToolset(tools Toolset) Option

func WithTopK

func WithTopK(topK int32) Option

func WithTopP

func WithTopP(topP float32) Option

func WithUserMessage

func WithUserMessage(text string) Option

func WithValues

func WithValues(values map[string]any) Option

func WithoutCache

func WithoutCache() Option

type OptionLoader

type OptionLoader func(ctx context.Context, agent *Agent) error

OptionLoader is called in the beginning of the agentic loop to load dynamic options

type Output

type Output struct {
	Payload any
}

Output error communicates, the final tool has been called, and it has produced the result (output). This is a sentinel error which stops agentic loop to communicate result immediately.

func (Output) Error

func (Output) Error() string

type Reasoning

type Reasoning struct {
	Enabled bool
	Budget  int
	Effort  string // "low", "medium", "high" (OpenAI specific)
}

type Skill

type Skill struct {
	SkillID string
	Type    string
	Version string
}

type StaticMemory

type StaticMemory struct {
	// contains filtered or unexported fields
}

StaticMemory keeps all messages in-memory.

func NewStaticMemory

func NewStaticMemory() *StaticMemory

func (*StaticMemory) Append

func (m *StaticMemory) Append(ctx context.Context, msg Message) error

func (*StaticMemory) List

func (m *StaticMemory) List() []Message

type StaticToolset

type StaticToolset struct {
	// contains filtered or unexported fields
}

func NewStaticToolset

func NewStaticToolset() *StaticToolset

func (*StaticToolset) Add

func (t *StaticToolset) Add(tool Tool, handler ToolHandlerFunc)

func (*StaticToolset) Call

func (t *StaticToolset) Call(ctx context.Context, function string, args []byte) (any, error)

func (*StaticToolset) List

func (t *StaticToolset) List() []Tool

type Storage

type Storage interface {
	Exists(ctx context.Context, filename string) (bool, error)
	Read(ctx context.Context, filename string) ([]byte, error)
	Write(ctx context.Context, filename string, content []byte) error
	Delete(ctx context.Context, filename string) error
}

Storage provides an interface to interact with "persistent" storage. This interface is used by set of tools which allow agent to create persistent objects, like content or code snippets.

type StreamChunkType

type StreamChunkType int
const (
	StreamChunkTypeText                StreamChunkType = iota // a text delta
	StreamChunkTypeToolCallStart                              // the start of a new tool call (just call id and tool name)
	StreamChunkTypeToolCallDelta                              // a delta in tool call arguments
	StreamChunkTypeToolCallExecute                            // a tool is being executed (comes from agent, not LLM)
	StreamChunkTypeToolCallComplete                           // a tool has finished (comes from agent, not LLM)
	StreamChunkTypeReasoning                                  // thinking content delta (extended reasoning)
	StreamChunkTypeSignature                                  // thinking signature for verification
	StreamChunkTypeServerToolCallStart                        // built-in tool call start (web_search, bash, etc.)
	StreamChunkTypeServerToolCallDelta                        // built-in tool call arguments delta
	StreamChunkTypeToolResult                                 // inline tool result from server
	StreamChunkTypeUsage                                      // usage statistics update
	StreamChunkTypeFinish                                     // the completion has finished
)

func (StreamChunkType) String

func (s StreamChunkType) String() string

type Streamer

type Streamer interface {
	Stream(ctx context.Context, chunk Chunk) error
}

type SystemMessage

type SystemMessage struct {
	Content string `json:"content"`
}

func NewSystemMessage

func NewSystemMessage(text string) SystemMessage

type Tool

type Tool struct {
	Name         string
	Type         string
	Description  string
	InputSchema  *jsonschema.Schema
	OutputSchema *jsonschema.Schema
	DeferLoading bool
}

type ToolApprovalRequest

type ToolApprovalRequest struct {
	Calls []ToolCall `json:"calls,omitempty"`
}

func (ToolApprovalRequest) Error

func (r ToolApprovalRequest) Error() string

type ToolCall

type ToolCall struct {
	ID        string `json:"id,omitempty"`
	Name      string `json:"name,omitempty"`
	Arguments string `json:"arguments,omitempty"`
}

type ToolCallApproval

type ToolCallApproval int
const (
	ToolCallUndecided ToolCallApproval = iota
	ToolCallApproved
	ToolCallRejected
)

type ToolChoice

type ToolChoice int

ToolChoice represents how the model should use tools during completion.

const (
	// ToolChoiceAuto allows the model to decide whether to use tools
	ToolChoiceAuto ToolChoice = iota
	// ToolChoiceRequired forces the model to use at least one tool
	ToolChoiceRequired
	// ToolChoiceNone prevents the model from using any tools
	ToolChoiceNone
)

func (ToolChoice) String

func (t ToolChoice) String() string

String returns the string representation of ToolChoice for debugging.

type ToolError

type ToolError struct {
	CallID string `json:"call_id"`
	Error  string `json:"error"`
}

func NewToolError

func NewToolError(callID string, err string) ToolError

func (ToolError) String

func (c ToolError) String() string

type ToolHandlerFunc

type ToolHandlerFunc func(context.Context, []byte) (any, error)

type ToolResult

type ToolResult struct {
	CallID string `json:"call_id"`
	Result any    `json:"result"`
}

func NewToolResult

func NewToolResult(callID string, result any) ToolResult

func (ToolResult) String

func (c ToolResult) String() string

type Toolset

type Toolset interface {
	Call(ctx context.Context, function string, args []byte) (any, error)
	List() []Tool
}

type UserMessage

type UserMessage struct {
	Content string `json:"content"`
}

func LastMessageAsUser

func LastMessageAsUser(memory Memory) (UserMessage, bool)

func NewUserMessage

func NewUserMessage(text string) UserMessage

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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