agentpod

package module
v0.0.0-...-c10a002 Latest Latest
Warning

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

Go to latest
Published: Jun 22, 2025 License: MIT Imports: 16 Imported by: 0

README

AgentPod

AgentPod was started as a simple agent framework in python which is being rewritten in Go for the sole purpose of using it in Agent Berlin. The upside of that is, it's been used in production handling scale and is battle tested. The downside is that it's very strict in the design and only has the features we needed for Berlin to work.

Documentation

Overview

Package agent provides the main Agent orchestrator, which uses LLM & Skills to process data.

Start of Selection

Package memory provides an interface for storing and retrieving conversation data.

Package session provides the Session struct for per-conversation state, along with methods for handling user messages and producing agent outputs.

Package agent - tool.go Defines the Tool interface and basic stubs for tool usage.

Index

Constants

View Source
const (
	GPT4oInputRate      = 2.5
	GPT4oOutputRate     = 10.0
	GPT4oMiniInputRate  = 0.15
	GPT4oMiniOutputRate = 0.60
	O3MiniInputRate     = 1.10
	O3MiniOutputRate    = 4.40
	O1InputRate         = 15.0
	O1OutputRate        = 60.0
	O3InputRate         = 10.0
	O3OutputRate        = 40.0
	O4MiniInputRate     = 1.10
	O4MiniOutputRate    = 4.40
	GPT41InputRate      = 2.0
	GPT41OutputRate     = 8.0
	GPT41MiniInputRate  = 0.40
	GPT41MiniOutputRate = 1.60
	GPT41NanoInputRate  = 0.10
	GPT41NanoOutputRate = 0.40
)

Pricing constants for GPT-4o and GPT-4o-mini and O3-mini(in dollars per million tokens)

Variables

View Source
var (
	ErrSessionClosed = errors.New("session has been closed")
	ErrNoMessage     = errors.New("no message available")
	ErrNoSessionID   = errors.New("session ID not found in context or is not a string")
)
View Source
var ModelPricings = map[string]TokenRates{
	"gpt-4o": {
		Input:  GPT4oInputRate,
		Output: GPT4oOutputRate,
	},
	"gpt-4o-mini": {
		Input:  GPT4oMiniInputRate,
		Output: GPT4oMiniOutputRate,
	},
	"o3-mini": {
		Input:  O3MiniInputRate,
		Output: O3MiniOutputRate,
	},
	"o1": {
		Input:  O1InputRate,
		Output: O1OutputRate,
	},
	"o3": {
		Input:  O3InputRate,
		Output: O3OutputRate,
	},
	"o4-mini": {
		Input:  O4MiniInputRate,
		Output: O4MiniOutputRate,
	},
	"gpt-4.1": {
		Input:  GPT41InputRate,
		Output: GPT41OutputRate,
	},
	"gpt-4.1-mini": {
		Input:  GPT41MiniInputRate,
		Output: GPT41MiniOutputRate,
	},
	"gpt-4.1-nano": {
		Input:  GPT41NanoInputRate,
		Output: GPT41NanoOutputRate,
	},
	"azure/gpt-4o": {
		Input:  GPT4oInputRate,
		Output: GPT4oOutputRate,
	},
	"azure/gpt-4o-mini": {
		Input:  GPT4oMiniInputRate,
		Output: GPT4oMiniOutputRate,
	},
	"azure/o3-mini": {
		Input:  O3MiniInputRate,
		Output: O3MiniOutputRate,
	},
	"azure/o1": {
		Input:  O1InputRate,
		Output: O1OutputRate,
	},
	"azure/o3": {
		Input:  O3InputRate,
		Output: O3OutputRate,
	},
	"azure/o4-mini": {
		Input:  O4MiniInputRate,
		Output: O4MiniOutputRate,
	},
	"azure/gpt-4.1": {
		Input:  GPT41InputRate,
		Output: GPT41OutputRate,
	},
	"azure/gpt-4.1-mini": {
		Input:  GPT41MiniInputRate,
		Output: GPT41MiniOutputRate,
	},
	"azure/gpt-4.1-nano": {
		Input:  GPT41NanoInputRate,
		Output: GPT41NanoOutputRate,
	},
}

ModelPricings is a map of model names to their pricing information

Functions

func AssistantMessage

func AssistantMessage(content string) openai.ChatCompletionMessageParamUnion

func DeveloperMessage

func DeveloperMessage(content string) openai.ChatCompletionMessageParamUnion

func GenerateSchema

func GenerateSchema[T any]() interface{}

func GetMessageText

func GetMessageText(message openai.ChatCompletionMessageParamUnion) (string, error)

GetMessageText extracts the plain text content from an OpenAI chat message of any type (user, assistant, or developer message)

func MessageWhenToolError

func MessageWhenToolError(toolCallID string) openai.ChatCompletionMessageParamUnion

func MessageWhenToolErrorWithRetry

func MessageWhenToolErrorWithRetry(errorString string, toolCallID string) openai.ChatCompletionMessageParamUnion

func NewIgnorableError

func NewIgnorableError(format string, a ...interface{}) error

NewIgnorableError creates a new instance of IgnorableError.

func NewRetryableError

func NewRetryableError(format string, a ...interface{}) error

NewRetryableError creates a new instance of RetryableError.

func UserMessage

func UserMessage(content string) openai.ChatCompletionMessageParamUnion

TODO Remove all three and use openai functions directly

Types

type Agent

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

Agent orchestrates calls to the LLM, uses Skills/Tools, and determines how to respond.

func NewAgent

func NewAgent(prompt string, skills []Skill) *Agent

NewAgent creates an Agent by adding the prompt as a DeveloperMessage.

func (*Agent) ConvertSkillsToTools

func (a *Agent) ConvertSkillsToTools() []openai.ChatCompletionToolParam

TODO - we probably need to have a custom made description for the tool that uses skill.description

func (*Agent) GetLogger

func (a *Agent) GetLogger() *slog.Logger

func (*Agent) GetSkill

func (a *Agent) GetSkill(name string) (*Skill, error)

func (*Agent) Run

func (a *Agent) Run(ctx context.Context, llm LLM, messageHistory *MessageList, memoryBlock *MemoryBlock, outUserChannel chan Response)

Run processes a user message through the LLM, executes any requested skills. It returns only after the agent is done. The intermediary messages are sent to the outUserChannel.

func (*Agent) SetLogger

func (a *Agent) SetLogger(logger *slog.Logger)

func (*Agent) SkillContextRunner

func (a *Agent) SkillContextRunner(ctx context.Context, messageHistory *MessageList, llm LLM, memoryBlock *MemoryBlock, skill *Skill, skillToolCall openai.ChatCompletionMessageToolCall) (*openai.ChatCompletionToolMessageParam, error)

func (*Agent) StopTool

func (a *Agent) StopTool() openai.ChatCompletionToolParam

type ContextKey

type ContextKey string

Define a custom type for context keys

type CostDetails

type CostDetails struct {
	InputTokens  int64
	OutputTokens int64
	TotalCost    float64
}

CostDetails represents detailed cost information for a session

type IgnorableError

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

IgnorableError is the custom type for errors that can be ignored.

func (*IgnorableError) Error

func (e *IgnorableError) Error() string

Error returns the error message for IgnorableError.

type InMemoryStorage

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

InMemoryStorage implements the Storage interface using in-memory data structures

func NewInMemoryStorage

func NewInMemoryStorage() *InMemoryStorage

NewInMemoryStorage creates a new instance of InMemoryStorage

func (*InMemoryStorage) AddAssistantMessage

func (s *InMemoryStorage) AddAssistantMessage(ctx context.Context, assistantMessage string) error

AddAssistantMessage adds the assistant message to the existing conversation

func (*InMemoryStorage) AddUserMessage

func (s *InMemoryStorage) AddUserMessage(ctx context.Context, userMessage string) error

AddUserMessage creates a new conversation with the user message

func (*InMemoryStorage) GetConversations

func (s *InMemoryStorage) GetConversations(ctx context.Context, limit int, offset int) (*MessageList, error)

GetConversations returns the conversations in the order they were created

type KeywordsAIClient

type KeywordsAIClient struct {
	APIKey  string
	BaseURL string
	// contains filtered or unexported fields
}

func NewKeywordsAIClient

func NewKeywordsAIClient(apiKey string, baseURL string, strongModel string, cheapModel string) *KeywordsAIClient

func (*KeywordsAIClient) CheapModel

func (c *KeywordsAIClient) CheapModel() string

func (*KeywordsAIClient) New

TODO failures like too long, non-processable etc from the LLM needs to be handled

func (*KeywordsAIClient) NewResponse

NewResponse creates a new response using OpenAI's Response API

func (*KeywordsAIClient) StrongModel

func (c *KeywordsAIClient) StrongModel() string

type LLM

type LLM interface {
	// New issues a non-streaming chat completion request.
	New(ctx context.Context, params openai.ChatCompletionNewParams) (*openai.ChatCompletion, error)
	// NewStreaming issues a streaming chat completion request, returning
	// an ssestream.Stream to consume the chunks.
	NewStreaming(ctx context.Context, params openai.ChatCompletionNewParams) *ssestream.Stream[openai.ChatCompletionChunk]

	StrongModel() string
	CheapModel() string
}

LLM defines the minimal contract required by the agent runtime to interact with a language-model provider. Implementations may add additional helper methods but only the operations below are relied upon by the rest of the codebase.

type Memory

type Memory interface {
	Retrieve(ctx context.Context) (*MemoryBlock, error)
}

Memory is an interface for reading/writing conversation data or other context.

type MemoryBlock

type MemoryBlock struct {
	Items map[string]MemoryValue // For storing multiple key-value pairs
	// contains filtered or unexported fields
}

MemoryBlock represents a key-value store where values can be strings or nested MemoryBlocks

func NewMemoryBlock

func NewMemoryBlock() *MemoryBlock

NewMemoryBlock creates a new MemoryBlock with initialized map

func (*MemoryBlock) AddBlock

func (mb *MemoryBlock) AddBlock(key string, value *MemoryBlock)

AddBlock adds a MemoryBlock value for the given key

func (*MemoryBlock) AddString

func (mb *MemoryBlock) AddString(key string, value string)

AddString adds a string value for the given key

func (*MemoryBlock) Delete

func (mb *MemoryBlock) Delete(key string) bool

Delete removes a key-value pair from the MemoryBlock Returns true if the key was found and deleted, false otherwise

func (*MemoryBlock) Exists

func (mb *MemoryBlock) Exists(key string) bool

Exists checks if a key exists in the MemoryBlock

func (*MemoryBlock) Parse

func (mb *MemoryBlock) Parse() string

Parse generates a string representation of the MemoryBlock recursively parsing any nested MemoryBlocks into XML-style format

type MemoryValue

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

MemoryValue represents a value that can be either a string or a nested MemoryBlock

func NewBlockValue

func NewBlockValue(block *MemoryBlock) MemoryValue

NewBlockValue creates a MemoryValue containing a MemoryBlock

func NewStringValue

func NewStringValue(s string) MemoryValue

NewStringValue creates a MemoryValue containing a string

func (MemoryValue) AsBlock

func (mv MemoryValue) AsBlock() *MemoryBlock

AsBlock returns the MemoryBlock value if type is BlockType, nil otherwise

func (MemoryValue) AsString

func (mv MemoryValue) AsString() string

AsString returns the string value if type is StringType, empty string otherwise

func (MemoryValue) IsBlock

func (mv MemoryValue) IsBlock() bool

IsBlock returns true if the value is a MemoryBlock

func (MemoryValue) IsString

func (mv MemoryValue) IsString() bool

IsString returns true if the value is a string

func (MemoryValue) Type

func (mv MemoryValue) Type() ValueType

Type returns the type of the value

type MessageList

type MessageList struct {
	Messages []openai.ChatCompletionMessageParamUnion
}

MessageList holds an ordered collection of LLMMessage to preserve the history.

func CompileConversationHistory

func CompileConversationHistory(ctx context.Context, storage Storage) (*MessageList, error)

CompileConversationHistory builds the message history for the LLM request now it fetches the last 5 messages but in the future, we'lll do smart things here like old message summarization etc

func NewMessageList

func NewMessageList() *MessageList

func (*MessageList) Add

Add appends one or more new messages to the MessageList in a FIFO order.

func (*MessageList) AddFirstDeveloperMessage

func (ml *MessageList) AddFirstDeveloperMessage(msg openai.ChatCompletionMessageParamUnion)

AddFirstDeveloperMessage prepends a developer message to the message list. It panics if the provided message is not a developer message.

func (*MessageList) All

func (*MessageList) Clear

func (ml *MessageList) Clear()

func (*MessageList) CloneWithoutDeveloperMessages

func (ml *MessageList) CloneWithoutDeveloperMessages() *MessageList

CloneWithoutDeveloperMessages returns a copy of the MessageList that excludes any developer or system messages, preserving the original order of the remaining messages. This is useful when sending conversation history back to the LLM, where developer/system prompts should not be repeated.

func (*MessageList) Len

func (ml *MessageList) Len() int

func (*MessageList) PrintMessages

func (ml *MessageList) PrintMessages()

PrintMessages is for debugging purposes

func (*MessageList) ReplaceAt

func (ml *MessageList) ReplaceAt(index int, newMsg openai.ChatCompletionMessageParamUnion) error

type Response

type Response struct {
	Content string
	Type    ResponseType
}

Response represents a communication unit from the Agent to the caller/UI.

type ResponseType

type ResponseType string
const (
	ResponseTypeEnd   ResponseType = "end"
	ResponseTypeError ResponseType = "error"
)

type RetryableError

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

RetryableError is the custom type for errors that can be retried.

func (*RetryableError) Error

func (e *RetryableError) Error() string

Error returns the error message for RetryableError.

type Session

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

Session holds ephemeral conversation data & references to global resources.

func NewSession

func NewSession(ctx context.Context, llm LLM, mem Memory, ag *Agent) *Session

NewSession constructs a session with references to shared LLM & memory, but isolated state.

func (*Session) Close

func (s *Session) Close()

Close ends the session lifecycle and releases any resources if needed.

func (*Session) Cost

func (s *Session) Cost() (*CostDetails, bool)

Cost returns the accumulated cost of the session. It calculates the cost based on the total input and output tokens and the pricing for the session's model.

func (*Session) ID

func (s *Session) ID() string

func (*Session) In

func (s *Session) In(userMessage string)

In processes incoming user messages. Could queue or immediately handle them.

func (*Session) Out

func (s *Session) Out() Response

Out retrieves the next message from the output channel, blocking until a message is available.

type Skill

type Skill struct {
	Name            string
	ToolDescription string // used as the tool description when the skill is presented as a tool
	SystemPrompt    string // used as the system prompt when the skill is running as an Agent
	Tools           []Tool
}

Skill holds a set of tools and a domain-specific prompt/description.

func (*Skill) GetTool

func (s *Skill) GetTool(name string) (Tool, error)

func (*Skill) GetTools

func (s *Skill) GetTools() []openai.ChatCompletionToolParam

func (*Skill) Spec

func (s *Skill) Spec() string

Spec converts the skill and all the tools into a string so we can pass the spec into LLM

type Storage

type Storage interface {
	// conversation related
	// GetConversations should return the conversations in the order of creating them.
	// The first message in the returned list must be older than the second message in the list.
	// Be careful on applying limit and offset. If the limit is 10 and offset is 5, it means
	// we'll do the offset from the end of the conversation (i.e., skip the last 5 conversations
	// in the whole chat history) and then take the 10 messages from that point backwards and
	// return a list of those 10 messages arranged in the described order.
	GetConversations(ctx context.Context, limit int, offset int) (*MessageList, error)
	AddUserMessage(ctx context.Context, userMessage string) error
	AddAssistantMessage(ctx context.Context, assistantMessage string) error
}

Storage is an interface that abstracts the user storage layer. For agentpod, a conversation is a pair of user messages and assistant messages.

type TokenRates

type TokenRates struct {
	Input  float64
	Output float64
}

type Tool

type Tool interface {
	Name() string
	Description() string
	OpenAI() []openai.ChatCompletionToolParam
	Execute(ctx context.Context, args map[string]interface{}) (string, error)
}

type ValueType

type ValueType int

ValueType represents the type of a memory value

const (
	StringType ValueType = iota
	BlockType
)

Directories

Path Synopsis
cmd
agentpod command
Common utility functions
Common utility functions

Jump to

Keyboard shortcuts

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