goagent

package module
v0.3.1 Latest Latest
Warning

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

Go to latest
Published: Mar 29, 2026 License: Apache-2.0 Imports: 9 Imported by: 3

README

goagent

⚠️ Work in Progress — API may change without notice. Not production-ready yet.

A minimal, Go-idiomatic framework for building AI agents with a ReAct loop and pluggable model providers.

Go version License

Install

git clone https://github.com/Germanblandin1/goagent.git

go get will be available once the first version is tagged.

Quickstart

agent, err := goagent.New(
    goagent.WithProvider(ollama.New()),
    goagent.WithModel("qwen3"),
)
if err != nil {
    log.Fatal(err)
}

answer, err := agent.Run(context.Background(), "What is the capital of France?")

Package layout

goagent/              Core — Agent, ReAct loop, interfaces
├── mcp/              MCP client + server (stdio and SSE transports)
├── memory/           Short-term and long-term memory
│   ├── storage/      InMemory storage
│   ├── policy/       FixedWindow, TokenWindow, NoOp
│   └── vector/       VectorStore, chunkers, similarity, size estimators
├── providers/
│   ├── anthropic/    Anthropic Messages API (Claude)
│   ├── ollama/       Local Ollama via OpenAI-compatible API (+ embedder)
│   └── voyage/       Voyage AI embedder
├── examples/
│   ├── calculator/           Tool use with arithmetic
│   ├── chatbot/              Multi-turn conversation
│   ├── chatbot-persistent/   Persistent memory across sessions
│   └── chatbot-mcp-fs/       Filesystem access via MCP stdio
└── internal/testutil/        Shared mocks

Core concepts

ReAct loop

Agent.Run alternates between calling the model and executing tool calls until the model produces a final answer, the context is cancelled, or the iteration budget is exhausted. All tool calls within a single turn are dispatched concurrently.

                    ┌──────────────────────┐
                    │        prompt        │
                    └──────────┬───────────┘
                               │
                    ┌──────────▼───────────┐
             ┌─────▶│        model         │◀── OnIterationStart
             │      └──────────┬───────────┘
             │                 │
             │      ┌──────────▼───────────────────────┐
             │      │    response has tool calls?       │
             │      └──────────┬────────────┬───────────┘
             │                yes           no
             │      ┌──────────▼──────┐  ┌──▼─────────────┐
             │      │ dispatch tools  │  │     answer      │
             │      │  (concurrent)   │  │    (return)     │
             │      │  OnToolCall     │  └────────────────-┘
             │      │  OnToolResult   │       OnResponse
             │      └──────────┬──────┘
             │                 │
             └─────────────────┘  (next iteration)
Tools

Implement the Tool interface or use the ToolFunc helper:

echo := goagent.ToolFunc("echo", "Returns the input text.",
    map[string]any{
        "type": "object",
        "properties": map[string]any{"text": map[string]any{"type": "string"}},
        "required": []string{"text"},
    },
    func(_ context.Context, args map[string]any) (string, error) {
        return args["text"].(string), nil
    },
)

agent, _ := goagent.New(
    goagent.WithProvider(ollama.New()),
    goagent.WithModel("qwen3"),
    goagent.WithTool(echo),
)
MCP (Model Context Protocol)

Connect external tool servers over stdio or SSE. The agent discovers all tools automatically at startup.

// Spawn a local MCP server as a subprocess
agent, err := goagent.New(
    goagent.WithProvider(ollama.New()),
    goagent.WithModel("qwen3"),
    mcp.WithStdio("./my-mcp-server", "--flag"),
)
if err != nil {
    log.Fatal(err) // connection or discovery error
}
defer agent.Close()

// Connect to a running HTTP+SSE server
agent, err := goagent.New(
    goagent.WithProvider(anthropic.New()),
    mcp.WithSSE("http://localhost:8080/sse"),
)

Multiple servers can be attached in a single New call. Build your own MCP server with mcp.NewServer:

s := mcp.NewServer("my-tools", "1.0.0")
s.MustAddTool("echo", "Returns the input unchanged", nil,
    func(_ context.Context, args map[string]any) (string, error) {
        return args["text"].(string), nil
    },
)
log.Fatal(s.ServeStdio())
Memory
mem := memory.NewShortTerm(
    memory.WithStorage(storage.NewInMemory()),
    memory.WithPolicy(policy.NewFixedWindow(20)),
)

agent, _ := goagent.New(
    goagent.WithProvider(ollama.New()),
    goagent.WithShortTermMemory(mem),
)

Available policies: NewNoOp(), NewFixedWindow(n), NewTokenWindow(maxTokens).

Long-term memory enables semantic retrieval across sessions. It requires a VectorStore and an Embedder; both are provided by the framework:

store := vector.NewInMemoryStore()

embedder := ollama.NewEmbedder(
    ollama.WithEmbedModel("nomic-embed-text"),
)
// or: voyage.NewEmbedder(voyage.WithEmbedModel("voyage-3"))

ltm, err := memory.NewLongTerm(
    memory.WithVectorStore(store),
    memory.WithEmbedder(embedder),
)

agent, _ := goagent.New(
    goagent.WithName("my-agent"),         // session namespace
    goagent.WithProvider(ollama.New()),
    goagent.WithShortTermMemory(mem),
    goagent.WithLongTermMemory(ltm),
)

For long documents, plug in a chunker before embedding:

ltm, err := memory.NewLongTerm(
    memory.WithVectorStore(store),
    memory.WithEmbedder(embedder),
    memory.WithChunker(vector.NewTextChunker(
        vector.WithMaxSize(500),
        vector.WithOverlap(50),
    )),
)
Extended thinking & effort
// Extended thinking — fixed budget
goagent.WithThinking(10_000)

// Extended thinking — adaptive (model decides)
goagent.WithAdaptiveThinking()

// Effort level
goagent.WithEffort("medium")  // "high" | "medium" | "low" | "" (model default)

Ollama captures reasoning from the reasoning field or <think>…</think> tags automatically.

Observability hooks
goagent.WithHooks(goagent.Hooks{
    OnIterationStart: func(i int)                                               { /* ... */ },
    OnThinking:       func(text string)                                         { /* ... */ },
    OnToolCall:       func(name string, args map[string]any)                    { /* ... */ },
    OnToolResult:     func(name string, _ []goagent.ContentBlock, d time.Duration, err error) { /* ... */ },
    OnResponse:       func(text string, iterations int)                         { /* ... */ },
})
Multimodal input
answer, err := agent.RunBlocks(ctx,
    goagent.TextBlock("Describe this image"),
    goagent.ImageBlock(imgData, "image/png"),
)

Configuration reference

Option Default Description
WithProvider(p) Required. Model backend
WithModel(m) Required. Model identifier
WithTool(t) Register a tool (repeatable)
WithSystemPrompt(s) System instruction for every run
WithMaxIterations(n) 10 Max ReAct iterations
WithThinking(budget) Extended thinking, fixed token budget
WithAdaptiveThinking() Extended thinking, model-chosen budget
WithEffort(level) "" "high", "medium", "low", or ""
WithHooks(h) Observability callbacks
WithName(name) Agent identity / session namespace for long-term memory
WithShortTermMemory(m) Conversation history within a session
WithLongTermMemory(m) Semantic retrieval across sessions
WithWritePolicy(p) StoreAlways What to persist to long-term memory
WithLongTermTopK(k) 3 Messages to retrieve from long-term memory
WithShortTermTraceTools(b) true Include tool traces in short-term history
WithLogger(l) slog.Default() Structured logger

Error handling

var maxErr *goagent.MaxIterationsError
var provErr *goagent.ProviderError

switch {
case errors.As(err, &maxErr):
    fmt.Printf("gave up after %d iterations\n", maxErr.Iterations)
case errors.As(err, &provErr):
    fmt.Printf("provider error: %v\n", provErr.Cause)
}
Error When
*ProviderError Provider returned an error
*MaxIterationsError Iteration budget exhausted
*ToolExecutionError A tool failed
*mcp.MCPConnectionError MCP server unreachable at startup
*mcp.MCPDiscoveryError MCP tool listing failed
ErrToolNotFound Requested tool does not exist

Providers

Provider Package Notes
Anthropic providers/anthropic Reads ANTHROPIC_API_KEY; supports text, images (5 MB), PDFs (32 MB)
Ollama providers/ollama Default http://localhost:11434/v1; supports text and images; includes NewEmbedder
Voyage AI providers/voyage Reads VOYAGE_API_KEY; embedder only (e.g. "voyage-3")

License

Apache 2.0 — see LICENSE.

Documentation

Overview

Package goagent provides a Go-idiomatic framework for building AI agents with a ReAct loop and pluggable providers.

Overview

goagent orchestrates the interaction between a language model and a set of tools. On each iteration of the ReAct loop the model either produces a final text answer or requests one or more tool calls. The agent dispatches those calls in parallel, feeds the results back, and repeats until the model stops or the iteration budget (WithMaxIterations) is exhausted.

The framework is built around three small interfaces:

  • Provider — wraps an LLM backend (Ollama, Anthropic, OpenAI-compatible, …).
  • Tool — a capability the model can invoke (calculator, web search, …).
  • ShortTermMemory / LongTermMemory — optional conversation persistence.

All configuration uses functional options passed to New.

Basic usage

provider := ollama.New(ollama.WithBaseURL("http://localhost:11434"))

add := goagent.ToolFunc("add", "Sum two numbers",
    map[string]any{
        "type": "object",
        "properties": map[string]any{
            "a": map[string]any{"type": "number"},
            "b": map[string]any{"type": "number"},
        },
        "required": []string{"a", "b"},
    },
    func(ctx context.Context, args map[string]any) (string, error) {
        a, _ := args["a"].(float64)
        b, _ := args["b"].(float64)
        return fmt.Sprintf("%g", a+b), nil
    },
)

agent := goagent.New(
    goagent.WithProvider(provider),
    goagent.WithTool(add),
    goagent.WithMaxIterations(5),
)

answer, err := agent.Run(ctx, "What is 2 + 3?")

Multimodal content

[RunBlocks] accepts images and documents alongside text:

answer, err := agent.RunBlocks(ctx,
    goagent.ImageBlock(pngBytes, "image/png"),
    goagent.TextBlock("Describe this image"),
)

Memory

By default each Agent.Run call is stateless. To maintain conversation context across calls, configure a ShortTermMemory via WithShortTermMemory. For semantic retrieval across sessions, add a LongTermMemory via WithLongTermMemory. Implementations live in the memory sub-package.

Sub-packages

  • memory — ShortTermMemory and LongTermMemory with pluggable storage and policies.
  • memory/storage — persistence backends (in-memory; bring your own).
  • memory/policy — read-time filters: FixedWindow, TokenWindow, NoOp.
  • providers/anthropic — Provider for the Anthropic Messages API (Claude).
  • providers/ollama — Provider for Ollama (OpenAI-compatible API).
  • internal/testutil — mock implementations for testing agents.
Example

Example demonstrates creating an Agent with a mock provider and running it.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/Germanblandin1/goagent"
	"github.com/Germanblandin1/goagent/internal/testutil"
)

func main() {
	agent, err := goagent.New(
		goagent.WithProvider(testutil.NewMockProvider(
			goagent.CompletionResponse{
				Message:    goagent.AssistantMessage("4"),
				StopReason: goagent.StopReasonEndTurn,
			},
		)),
	)
	if err != nil {
		log.Fatal(err)
	}

	result, err := agent.Run(context.Background(), "what is 2+2?")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(result)
}
Output:
4

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrInvalidMediaType = errors.New("invalid media type")

ErrInvalidMediaType is returned when a content block has a MIME type that is not in the set of supported types for its content kind.

View Source
var ErrToolNotFound = errors.New("tool not found")

ErrToolNotFound is returned when the model requests a tool that was not registered with the agent.

View Source
var ErrUnsupportedContent = errors.New("unsupported content type")

ErrUnsupportedContent is returned when the provider does not support a content type present in the request (e.g. documents on an OpenAI-compatible provider, or images on a text-only model).

Functions

func TextFrom

func TextFrom(blocks []ContentBlock) string

TextFrom extracts and concatenates the text from a slice of ContentBlocks. Non-text blocks are ignored. Adjacent text values are separated by a space.

Intended as a convenience for Embedder implementations that only handle text:

func (e *myEmbedder) Embed(ctx context.Context, content []goagent.ContentBlock) ([]float32, error) {
    return e.client.Embed(ctx, goagent.TextFrom(content))
}
Example

ExampleTextFrom shows how TextFrom extracts text from a mixed slice of ContentBlocks, ignoring non-text blocks like images.

package main

import (
	"fmt"

	"github.com/Germanblandin1/goagent"
)

func main() {
	blocks := []goagent.ContentBlock{
		goagent.TextBlock("hello"),
		goagent.ImageBlock([]byte{0xFF}, "image/png"),
		goagent.TextBlock("world"),
	}
	fmt.Println(goagent.TextFrom(blocks))
}
Output:
hello world

func ValidDocumentMediaType

func ValidDocumentMediaType(mediaType string) bool

ValidDocumentMediaType reports whether mediaType is a supported document MIME type.

func ValidImageMediaType

func ValidImageMediaType(mediaType string) bool

ValidImageMediaType reports whether mediaType is a supported image MIME type.

Types

type Agent

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

Agent runs a ReAct loop: it alternates between calling the LLM provider and dispatching tool calls until the model produces a final answer or the iteration budget is exhausted.

By default an Agent is stateless — each Run call is independent and carries no memory of previous calls. To persist conversation history across calls, configure a ShortTermMemory via WithShortTermMemory. For semantic retrieval across sessions, configure a LongTermMemory via WithLongTermMemory.

Use WithName to assign a stable identity to the agent. When a LongTermMemory is configured, the name is used as the session namespace so that multiple agents sharing the same memory backend can only see their own entries.

Concurrency

Agent itself holds no mutable state after construction; all fields are set once by New and never written again. Whether concurrent calls to Run are safe depends entirely on the implementations injected by the caller:

  • Provider: safe if the implementation is. All built-in providers are.
  • ShortTermMemory: concurrent Run calls produce undefined message ordering. See WithShortTermMemory.
  • LongTermMemory: concurrent Retrieve and Store calls produce undefined ordering. See WithLongTermMemory.
  • Logger: slog.Logger is documented as safe for concurrent use.

If no memory backend is configured (the default), Run is safe to call from multiple goroutines simultaneously.

func New

func New(opts ...Option) (*Agent, error)

New creates an Agent with the provided options applied over sensible defaults. A Provider must be supplied via WithProvider before calling Run.

If any WithMCP* options are present, New establishes the MCP connections, discovers their tools, and returns an error if any connection fails. On error, all already-opened connections are closed before returning.

Call Close to release MCP connections when the agent is no longer needed:

agent, err := goagent.New(...)
if err != nil {
    log.Fatal(err)
}
defer agent.Close()

func (*Agent) Close

func (a *Agent) Close() error

Close releases all MCP connections opened during New. For stdio transports: terminates the subprocess. For SSE transports: closes the HTTP connection. Idempotent — multiple calls are safe. Errors are logged at Warn level; the method always returns nil.

func (*Agent) Run

func (a *Agent) Run(ctx context.Context, prompt string) (string, error)

Run executes the ReAct loop for the given prompt and returns the model's final text response.

This is the main entry point for text interactions. For sending images, documents, or other multimodal content, use RunBlocks.

If a ShortTermMemory is configured via WithShortTermMemory, Run loads the conversation history before calling the provider and persists the new turn after producing an answer (or exhausting iterations).

If a LongTermMemory is configured via WithLongTermMemory, Run retrieves semantically relevant context before building the request, and stores the completed turn (subject to WritePolicy) after each Run.

Memory write failures are logged at Warn level and do not cause Run to return an error.

Possible errors:

  • *ProviderError — the provider returned an error
  • *MaxIterationsError — the iteration budget was exhausted
  • context.Canceled / context.DeadlineExceeded — context was cancelled
Example (WithMemory)

ExampleAgent_Run_withMemory shows that completed turns are persisted to ShortTermMemory and available for the next Run call.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/Germanblandin1/goagent"
	"github.com/Germanblandin1/goagent/internal/testutil"
	"github.com/Germanblandin1/goagent/memory"
)

func main() {
	mem := memory.NewShortTerm()

	agent, err := goagent.New(
		goagent.WithProvider(testutil.NewMockProvider(
			goagent.CompletionResponse{
				Message:    goagent.AssistantMessage("pong"),
				StopReason: goagent.StopReasonEndTurn,
			},
		)),
		goagent.WithShortTermMemory(mem),
	)
	if err != nil {
		log.Fatal(err)
	}

	if _, err := agent.Run(context.Background(), "ping"); err != nil {
		log.Fatal(err)
	}

	msgs, err := mem.Messages(context.Background())
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(len(msgs))
	fmt.Println(msgs[0].TextContent())
	fmt.Println(msgs[1].TextContent())
}
Output:
2
ping
pong
Example (WithTools)

ExampleAgent_Run_withTools shows how a tool is registered and invoked during a ReAct loop. The mock provider first requests a tool call, then produces the final answer after receiving the tool result.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/Germanblandin1/goagent"
	"github.com/Germanblandin1/goagent/internal/testutil"
)

func main() {
	echo := goagent.ToolFunc("echo", "returns the input text unchanged", nil,
		func(_ context.Context, args map[string]any) (string, error) {
			return fmt.Sprintf("%v", args["text"]), nil
		},
	)

	mock := testutil.NewMockProvider(
		// Iteration 1: model requests the echo tool.
		goagent.CompletionResponse{
			Message: goagent.Message{
				Role: goagent.RoleAssistant,
				ToolCalls: []goagent.ToolCall{
					{ID: "call-1", Name: "echo", Arguments: map[string]any{"text": "hello"}},
				},
			},
			StopReason: goagent.StopReasonToolUse,
		},
		// Iteration 2: model produces the final answer.
		goagent.CompletionResponse{
			Message:    goagent.AssistantMessage("hello"),
			StopReason: goagent.StopReasonEndTurn,
		},
	)

	agent, err := goagent.New(
		goagent.WithProvider(mock),
		goagent.WithTool(echo),
	)
	if err != nil {
		log.Fatal(err)
	}

	result, err := agent.Run(context.Background(), "echo hello")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(result)
}
Output:
hello

func (*Agent) RunBlocks

func (a *Agent) RunBlocks(ctx context.Context, blocks ...ContentBlock) (string, error)

RunBlocks executes the ReAct loop with multimodal content and returns the model's final text response.

It accepts one or more ContentBlock in any combination of types. For text-only prompts, prefer Run which is more ergonomic.

Example:

result, err := agent.RunBlocks(ctx,
    goagent.ImageBlock(imgData, "image/png"),
    goagent.TextBlock("What animal is this?"),
)

Possible errors:

  • error if no content blocks are provided
  • ErrInvalidMediaType if a content block has an unsupported MIME type
  • *ProviderError — the provider returned an error
  • *UnsupportedContentError — the provider does not support a content type
  • *MaxIterationsError — the iteration budget was exhausted
  • context.Canceled / context.DeadlineExceeded — context was cancelled
Example

ExampleAgent_RunBlocks shows how to use RunBlocks with multimodal content. Here we send a text block; in practice you would combine text with image or document blocks.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/Germanblandin1/goagent"
	"github.com/Germanblandin1/goagent/internal/testutil"
)

func main() {
	agent, err := goagent.New(
		goagent.WithProvider(testutil.NewMockProvider(
			goagent.CompletionResponse{
				Message:    goagent.AssistantMessage("It's a cat"),
				StopReason: goagent.StopReasonEndTurn,
			},
		)),
	)
	if err != nil {
		log.Fatal(err)
	}

	result, err := agent.RunBlocks(context.Background(),
		goagent.TextBlock("What animal is this?"),
	)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(result)
}
Output:
It's a cat

type CompletionRequest

type CompletionRequest struct {
	// Model is the exact model identifier forwarded to the provider
	// (e.g. "llama3", "qwen3"). Interpretation is provider-specific;
	// the framework passes it through without validation.
	Model string

	// SystemPrompt is the system-level instruction for the model.
	// Providers must forward it using their native mechanism — for
	// OpenAI-compatible APIs this means prepending a system message;
	// for Anthropic it maps to the top-level "system" field.
	// Empty string means no system prompt.
	SystemPrompt string

	// Messages is the conversation history to send, in chronological order.
	// The slice is never nil when sent by Agent, but Provider implementations
	// must handle a nil or empty slice without panicking.
	Messages []Message

	// Tools is the list of tools the model may call during this completion.
	// Nil or empty means no tool use is available for this request.
	// Providers must not error when this field is nil.
	Tools []ToolDefinition

	// Thinking configures extended thinking for this request.
	// nil means thinking is disabled (default behaviour).
	// Providers that do not support thinking must ignore this field.
	Thinking *ThinkingConfig

	// Effort controls the overall effort the model puts into its response,
	// affecting text, tool calls, and thinking (when enabled).
	// Valid values: "high", "medium", "low". Empty string means the model's
	// default (equivalent to "high"). Thinking and Effort are orthogonal —
	// each can be set independently.
	// Providers that do not support effort must ignore this field.
	Effort string
}

CompletionRequest is the input to a provider's Complete call.

type CompletionResponse

type CompletionResponse struct {
	// Message is the model's reply. Role is always RoleAssistant.
	// Content may be empty if the model produced only tool calls.
	// ToolCalls is non-empty when StopReason is StopReasonToolUse.
	Message Message

	// StopReason indicates why the model stopped generating.
	StopReason StopReason

	// Usage reports token consumption for this completion.
	// Providers should populate this when the API returns it;
	// zero values are valid if the backend does not expose token counts.
	Usage Usage
}

CompletionResponse is the output from a provider's Complete call.

type ContentBlock

type ContentBlock struct {
	Type     ContentType
	Text     string
	Image    *ImageData
	Document *DocumentData
	Thinking *ThinkingData
}

ContentBlock represents a unit of content within a message. Exactly one of Text, Image, Document, or Thinking is valid depending on the value of Type. The others are zero value.

Use the helpers TextBlock, ImageBlock, DocumentBlock, and ThinkingBlock to construct content blocks instead of building the struct directly.

func DocumentBlock

func DocumentBlock(data []byte, mediaType, title string) ContentBlock

DocumentBlock creates a document ContentBlock from raw bytes. mediaType must be one of: "application/pdf", "text/plain". title is optional — if non-empty, it gives the model context about the document.

func ImageBlock

func ImageBlock(data []byte, mediaType string) ContentBlock

ImageBlock creates an image ContentBlock from raw bytes. mediaType must be one of: "image/jpeg", "image/png", "image/gif", "image/webp".

func TextBlock

func TextBlock(s string) ContentBlock

TextBlock creates a text ContentBlock.

func ThinkingBlock

func ThinkingBlock(thinking, signature string) ContentBlock

ThinkingBlock creates a ContentBlock that carries the model's internal reasoning. signature is the opaque cryptographic token from the Anthropic API; pass an empty string for local models that do not use this mechanism.

type ContentType

type ContentType string

ContentType identifies the kind of content in a ContentBlock.

const (
	// ContentText indicates the block contains plain text.
	ContentText ContentType = "text"

	// ContentImage indicates the block contains an image.
	// Supported formats: JPEG, PNG, GIF, WebP.
	ContentImage ContentType = "image"

	// ContentDocument indicates the block contains a document.
	// Supported formats: PDF, plain text.
	ContentDocument ContentType = "document"

	// ContentThinking indicates the block contains the model's internal
	// reasoning produced before the final response or a tool call.
	// The text may be a summary (Claude 4+) or the full chain-of-thought
	// (Claude Sonnet 3.7, local models).
	//
	// Thinking blocks are produced by the model and must not be constructed
	// by callers except when echoing them back to the provider (which the
	// Agent does automatically). Use ThinkingBlock to build one if needed.
	ContentThinking ContentType = "thinking"
)

type DocumentData

type DocumentData struct {
	MediaType string // MIME type: "application/pdf", "text/plain"
	Data      []byte // raw document content
	Title     string // optional — gives the model context about the document
}

DocumentData holds a document to send to the model. For PDFs, Claude processes both text and visual content (tables, charts, embedded images) page by page.

Supported formats: application/pdf, text/plain. Anthropic limit: 32 MB per document.

type Embedder

type Embedder interface {
	Embed(ctx context.Context, content []ContentBlock) ([]float32, error)
}

Embedder converts message content into a dense vector representation suitable for semantic similarity search. Implementations receive the full []ContentBlock so they can handle text, image, and document blocks natively — for example, by routing ContentImage blocks to a vision embedding model.

The vector for a given content slice must be consistent across calls (deterministic given the same model and input).

Use TextFrom to extract and concatenate all text blocks in implementations that only support text.

type Hooks

type Hooks struct {
	// OnIterationStart se invoca al inicio de cada iteración del loop ReAct,
	// antes de llamar al provider.
	// iteration es 0-indexed: la primera iteración es 0.
	OnIterationStart func(iteration int)

	// OnThinking se invoca cuando el modelo produce un bloque de thinking.
	// text es el contenido del razonamiento — puede ser un resumen en Claude 4+
	// o el razonamiento completo en modelos locales y Claude Sonnet 3.7.
	//
	// Se invoca una vez por cada thinking block en la respuesta del modelo.
	// Si la respuesta tiene múltiples thinking blocks (interleaved thinking),
	// se invoca una vez por cada uno, en orden.
	//
	// Solo se invoca si el agente tiene thinking habilitado (WithThinking,
	// WithAdaptiveThinking) o si el modelo local produce thinking.
	OnThinking func(text string)

	// OnToolCall se invoca cuando el modelo solicita ejecutar una herramienta,
	// antes de que el dispatcher la ejecute.
	// Se invoca una vez por cada tool call en la respuesta del modelo.
	// Si el modelo pide N tools en paralelo, se invoca N veces antes del dispatch.
	OnToolCall func(name string, args map[string]any)

	// OnToolResult se invoca después de que una herramienta termina de ejecutarse.
	// content es el resultado que se devolverá al modelo.
	// duration es el tiempo que tardó la ejecución.
	// err es nil si la tool ejecutó exitosamente, o el error si falló.
	//
	// Se invoca incluso cuando la tool falla — err contiene el error.
	// Se invoca una vez por cada tool call, después de que todas terminan.
	OnToolResult func(name string, content []ContentBlock, duration time.Duration, err error)

	// OnResponse se invoca cuando el modelo produce la respuesta final,
	// justo antes de que Run/RunBlocks retorne al caller.
	// text es la respuesta textual extraída (sin thinking blocks).
	// iterations es la cantidad total de iteraciones que usó el loop (1-indexed).
	//
	// También se invoca cuando el loop se agota (MaxIterationsError) —
	// text puede ser "" si la última iteración terminó en tool use.
	OnResponse func(text string, iterations int)

	// OnShortTermLoad se invoca después de que el agente carga el historial de la
	// memoria de corto plazo al inicio de cada Run, tanto en éxito como en error.
	// results es la cantidad de mensajes cargados (0 si err != nil).
	// duration es el tiempo que tardó la operación.
	// err es nil si la carga fue exitosa.
	//
	// Solo se invoca si el agente tiene una ShortTermMemory configurada.
	OnShortTermLoad func(results int, duration time.Duration, err error)

	// OnShortTermAppend se invoca después de que el agente persiste el turno en
	// la memoria de corto plazo al finalizar cada Run, tanto en éxito como en error.
	// msgs es la cantidad de mensajes que se intentó almacenar.
	// duration es el tiempo que tardó la operación.
	// err es nil si el almacenamiento fue exitoso.
	//
	// Solo se invoca si el agente tiene una ShortTermMemory configurada.
	OnShortTermAppend func(msgs int, duration time.Duration, err error)

	// OnLongTermRetrieve se invoca después de que el agente consulta la memoria
	// de largo plazo al inicio de cada Run, tanto en caso de éxito como de error.
	// results es la cantidad de mensajes recuperados (0 si err != nil).
	// duration es el tiempo que tardó la operación de recuperación.
	// err es nil si la recuperación fue exitosa.
	//
	// Solo se invoca si el agente tiene una LongTermMemory configurada.
	OnLongTermRetrieve func(results int, duration time.Duration, err error)

	// OnLongTermStore se invoca después de que el agente persiste un turno en la
	// memoria de largo plazo al finalizar cada Run, tanto en caso de éxito como
	// de error.
	// msgs es la cantidad de mensajes que se intentó almacenar.
	// duration es el tiempo que tardó la operación de almacenamiento.
	// err es nil si el almacenamiento fue exitoso.
	//
	// Solo se invoca si el agente tiene una LongTermMemory configurada y la
	// WritePolicy decidió persistir el turno. No se invoca si la política
	// descarta el turno.
	OnLongTermStore func(msgs int, duration time.Duration, err error)
}

Hooks permite observar eventos del loop ReAct sin modificar su comportamiento. Todos los campos son opcionales — un hook nil se ignora silenciosamente.

Los hooks se invocan sincrónicamente dentro del loop. Si un hook necesita hacer trabajo pesado (ej: enviar a un servicio externo), debe lanzar una goroutine internamente para no bloquear el loop.

El zero value de Hooks es funcional y no invoca ningún callback.

Ejemplo:

agent := goagent.New(
    goagent.WithProvider(provider),
    goagent.WithHooks(goagent.Hooks{
        OnToolCall: func(name string, args map[string]any) {
            fmt.Printf("🔧 %s\n", name)
        },
    }),
)

type ImageData

type ImageData struct {
	MediaType string // MIME type: "image/jpeg", "image/png", "image/gif", "image/webp"
	Data      []byte // raw image content
}

ImageData holds an image to send to the model. Data is the raw image content — the provider layer encodes it to base64.

Supported formats: image/jpeg, image/png, image/gif, image/webp. Anthropic limit: 5 MB per image, ~1600x1600 px recommended.

type LongTermMemory

type LongTermMemory interface {
	// Store persists msgs for future retrieval.
	Store(ctx context.Context, msgs ...Message) error

	// Retrieve returns the topK messages most semantically similar to the
	// given content. The full []ContentBlock is passed so that embedder
	// implementations that support vision or documents can build a meaningful
	// query vector even when the prompt contains no text.
	Retrieve(ctx context.Context, query []ContentBlock, topK int) ([]Message, error)
}

LongTermMemory stores and retrieves messages across sessions by semantic relevance. Unlike ShortTermMemory, retrieval is similarity-based, not positional — the store may contain thousands of messages but only the most relevant ones are surfaced on each Run. Implementations must be safe for concurrent use.

type MCPConnectorFn

type MCPConnectorFn func(ctx context.Context, logger *slog.Logger) ([]Tool, io.Closer, error)

MCPConnectorFn is a function that establishes an MCP connection, discovers tools, and returns them along with a Closer for lifecycle management. It is called by New for each WithMCP* option applied to the agent.

type MaxIterationsError

type MaxIterationsError struct {
	// Iterations is the budget that was exhausted (set by WithMaxIterations).
	Iterations int

	// LastThought is the text content of the model's last assistant message
	// before the budget ran out. It is empty if the model's last turn
	// produced only tool calls with no accompanying text. Useful for
	// debugging runaway loops or surfacing a partial answer to the user.
	LastThought string
}

MaxIterationsError is returned by Run when the agent exhausts its iteration budget without producing a final answer.

func (*MaxIterationsError) Error

func (e *MaxIterationsError) Error() string

type Message

type Message struct {
	Role    Role
	Content []ContentBlock

	// ToolCalls is non-empty when the model requests one or more tool
	// invocations. Only set on assistant messages (Role == RoleAssistant).
	ToolCalls []ToolCall

	// ToolCallID is the ID of the ToolCall this message is a result for.
	// Must be set — and must exactly match ToolCall.ID — when Role == RoleTool.
	// The Agent sets this automatically when building tool result messages;
	// Provider implementations must populate ToolCall.ID for the correlation
	// to work correctly.
	ToolCallID string
}

Message is a single turn in a conversation.

Content is a slice of ContentBlock that can hold text, images, documents, or any combination. For simple text messages, use the helpers TextMessage() or UserMessage(). To extract concatenated text from all blocks, use TextContent().

func AssistantMessage

func AssistantMessage(text string) Message

AssistantMessage creates an assistant-role Message with text content. Shorthand for TextMessage(RoleAssistant, text).

func TextMessage

func TextMessage(role Role, text string) Message

TextMessage creates a Message with a single text content block.

func UserMessage

func UserMessage(text string) Message

UserMessage creates a user-role Message with text content. Shorthand for TextMessage(RoleUser, text).

func (Message) HasContentType

func (m Message) HasContentType(ct ContentType) bool

HasContentType reports whether the message contains at least one ContentBlock of the given type.

func (Message) TextContent

func (m Message) TextContent() string

TextContent returns the concatenation of all ContentText blocks in the message, separated by newlines. Returns an empty string if the message contains no text blocks.

type Option

type Option func(*options)

Option is a functional option for configuring an Agent.

func WithAdaptiveThinking

func WithAdaptiveThinking() Option

WithAdaptiveThinking enables thinking in adaptive mode: the model decides how much to reason based on the complexity of each prompt. Recommended for claude-opus-4-6 and claude-sonnet-4-6.

On models that do not support adaptive mode, the provider may fall back to a manual budget.

func WithEffort

func WithEffort(level string) Option

WithEffort controls the overall effort the model puts into its response, affecting text quality, tool call accuracy, and reasoning depth.

Valid values:

  • "high": maximum effort — equivalent to the model's default behaviour.
  • "medium": balanced quality and cost — suitable for most tasks.
  • "low": faster and cheaper responses — best for simple classification or extraction tasks.

Effort and thinking are orthogonal and can be combined freely. Supported models: claude-opus-4-6, claude-sonnet-4-6, claude-opus-4-5. Models that do not support effort silently ignore this setting.

func WithHooks

func WithHooks(h Hooks) Option

WithHooks registers observability callbacks for the ReAct loop. All fields of Hooks are optional — only non-nil hooks are invoked.

Example:

agent := goagent.New(
    goagent.WithProvider(provider),
    goagent.WithHooks(goagent.Hooks{
        OnToolCall: func(name string, args map[string]any) {
            fmt.Printf("calling tool: %s\n", name)
        },
    }),
)

func WithLogger

func WithLogger(l *slog.Logger) Option

WithLogger sets the structured logger used for debug output.

func WithLongTermMemory

func WithLongTermMemory(m LongTermMemory) Option

WithLongTermMemory configures the agent to retrieve semantically relevant context from past sessions before each Run, and to store the completed turn after each Run (subject to the configured WritePolicy). The default is no long-term memory.

Note: concurrent Run calls on the same Agent will issue concurrent Retrieve and Store calls to this backend. Whether that is safe depends on the LongTermMemory implementation supplied by the caller.

func WithLongTermTopK

func WithLongTermTopK(k int) Option

WithLongTermTopK sets how many messages the long-term memory retrieves per Run. Default: 3.

func WithMCPConnector

func WithMCPConnector(fn MCPConnectorFn) Option

WithMCPConnector registers an MCP connector that is called during New to establish a connection, discover tools, and obtain a Closer for lifecycle management. The connection is established once during New; if it fails, New returns an error and closes any already-opened connections.

Callers typically use the higher-level helpers in the mcp sub-package (mcp.WithStdio, mcp.WithSSE) rather than calling this directly.

func WithMaxIterations

func WithMaxIterations(n int) Option

WithMaxIterations limits how many reasoning iterations the agent may perform. Defaults to 10.

func WithModel

func WithModel(model string) Option

WithModel sets the model identifier forwarded to the provider. Required. The value is provider-specific (e.g. "qwen3" for Ollama, "claude-sonnet-4-6" for Anthropic). If not set, the provider may return an error.

func WithName

func WithName(name string) Option

WithName assigns a name to the agent. When a LongTermMemory is configured, the name is used as the session namespace: all vectors stored and retrieved during Run are scoped to this name, so two agents sharing the same LongTermMemory backend but different names cannot see each other's entries. If not set, no session filtering is applied.

func WithProvider

func WithProvider(p Provider) Option

WithProvider sets the LLM backend used by the agent.

func WithShortTermMemory

func WithShortTermMemory(m ShortTermMemory) Option

WithShortTermMemory configures the agent to persist and replay conversation history across Run calls using the provided ShortTermMemory. The default is stateless — each Run starts with no history.

Note: sharing a ShortTermMemory across concurrent Run calls produces undefined message ordering. Sequential use (one Run at a time) is safe.

func WithShortTermTraceTools

func WithShortTermTraceTools(include bool) Option

WithShortTermTraceTools controls whether the full ReAct trace (tool calls and their results) is included when persisting to short-term memory.

  • true (default): the complete trace is stored — user message, all intermediate assistant turns, tool results, and final assistant answer. The next Run will see the full reasoning history.
  • false: only the user message and the final assistant answer are stored, discarding intermediate tool call steps.

func WithSystemPrompt

func WithSystemPrompt(prompt string) Option

WithSystemPrompt sets a system-level instruction sent to the provider on every Run call.

func WithThinking

func WithThinking(budgetTokens int) Option

WithThinking enables extended thinking with a fixed token budget. The model uses up to budgetTokens tokens for internal reasoning before responding or invoking a tool.

Minimum: 1024 tokens. Recommended ranges:

  • Simple tasks: 4 000–8 000
  • Complex tasks (math, code): 10 000–16 000
  • Deep reasoning: 16 000–32 000

For budgets above 32 000 tokens, consider WithAdaptiveThinking instead. Supported models: claude-sonnet-4-6, claude-opus-4-6, claude-sonnet-3-7, claude-opus-4, claude-opus-4-5.

func WithTool

func WithTool(t Tool) Option

WithTool registers a tool the agent may invoke during the ReAct loop.

func WithWritePolicy

func WithWritePolicy(p WritePolicy) Option

WithWritePolicy sets the function that decides whether a completed turn (prompt + final response) is stored in long-term memory. Default: StoreAlways. Only effective when WithLongTermMemory is configured.

type Provider

type Provider interface {
	Complete(ctx context.Context, req CompletionRequest) (CompletionResponse, error)
}

Provider is the interface that wraps a language model backend. Callers supply a Provider to Agent via WithProvider.

type ProviderError

type ProviderError struct {
	Provider string
	Cause    error
}

ProviderError wraps an error returned by a Provider's Complete method.

func (*ProviderError) Error

func (e *ProviderError) Error() string

func (*ProviderError) Unwrap

func (e *ProviderError) Unwrap() error

Unwrap enables errors.Is and errors.As to inspect the underlying cause.

type Role

type Role string

Role identifies who authored a message in a conversation.

const (
	RoleUser      Role = "user"
	RoleAssistant Role = "assistant"
	RoleTool      Role = "tool"

	// RoleSystem is provided for completeness and for callers that build
	// Provider implementations or raw message slices. When using Agent,
	// the system prompt is set via WithSystemPrompt and is forwarded to the
	// provider through CompletionRequest.SystemPrompt — never as a Message
	// with this role. Callers do not need to construct RoleSystem messages
	// directly.
	RoleSystem Role = "system"
)

type ShortTermMemory

type ShortTermMemory interface {
	// Messages returns the messages to include in the next provider request,
	// with the configured read policy applied (e.g. FixedWindow, TokenWindow).
	// The returned slice is a defensive copy; callers may modify it freely.
	Messages(ctx context.Context) ([]Message, error)

	// Append adds msgs to the store in the order provided.
	// Filtering occurs at read time (Messages), never at write time.
	Append(ctx context.Context, msgs ...Message) error
}

ShortTermMemory manages the active conversation history for an Agent. It is used to maintain context across multiple Run calls within a session. Implementations must be safe for concurrent use.

type StopReason

type StopReason int

StopReason indicates why the model stopped generating.

const (
	StopReasonEndTurn   StopReason = iota // model produced a final answer
	StopReasonMaxTokens                   // token limit reached
	StopReasonToolUse                     // model wants to call tools
	StopReasonError                       // provider-level error
)

func (StopReason) String

func (s StopReason) String() string

String returns a human-readable representation of the stop reason.

type ThinkingConfig

type ThinkingConfig struct {
	Enabled      bool
	BudgetTokens int
}

ThinkingConfig configures the model's extended thinking mode.

Manual mode: Enabled true, BudgetTokens > 0. The model uses up to BudgetTokens tokens for internal reasoning before responding or invoking a tool. Minimum: 1024 tokens.

Adaptive mode: Enabled true, BudgetTokens 0. The model decides how much to reason based on prompt complexity. Recommended for Opus 4.6 and Sonnet 4.6.

Disabled: Enabled false (or nil pointer in CompletionRequest).

type ThinkingData

type ThinkingData struct {
	Thinking  string
	Signature string
}

ThinkingData holds the model's internal reasoning produced during extended thinking. The Agent preserves this data within a turn so the provider can echo it back to the API (required by Anthropic for thinking continuity).

Thinking is the reasoning text — may be a summary in Claude 4+ or the full chain-of-thought in Claude Sonnet 3.7 and local models.

Signature is the opaque cryptographic token issued by the Anthropic API to verify the block's authenticity. It must be echoed back unchanged and must never be logged, inspected, or modified. For local models (Ollama) that do not use this mechanism, Signature is an empty string.

type Tool

type Tool interface {
	Definition() ToolDefinition
	Execute(ctx context.Context, args map[string]any) ([]ContentBlock, error)
}

Tool is the interface that callers implement to give capabilities to an agent.

Execute receives the arguments parsed by the model and returns content that is injected into the conversation as the tool result. The content can be text, images, documents, or any combination.

For tools that only return text (the most common case), use ToolFunc which accepts func(...) (string, error) and wraps it automatically.

func ToolBlocksFunc

func ToolBlocksFunc(
	name, description string,
	parameters map[string]any,
	fn func(ctx context.Context, args map[string]any) ([]ContentBlock, error),
) Tool

ToolBlocksFunc creates a Tool from a plain function that returns multimodal content. Use this when the tool needs to return images, documents, or a combination of content types.

For tools that only return text, prefer ToolFunc which is more ergonomic.

Example

ExampleToolBlocksFunc shows how to create a Tool that returns multimodal content blocks instead of plain text.

package main

import (
	"context"
	"fmt"

	"github.com/Germanblandin1/goagent"
)

func main() {
	t := goagent.ToolBlocksFunc("screenshot", "captures the current screen", nil,
		func(_ context.Context, _ map[string]any) ([]goagent.ContentBlock, error) {
			return []goagent.ContentBlock{
				goagent.TextBlock("captured"),
			}, nil
		},
	)
	fmt.Println(t.Definition().Name)
	fmt.Println(t.Definition().Description)
}
Output:
screenshot
captures the current screen

func ToolFunc

func ToolFunc(
	name, description string,
	parameters map[string]any,
	fn func(ctx context.Context, args map[string]any) (string, error),
) Tool

ToolFunc creates a Tool from a plain function that returns text. The returned string is wrapped in a single text ContentBlock automatically, avoiding the need to define a new struct for simple tools.

For tools that need to return images, documents, or mixed content, use ToolBlocksFunc instead.

Example

ExampleToolFunc shows how to create a Tool from a plain function.

package main

import (
	"context"
	"fmt"

	"github.com/Germanblandin1/goagent"
)

func main() {
	t := goagent.ToolFunc("add", "adds two numbers", nil,
		func(_ context.Context, _ map[string]any) (string, error) {
			return "42", nil
		},
	)
	fmt.Println(t.Definition().Name)
	fmt.Println(t.Definition().Description)
}
Output:
add
adds two numbers

type ToolCall

type ToolCall struct {
	// ID is the opaque identifier assigned by the model to this tool call.
	// It must be echoed back in Message.ToolCallID of the corresponding
	// tool result message so the model can correlate the result with the
	// request. Provider implementations must populate this field; leaving
	// it empty will cause the next completion to fail on APIs that enforce
	// the tool call / tool result pairing (e.g. Anthropic, OpenAI).
	ID string

	// Name is the tool name the model wants to invoke, matching the
	// Name field of a registered ToolDefinition.
	Name string

	// Arguments contains the arguments the model supplied for this call,
	// decoded from the provider's JSON payload. Keys match the parameter
	// names defined in ToolDefinition.Parameters.
	Arguments map[string]any
}

ToolCall represents a request from the model to invoke a tool.

type ToolDefinition

type ToolDefinition struct {
	Name        string
	Description string
	Parameters  map[string]any
}

ToolDefinition describes a tool's name, purpose, and parameter schema. Parameters must be a valid JSON Schema object as map[string]any.

type ToolExecutionError

type ToolExecutionError struct {
	ToolName string
	Args     map[string]any
	Cause    error
}

ToolExecutionError wraps an error returned by a tool's Execute method, adding the tool name and arguments for diagnosis.

func (*ToolExecutionError) Error

func (e *ToolExecutionError) Error() string

func (*ToolExecutionError) Unwrap

func (e *ToolExecutionError) Unwrap() error

Unwrap enables errors.Is and errors.As to inspect the underlying cause.

type ToolResult

type ToolResult struct {
	ToolCallID string
	Name       string
	Content    []ContentBlock
	Err        error
	// Duration is how long Execute took. It is zero when the tool was not
	// found (ErrToolNotFound) — no execution occurred in that case.
	Duration time.Duration
}

ToolResult holds the outcome of a single tool execution dispatched by the agent.

type UnsupportedContentError

type UnsupportedContentError struct {
	ContentType ContentType
	Provider    string
	Reason      string
}

UnsupportedContentError provides detail about which content type is not supported and by which provider. It wraps ErrUnsupportedContent so callers can match with errors.Is(err, ErrUnsupportedContent).

func (*UnsupportedContentError) Error

func (e *UnsupportedContentError) Error() string

func (*UnsupportedContentError) Unwrap

func (e *UnsupportedContentError) Unwrap() error

Unwrap returns ErrUnsupportedContent so errors.Is works.

type Usage

type Usage struct {
	// InputTokens is the number of tokens in the prompt (including history).
	InputTokens int

	// OutputTokens is the number of tokens in the model's response.
	OutputTokens int
}

Usage reports token consumption for a completion.

type VectorStore

type VectorStore interface {
	// Upsert stores or updates a message with its embedding vector.
	// id must be a stable identifier for the message (e.g. content hash).
	Upsert(ctx context.Context, id string, vector []float32, msg Message) error

	// Search returns the topK messages most similar to the given vector.
	Search(ctx context.Context, vector []float32, topK int) ([]Message, error)
}

VectorStore stores (message, embedding) pairs and supports similarity search. This module does not ship a VectorStore implementation; the caller must supply one (e.g. a pgvector client, a Chroma adapter, or an in-process approximate nearest-neighbour store).

type WritePolicy

type WritePolicy func(prompt, response Message) []Message

WritePolicy decides what to persist after a completed turn. It is called once per Run after the final answer is produced.

Returning nil discards the turn — nothing is written to long-term memory. Returning a non-nil slice (even an empty one) stores exactly those messages.

This design lets policies both filter and transform: a policy may return the original user+assistant pair unchanged (like StoreAlways), a condensed single message (like a summarising judge agent), or any custom set of messages.

prompt is the user Message that opened the turn (may contain images, documents, or other multimodal blocks). response is the final assistant Message. Both are passed in full so policies can inspect or forward binary content without losing it.

var StoreAlways WritePolicy = func(p, r Message) []Message {
	return []Message{p, r}
}

StoreAlways is a WritePolicy that persists every turn as the original user+assistant message pair. It is the default when WithLongTermMemory is configured without an explicit WritePolicy.

func MinLength

func MinLength(n int) WritePolicy

MinLength returns a WritePolicy that stores the original user+assistant pair only when the combined character count of their text content exceeds n. Returns nil (discard) when the combined length is n or fewer characters. Useful for filtering out trivial exchanges ("ok", "gracias", "seguí") that add noise to the long-term store without carrying durable information.

Example

ExampleMinLength shows how MinLength filters out short exchanges from long-term memory storage. A nil return means the turn is discarded; a non-nil slice is stored as-is.

package main

import (
	"fmt"

	"github.com/Germanblandin1/goagent"
)

func main() {
	policy := goagent.MinLength(10)

	// 4 chars total ("hi" + "ok") — below threshold, turn is discarded.
	fmt.Println(policy(goagent.UserMessage("hi"), goagent.AssistantMessage("ok")) == nil)

	// 15 chars total ("hello world" + "fine") — above threshold, returns the
	// default user+assistant pair ready to be passed to LongTermMemory.Store.
	msgs := policy(goagent.UserMessage("hello world"), goagent.AssistantMessage("fine"))
	fmt.Printf("%d messages: %s / %s\n", len(msgs), msgs[0].Role, msgs[1].Role)
}
Output:
true
2 messages: user / assistant

Directories

Path Synopsis
internal
testutil
Package testutil provides shared test helpers for the goagent module.
Package testutil provides shared test helpers for the goagent module.
Package memory provides ShortTermMemory and LongTermMemory implementations for the goagent framework.
Package memory provides ShortTermMemory and LongTermMemory implementations for the goagent framework.
policy
Package policy provides read Policy implementations for the goagent memory system.
Package policy provides read Policy implementations for the goagent memory system.
storage
Package storage provides Storage implementations for the goagent memory system.
Package storage provides Storage implementations for the goagent memory system.
vector
Package vector provides embeddings, chunking, similarity search, and an in-process vector store for goagent's long-term memory subsystem.
Package vector provides embeddings, chunking, similarity search, and an in-process vector store for goagent's long-term memory subsystem.
rag module

Jump to

Keyboard shortcuts

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