agentcore

package module
v1.5.8 Latest Latest
Warning

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

Go to latest
Published: Mar 30, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

README

AgentCore

AgentCore is a minimal, composable Go library for building AI agent applications.

English | 中文

Install

go get github.com/voocel/agentcore

Design Philosophy

A restrained core with open extensibility tends to be more reliable than a complex all-in-one solution. Fewer built-ins, more possibilities.

Stability

  • Keep Agent, AgentLoop, Event, Tool, and Message stable first
  • Behavioral changes should come with tests first; examples/ and internal implementation details are not stable API

Architecture

agentcore/            Agent core (types, loop, agent, events, subagent)
agentcore/llm/        LLM adapters (OpenAI, Anthropic, Gemini via litellm)
agentcore/tools/      Built-in tools: read, write, edit, bash
agentcore/memory/     Context compaction — auto-summarize long conversations

Core design:

  • Standalone loop (loop.go) — free function, all dependencies injected via parameters. Double loop: inner processes tool calls + steering, outer handles follow-up
  • Stateful Agent (agent.go) — sole consumer of loop events, updates internal state then dispatches to external listeners
  • Event stream — single <-chan Event output drives any UI (TUI, Web, Slack, logging)
  • Two-stage pipelineTransformContext (prune/inject) → ConvertToLLM (filter to LLM messages)
  • SubAgent tool (subagent.go) — multi-agent via tool invocation, four modes: single, parallel, chain, background
  • Context compaction (memory/) — automatic summarization when context approaches window limit

Quick Start

Single Agent
package main

import (
    "fmt"
    "os"

    "github.com/voocel/agentcore"
    "github.com/voocel/agentcore/llm"
    "github.com/voocel/agentcore/policy"
    "github.com/voocel/agentcore/tools"
)

func main() {
    model, err := llm.NewOpenAIModel("gpt-5-mini", os.Getenv("OPENAI_API_KEY"))
    if err != nil {
        panic(err)
    }

    agent := agentcore.NewAgent(
        agentcore.WithModel(model),
        agentcore.WithSystemPrompt("You are a helpful coding assistant."),
        agentcore.WithTools(
            tools.NewRead("."),
            tools.NewWrite("."),
            tools.NewEdit("."),
            tools.NewBash("."),
        ),
        agentcore.WithPermission(policy.WorkspaceProfile(".")),
    )

    agent.Subscribe(func(ev agentcore.Event) {
        if ev.Type == agentcore.EventMessageEnd {
            if msg, ok := ev.Message.(agentcore.Message); ok && msg.Role == agentcore.RoleAssistant {
                fmt.Println(msg.Content)
            }
        }
    })

    agent.Prompt("List the files in the current directory.")
    agent.WaitForIdle()
}

For a safer default, use policy.ReadOnlyProfile(root) or policy.WorkspaceProfile(root).

Multi-Agent (SubAgent Tool)

Sub-agents are invoked as regular tools with isolated contexts:

model, _ := llm.NewOpenAIModel("gpt-5-mini", apiKey)

scout := agentcore.SubAgentConfig{
    Name:         "scout",
    Description:  "Fast codebase reconnaissance",
    Model:        model,
    SystemPrompt: "Quickly explore and report findings. Be concise.",
    Tools:        []agentcore.Tool{tools.NewRead("."), tools.NewBash(".")},
    MaxTurns:     5,
}

worker := agentcore.SubAgentConfig{
    Name:         "worker",
    Description:  "General-purpose executor",
    Model:        model,
    SystemPrompt: "Implement tasks given to you.",
    Tools:        []agentcore.Tool{tools.NewRead("."), tools.NewWrite("."), tools.NewEdit("."), tools.NewBash(".")},
}

agent := agentcore.NewAgent(
    agentcore.WithModel(model),
    agentcore.WithTools(agentcore.NewSubAgentTool(scout, worker)),
)

Four execution modes via tool call:

// Single: one agent, one task
{"agent": "scout", "task": "Find all API endpoints"}

// Parallel: concurrent execution
{"tasks": [{"agent": "scout", "task": "Find auth code"}, {"agent": "scout", "task": "Find DB schema"}]}

// Chain: sequential with {previous} context passing
{"chain": [{"agent": "scout", "task": "Find auth code"}, {"agent": "worker", "task": "Refactor based on: {previous}"}]}

// Background: async execution, returns immediately, notifies on completion
{"agent": "worker", "task": "Run full test suite", "background": true, "description": "Running tests"}
Steering & Follow-Up
// Interrupt mid-run (delivered after current tool, remaining tools skipped)
agent.Steer(agentcore.UserMsg("Stop and focus on tests instead."))

// Queue for after the agent finishes
agent.FollowUp(agentcore.UserMsg("Now run the tests."))

// Cancel immediately
agent.Abort()
Event Stream

All lifecycle events flow through a single channel — subscribe to drive any UI:

agent.Subscribe(func(ev agentcore.Event) {
    switch ev.Type {
    case agentcore.EventMessageStart:    // assistant starts streaming
    case agentcore.EventMessageUpdate:   // streaming token delta
    case agentcore.EventMessageEnd:      // message complete
    case agentcore.EventToolExecStart:   // tool execution begins
    case agentcore.EventToolExecEnd:     // tool execution ends
    case agentcore.EventError:           // error occurred
    }
})
Structured Tool Progress

Long-running tools can emit structured progress updates instead of ad-hoc JSON:

agentcore.ReportToolProgress(ctx, agentcore.ProgressPayload{
    Kind:    agentcore.ProgressSummary,
    Agent:   "worker",
    Tool:    "bash",
    Summary: "worker → bash",
})

Subscribers should read ev.Progress directly for tool progress updates:

agent.Subscribe(func(ev agentcore.Event) {
    if ev.Type == agentcore.EventToolExecUpdate && ev.Progress != nil {
        fmt.Printf("[%s] %s\n", ev.Progress.Kind, ev.Progress.Summary)
    }
})
Swappable Models

When a model needs to change at runtime, wrap it with SwappableModel. The swap takes effect on the next call. SubAgentConfig.Model is resolved at the start of each sub-agent run, so the same wrapper also works for sub-agents.

defaultModel, _ := llm.NewOpenAIModel("gpt-5-mini", apiKey)
sw := agentcore.NewSwappableModel(defaultModel)

agent := agentcore.NewAgent(agentcore.WithModel(sw))

nextModel, _ := llm.NewOpenAIModel("gpt-5", apiKey)
sw.Swap(nextModel) // next turn uses the new model
Custom LLM (StreamFn)

Swap the LLM call with a proxy, mock, or custom implementation:

agent := agentcore.NewAgent(
    agentcore.WithStreamFn(func(ctx context.Context, req *agentcore.LLMRequest) (*agentcore.LLMResponse, error) {
        // Route to your own proxy/gateway
        return callMyProxy(ctx, req)
    }),
)
Context Compaction

Auto-summarize conversation history when approaching the context window limit. Hooks in via TransformContext — zero changes to core:

import "github.com/voocel/agentcore/memory"

agent := agentcore.NewAgent(
    agentcore.WithModel(model),
    agentcore.WithTransformContext(memory.NewCompaction(memory.CompactionConfig{
        Model:         model,
        ContextWindow: 128000,
    })),
    agentcore.WithConvertToLLM(memory.CompactionConvertToLLM),
)

On each LLM call, compaction checks total tokens. When they exceed ContextWindow - ReserveTokens (default 16384), it:

  1. Keeps recent messages (default 20000 tokens)
  2. Summarizes older messages via LLM into a structured checkpoint (Goal / Progress / Key Decisions / Next Steps)
  3. Tracks file operations (read/write/edit paths) across compacted messages
  4. Supports incremental updates — subsequent compactions update the existing summary rather than re-summarizing
Context Pipeline
agent := agentcore.NewAgent(
    // Stage 1: prune old messages, inject external context
    agentcore.WithTransformContext(func(ctx context.Context, msgs []agentcore.AgentMessage) ([]agentcore.AgentMessage, error) {
        if len(msgs) > 100 {
            msgs = msgs[len(msgs)-50:]
        }
        return msgs, nil
    }),
    // Stage 2: filter to LLM-compatible messages
    agentcore.WithConvertToLLM(func(msgs []agentcore.AgentMessage) []agentcore.Message {
        var out []agentcore.Message
        for _, m := range msgs {
            if msg, ok := m.(agentcore.Message); ok {
                out = append(out, msg)
            }
        }
        return out
    }),
)

Built-in Tools

Tool Description
read Read file contents with head truncation (2000 lines / 50KB)
write Write file with auto-mkdir
edit Exact text replacement with fuzzy match, BOM/line-ending normalization, unified diff output
bash Execute shell commands with tail truncation (2000 lines / 50KB)

Runtime Injection

Use Inject(msg) when the caller's intent is "deliver this as soon as the current agent state allows" without manually branching on running vs idle state.

result, err := agent.Inject(agentcore.UserMsg("Re-check unfinished tasks before stopping."))
if err != nil {
    panic(err)
}
fmt.Println(result.Disposition)

Inject has three outcomes:

  • steered_current_run: the agent is running, so the message was queued into the current run's steering path
  • resumed_idle_run: the agent was idle with an assistant-tail conversation, so the message was queued and Continue() was started immediately
  • queued: the message was queued, but no run was started

Use the lower-level APIs when you need stricter control:

  • Steer(msg): queue for the steering path without any idle auto-resume logic
  • FollowUp(msg): queue for after the current run stops
  • prompt-side injection: keep this in the application layer if the message must be merged into the next explicit user prompt rather than the agent queues

API Reference

Agent
Method Description
NewAgent(opts...) Create agent with options
Prompt(input) Start new conversation turn
PromptMessages(msgs...) Start turn with arbitrary AgentMessages
Continue() Resume from current context
Inject(msg) Deliver message via steer / idle resume / queue, depending on current state
Steer(msg) Inject steering message mid-run
FollowUp(msg) Queue message for after completion
Abort() Cancel current execution
AbortSilent() Cancel without emitting abort marker
WaitForIdle() Block until agent finishes
Subscribe(fn) Register event listener
State() Snapshot of current state
ExportMessages() Export messages for serialization
ImportMessages(msgs) Import deserialized messages

License

Apache License 2.0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AgentLoop

func AgentLoop(ctx context.Context, prompts []AgentMessage, agentCtx AgentContext, config LoopConfig) <-chan Event

AgentLoop starts an agent loop with new prompt messages. Prompts are added to context and events are emitted for them.

func AgentLoopContinue

func AgentLoopContinue(ctx context.Context, agentCtx AgentContext, config LoopConfig) <-chan Event

AgentLoopContinue continues from existing context without adding new messages. The last message in context must convert to user or tool role via ConvertToLLM.

func IsContextOverflow

func IsContextOverflow(err error) bool

IsContextOverflow reports whether the error indicates a context window overflow.

func ReactivateDeferred added in v1.5.2

func ReactivateDeferred(tools []Tool, msgs []AgentMessage)

ReactivateDeferred scans restored messages for tool_reference blocks and pre-activates them via the DeferActivator found in tools. This must be called after restoring a session to avoid "Tool reference not found" errors.

func ReportToolProgress

func ReportToolProgress(ctx context.Context, progress ProgressPayload)

ReportToolProgress reports structured progress during tool execution. Silently ignored if no callback is registered in the context.

func WithToolProgress

func WithToolProgress(ctx context.Context, fn ToolProgressFunc) context.Context

WithToolProgress injects a progress callback into the context.

Types

type Agent

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

Agent is a stateful wrapper around the agent loop. It consumes loop events to update internal state, just like any external listener.

func NewAgent

func NewAgent(opts ...AgentOption) *Agent

NewAgent creates a new Agent with the given options.

func (*Agent) Abort

func (a *Agent) Abort()

Abort cancels the current execution and emits an abort marker message so the LLM knows the user interrupted.

func (*Agent) AbortSilent added in v1.5.1

func (a *Agent) AbortSilent()

AbortSilent cancels the current execution without emitting an abort marker. Use for programmatic cancellation (e.g. plan mode transitions) where the cancellation is not a user interruption.

func (*Agent) BuildLLMMessages added in v1.5.6

func (a *Agent) BuildLLMMessages() []Message

BuildLLMMessages constructs the message list exactly as the agent loop would for an LLM call: system blocks/prompt → converted conversation messages. This enables external callers (e.g., prompt suggestion) to make background LLM calls that share the same message prefix for prompt cache hits.

func (*Agent) ClearAllQueues

func (a *Agent) ClearAllQueues()

ClearAllQueues removes all queued steering and follow-up messages.

func (*Agent) ClearFollowUpQueue

func (a *Agent) ClearFollowUpQueue()

ClearFollowUpQueue removes all queued follow-up messages.

func (*Agent) ClearMessages

func (a *Agent) ClearMessages()

ClearMessages resets the message history.

func (*Agent) ClearSteeringQueue

func (a *Agent) ClearSteeringQueue()

ClearSteeringQueue removes all queued steering messages.

func (*Agent) ContextUsage

func (a *Agent) ContextUsage() *ContextUsage

ContextUsage returns an estimate of the current context window occupancy. Returns nil if contextWindow or contextEstimateFn is not configured.

func (*Agent) Continue

func (a *Agent) Continue() error

Continue resumes from the current context without adding new messages. If the last message is from assistant, it dequeues steering/follow-up

func (*Agent) ExportMessages

func (a *Agent) ExportMessages() []Message

ExportMessages returns concrete Messages for serialization.

func (*Agent) FollowUp

func (a *Agent) FollowUp(msg AgentMessage)

FollowUp queues a message to be processed after the agent finishes.

func (*Agent) HasQueuedMessages

func (a *Agent) HasQueuedMessages() bool

HasQueuedMessages reports whether any steering or follow-up messages are queued.

func (*Agent) ImportMessages

func (a *Agent) ImportMessages(msgs []Message) error

ImportMessages replaces message history from deserialized Messages.

func (*Agent) Inject added in v1.5.7

func (a *Agent) Inject(msg AgentMessage) (InjectResult, error)

Inject delivers a message as soon as the current agent state allows.

Semantics:

  • running: enqueue into steeringQ for the current run
  • idle with assistant tail: enqueue then synchronously Continue()
  • other idle states: enqueue for a later run

func (*Agent) Messages

func (a *Agent) Messages() []AgentMessage

Messages returns the current message history.

func (*Agent) Prompt

func (a *Agent) Prompt(input string) error

Prompt starts a new conversation turn with the given input.

func (*Agent) PromptMessages

func (a *Agent) PromptMessages(msgs ...AgentMessage) error

PromptMessages starts a new conversation turn with arbitrary AgentMessages.

func (*Agent) Reset

func (a *Agent) Reset()

Reset clears all state and queues. If the agent is running, it cancels and waits first.

func (*Agent) SetContextWindow added in v1.5.2

func (a *Agent) SetContextWindow(n int)

SetContextWindow updates the context window size (in tokens).

func (*Agent) SetMessages

func (a *Agent) SetMessages(msgs []AgentMessage) error

SetMessages replaces the message history (e.g. to restore a previous conversation). The agent must not be running.

func (*Agent) SetModel

func (a *Agent) SetModel(m ChatModel)

SetModel changes the LLM provider. Takes effect on the next turn.

func (*Agent) SetSystemBlocks added in v1.5.2

func (a *Agent) SetSystemBlocks(blocks []SystemBlock)

SetSystemBlocks sets a multi-block system prompt with per-block cache control. Takes precedence over SetSystemPrompt. Clears the single-string prompt.

func (*Agent) SetSystemPrompt

func (a *Agent) SetSystemPrompt(s string)

SetSystemPrompt changes the system prompt (single-string mode). Clears any multi-block system prompt set via SetSystemBlocks.

func (*Agent) SetThinkingLevel

func (a *Agent) SetThinkingLevel(level ThinkingLevel)

SetThinkingLevel changes the reasoning depth. Takes effect on the next turn.

func (*Agent) SetTools

func (a *Agent) SetTools(tools ...Tool)

SetTools replaces the tool set. Takes effect on the next turn.

func (*Agent) State

func (a *Agent) State() AgentState

State returns a snapshot of the agent's current state.

func (*Agent) Steer

func (a *Agent) Steer(msg AgentMessage)

Steer queues a steering message to interrupt the agent mid-run. Delivered after the current tool execution; remaining tools are skipped.

func (*Agent) Subscribe

func (a *Agent) Subscribe(fn func(Event)) func()

Subscribe registers a listener for agent events. Returns an unsubscribe function.

func (*Agent) TotalUsage

func (a *Agent) TotalUsage() Usage

TotalUsage returns the cumulative token usage across all turns.

func (*Agent) WaitForIdle

func (a *Agent) WaitForIdle()

WaitForIdle blocks until the agent finishes the current run.

type AgentContext

type AgentContext struct {
	SystemPrompt string        // single-string system prompt (legacy)
	SystemBlocks []SystemBlock // multi-block system prompt with cache control (takes precedence)
	Messages     []AgentMessage
	Tools        []Tool
}

AgentContext holds the immutable context for a single agent loop invocation.

type AgentMessage

type AgentMessage interface {
	GetRole() Role
	GetTimestamp() time.Time
	TextContent() string
	ThinkingContent() string
	HasToolCalls() bool
}

AgentMessage is the app-layer message abstraction. Message implements this interface. Users can define custom types (e.g. status notifications, UI hints) that flow through the context pipeline but get filtered out by ConvertToLLM.

func Collect added in v1.5.1

func Collect(events <-chan Event) ([]AgentMessage, error)

Collect consumes all events from the channel and returns the final messages. Blocks until the channel is closed. Returns any error from EventError events.

func ToAgentMessages

func ToAgentMessages(msgs []Message) []AgentMessage

ToAgentMessages converts a Message slice to AgentMessage slice. Use this to restore conversation history from deserialized Messages.

type AgentOption

type AgentOption func(*Agent)

AgentOption configures an Agent.

func WithContextEstimate

func WithContextEstimate(fn ContextEstimateFn) AgentOption

WithContextEstimate sets the context token estimation function. Use memory.ContextEstimateAdapter for the default hybrid estimation.

func WithContextPipeline

func WithContextPipeline(
	transform func(ctx context.Context, msgs []AgentMessage) ([]AgentMessage, error),
	convert func([]AgentMessage) []Message,
) AgentOption

WithContextPipeline sets both TransformContext and ConvertToLLM in one call. This is the recommended way to configure context compaction:

agentcore.WithContextPipeline(
    memory.NewCompaction(cfg),
    memory.CompactionConvertToLLM,
)

func WithContextWindow

func WithContextWindow(n int) AgentOption

WithContextWindow sets the model's context window size in tokens. Used by ContextUsage() to calculate context occupancy percentage.

func WithConvertToLLM

func WithConvertToLLM(fn func([]AgentMessage) []Message) AgentOption

WithConvertToLLM sets the message conversion function.

func WithFollowUpMode

func WithFollowUpMode(mode QueueMode) AgentOption

WithFollowUpMode sets the follow-up queue drain mode. QueueModeAll (default) delivers all queued follow-up messages at once. QueueModeOneAtATime delivers one per turn.

func WithGetApiKey

func WithGetApiKey(fn func(provider string) (string, error)) AgentOption

WithGetApiKey sets a dynamic API key resolver called before each LLM call. The provider parameter identifies which provider is being called (e.g. "openai", "anthropic"). Enables per-provider key resolution, key rotation, OAuth short-lived tokens, and multi-tenant scenarios.

func WithMaxRetries

func WithMaxRetries(n int) AgentOption

WithMaxRetries sets the LLM call retry limit for retryable errors.

func WithMaxRetryDelay added in v1.5.1

func WithMaxRetryDelay(d time.Duration) AgentOption

WithMaxRetryDelay caps the wait time between LLM retries. Applies to both exponential backoff and server-requested Retry-After delays. Default: 60s.

func WithMaxToolConcurrency added in v1.5.1

func WithMaxToolConcurrency(n int) AgentOption

WithMaxToolConcurrency sets the maximum number of tools executed in parallel. 0 or 1 = sequential (default). >1 enables concurrent tool execution.

func WithMaxToolErrors

func WithMaxToolErrors(n int) AgentOption

WithMaxToolErrors sets the consecutive failure threshold per tool. After reaching this limit, the tool is disabled for the rest of the loop. 0 means unlimited (no circuit breaker).

func WithMaxTurns

func WithMaxTurns(n int) AgentOption

WithMaxTurns sets the max turns safety limit.

func WithMiddlewares added in v1.5.1

func WithMiddlewares(mw ...ToolMiddleware) AgentOption

WithMiddlewares sets tool execution middlewares. Each middleware wraps the tool.Execute call. First middleware is outermost.

func WithModel

func WithModel(model ChatModel) AgentOption

WithModel sets the LLM model.

func WithSessionID

func WithSessionID(id string) AgentOption

WithSessionID sets a session identifier for provider-level caching. Forwarded to providers that support session-based prompt caching.

func WithSteeringMode

func WithSteeringMode(mode QueueMode) AgentOption

WithSteeringMode sets the steering queue drain mode. QueueModeAll (default) delivers all queued steering messages at once. QueueModeOneAtATime delivers one per turn, letting the agent respond to each individually.

func WithStreamFn

func WithStreamFn(fn StreamFn) AgentOption

WithStreamFn sets a custom LLM call function (for proxy/mock).

func WithSystemBlocks added in v1.5.2

func WithSystemBlocks(blocks []SystemBlock) AgentOption

WithSystemBlocks sets a multi-block system prompt with per-block cache control. Takes precedence over WithSystemPrompt.

func WithSystemPrompt

func WithSystemPrompt(prompt string) AgentOption

WithSystemPrompt sets the system prompt (single-string mode).

func WithThinkingBudgets

func WithThinkingBudgets(budgets map[ThinkingLevel]int) AgentOption

WithThinkingBudgets sets per-level thinking token budgets. Each ThinkingLevel maps to a max thinking token count.

func WithThinkingLevel

func WithThinkingLevel(level ThinkingLevel) AgentOption

WithThinkingLevel sets the reasoning depth for models that support it.

func WithToolApproval added in v1.5.6

func WithToolApproval(fn ToolApprovalFunc) AgentOption

WithToolApproval sets a runtime approval callback called before tool execution.

func WithTools

func WithTools(tools ...Tool) AgentOption

WithTools sets the tool list.

func WithTransformContext

func WithTransformContext(fn func(ctx context.Context, msgs []AgentMessage) ([]AgentMessage, error)) AgentOption

WithTransformContext sets the context transform function.

type AgentState

type AgentState struct {
	SystemPrompt     string
	Messages         []AgentMessage
	Tools            []Tool
	IsRunning        bool
	StreamMessage    AgentMessage        // partial message being streamed, nil when idle
	PendingToolCalls map[string]struct{} // tool call IDs currently executing
	TotalUsage       Usage               // cumulative token usage across all turns
	Error            string
}

AgentState is a snapshot of the agent's current state.

type BackgroundTask added in v1.5.3

type BackgroundTask struct {
	ID          string
	Agent       string // agent config name
	Description string
	Prompt      string // original task prompt
	Status      string // "running" | "completed" | "failed"
	StartedAt   time.Time
	EndedAt     time.Time
	OutputFile  string // path to output file on disk
	Error       string
	Progress    []string // tool call history: "Tool(args...)"
	TokensIn    int
	TokensOut   int
	ToolCount   int
	// contains filtered or unexported fields
}

BackgroundTask tracks a background sub-agent's lifecycle. Output is written to a persistent file (OutputFile) with a symlink in the tasks dir.

type CallConfig

type CallConfig struct {
	ThinkingLevel  ThinkingLevel
	ThinkingBudget int    // max thinking tokens, 0 = use provider default
	APIKey         string // per-call API key override, empty = use model default
	SessionID      string // provider session caching identifier
	MaxTokens      int    // per-call max tokens override, 0 = use model default
}

CallConfig holds per-call configuration resolved from CallOptions.

func ResolveCallConfig

func ResolveCallConfig(opts []CallOption) CallConfig

ResolveCallConfig applies options and returns the resolved config.

type CallOption

type CallOption func(*CallConfig)

CallOption configures per-call LLM parameters.

func WithAPIKey

func WithAPIKey(key string) CallOption

WithAPIKey overrides the API key for a single LLM call. Enables key rotation, OAuth short-lived tokens, and multi-tenant scenarios.

func WithCallSessionID

func WithCallSessionID(id string) CallOption

WithCallSessionID sets a session identifier for a single LLM call.

func WithMaxTokens added in v1.5.1

func WithMaxTokens(tokens int) CallOption

WithMaxTokens overrides the max output tokens for a single LLM call.

func WithThinking

func WithThinking(level ThinkingLevel) CallOption

WithThinking sets the thinking level for a single LLM call.

func WithThinkingBudget

func WithThinkingBudget(tokens int) CallOption

WithThinkingBudget sets the max thinking tokens for a single LLM call.

type ChatModel

type ChatModel interface {
	Generate(ctx context.Context, messages []Message, tools []ToolSpec, opts ...CallOption) (*LLMResponse, error)
	GenerateStream(ctx context.Context, messages []Message, tools []ToolSpec, opts ...CallOption) (<-chan StreamEvent, error)
	SupportsTools() bool
}

ChatModel is the LLM provider interface.

type ContentBlock

type ContentBlock struct {
	Type     ContentType `json:"type"`
	Text     string      `json:"text,omitempty"`
	Thinking string      `json:"thinking,omitempty"`
	ToolCall *ToolCall   `json:"tool_call,omitempty"`
	Image    *ImageData  `json:"image,omitempty"`
	ToolName string      `json:"tool_name,omitempty"` // tool_reference: referenced tool name
}

ContentBlock is a tagged union for message content. Exactly one payload field is populated, matching the Type value.

func ImageBlock

func ImageBlock(data, mimeType string) ContentBlock

func ImageURLBlock added in v1.5.1

func ImageURLBlock(url string) ContentBlock

func TextBlock

func TextBlock(text string) ContentBlock

func ThinkingBlock

func ThinkingBlock(thinking string) ContentBlock

func ToolCallBlock

func ToolCallBlock(tc ToolCall) ContentBlock

func ToolRefBlock added in v1.5.2

func ToolRefBlock(toolName string) ContentBlock

type ContentTool added in v1.5.1

type ContentTool interface {
	ExecuteContent(ctx context.Context, args json.RawMessage) ([]ContentBlock, error)
}

ContentTool is an optional interface for tools that return rich content (e.g., images). When a tool implements ContentTool, the agent loop calls ExecuteContent instead of Execute, enabling multi-block responses with text + image content blocks.

type ContentType

type ContentType string

ContentType identifies the kind of content in a ContentBlock.

const (
	ContentText     ContentType = "text"
	ContentThinking ContentType = "thinking"
	ContentToolCall ContentType = "toolCall"
	ContentImage    ContentType = "image"
	ContentToolRef  ContentType = "tool_reference"
)

type ContextEstimateFn

type ContextEstimateFn func(msgs []AgentMessage) (tokens, usageTokens, trailingTokens int)

ContextEstimateFn estimates the current context token consumption from messages. Returns total tokens, tokens from LLM Usage, and estimated trailing tokens.

type ContextUsage

type ContextUsage struct {
	Tokens         int     `json:"tokens"`          // estimated total tokens in context
	ContextWindow  int     `json:"context_window"`  // model's context window size
	Percent        float64 `json:"percent"`         // tokens / contextWindow * 100
	UsageTokens    int     `json:"usage_tokens"`    // from last LLM-reported Usage
	TrailingTokens int     `json:"trailing_tokens"` // chars/4 estimate for trailing messages
}

ContextUsage represents the current context window occupancy estimate.

type Cost added in v1.5.1

type Cost struct {
	Input      float64 `json:"input"`
	Output     float64 `json:"output"`
	CacheRead  float64 `json:"cache_read"`
	CacheWrite float64 `json:"cache_write"`
	Total      float64 `json:"total"`
}

Cost tracks monetary cost for a single LLM call in USD.

func (*Cost) Add added in v1.5.1

func (c *Cost) Add(other *Cost)

Add accumulates another Cost into this one (nil-safe).

type DeferActivator added in v1.5.2

type DeferActivator interface {
	DeferFilter
	Activate(names ...string)
}

DeferActivator is an optional extension of DeferFilter that supports pre-activating deferred tools (e.g. when restoring a session whose history contains tool_reference blocks for previously activated tools).

type DeferFilter added in v1.5.2

type DeferFilter interface {
	// IsDeferred reports whether the tool is deferred and not yet activated.
	// Unactivated deferred tools are excluded from the API request entirely.
	IsDeferred(toolName string) bool
	// WasDeferred reports whether the tool was originally in the deferred set
	// (regardless of activation). Activated deferred tools are sent with
	// defer_loading: true.
	WasDeferred(toolName string) bool
}

DeferFilter controls deferred tool loading for the LLM. When a tool in the agent's tool list implements DeferFilter:

  • IsDeferred returns true → tool schema is excluded from the API request
  • WasDeferred returns true → tool schema is sent with defer_loading: true

Unactivated deferred tools are excluded entirely. Once activated via tool_reference, they are sent with defer_loading: true so the API server manages their context loading. Tools remain registered for execution regardless — only their API visibility changes.

IsDeferred is also used by the system prompt builder to exclude unactivated tools from the tool description section (they appear in <available-deferred-tools> by name only).

type EndReason added in v1.5.7

type EndReason string

EndReason describes why a single agent run stopped.

const (
	EndReasonStop     EndReason = "stop"
	EndReasonMaxTurns EndReason = "max_turns"
	EndReasonAborted  EndReason = "aborted"
	EndReasonError    EndReason = "error"
)

type Event

type Event struct {
	Type             EventType
	Message          AgentMessage    // for message_start/update/end, turn_end
	Delta            string          // text delta for message_update
	ToolID           string          // for tool_exec_*
	Tool             string          // tool name for tool_exec_*
	ToolLabel        string          // human-readable tool label (from ToolLabeler)
	Args             json.RawMessage // tool args for tool_exec_start/tool_exec_update
	Result           json.RawMessage // tool result for tool_exec_end and preview updates
	Progress         *ProgressPayload
	UpdateKind       ToolExecUpdateKind
	IsError          bool // tool error flag for tool_exec_end
	ApprovalDecision ToolApprovalDecision
	ApprovalReason   string
	Preview          json.RawMessage
	ToolResults      []ToolResult   // for turn_end: all tool results from this turn
	Err              error          // for error events
	NewMessages      []AgentMessage // for agent_end: messages added during this loop
	RetryInfo        *RetryInfo     // for retry events
	Summary          *RunSummary    // for agent_end: factual run summary
}

Event is a lifecycle event emitted by the agent loop. This is the single output channel for all lifecycle information.

type EventStream added in v1.5.1

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

EventStream wraps an event channel to provide both real-time iteration and deferred result collection.

Usage:

stream := agentcore.NewEventStream(AgentLoop(...))
for ev := range stream.Events() {
    // handle real-time events
}
msgs, err := stream.Result()

func NewEventStream added in v1.5.1

func NewEventStream(source <-chan Event) *EventStream

NewEventStream creates an EventStream that reads from the source channel. Events are forwarded to an internal channel for iteration. The final result is captured from EventAgentEnd.

func (*EventStream) Done added in v1.5.1

func (s *EventStream) Done() <-chan struct{}

Done returns a channel that is closed when the stream finishes.

func (*EventStream) Events added in v1.5.1

func (s *EventStream) Events() <-chan Event

Events returns the event channel for real-time iteration. The channel is closed when the source is exhausted.

func (*EventStream) Result added in v1.5.1

func (s *EventStream) Result() ([]AgentMessage, error)

Result blocks until the stream is done and returns the final messages. Returns the error from the last EventError, if any.

type EventType

type EventType string

EventType identifies agent lifecycle event types.

const (
	EventAgentStart           EventType = "agent_start"
	EventAgentEnd             EventType = "agent_end"
	EventTurnStart            EventType = "turn_start"
	EventTurnEnd              EventType = "turn_end"
	EventMessageStart         EventType = "message_start"
	EventMessageUpdate        EventType = "message_update"
	EventMessageEnd           EventType = "message_end"
	EventToolExecStart        EventType = "tool_exec_start"
	EventToolExecUpdate       EventType = "tool_exec_update"
	EventToolExecEnd          EventType = "tool_exec_end"
	EventToolApprovalRequest  EventType = "tool_approval_request"
	EventToolApprovalResolved EventType = "tool_approval_resolved"
	EventRetry                EventType = "retry"
	EventError                EventType = "error"
)

type FuncTool

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

FuncTool wraps a function as a Tool (convenience helper).

func NewFuncTool

func NewFuncTool(name, description string, schema map[string]any, fn func(ctx context.Context, args json.RawMessage) (json.RawMessage, error)) *FuncTool

func (*FuncTool) Description

func (t *FuncTool) Description() string

func (*FuncTool) Execute

func (t *FuncTool) Execute(ctx context.Context, args json.RawMessage) (json.RawMessage, error)

func (*FuncTool) Name

func (t *FuncTool) Name() string

func (*FuncTool) Schema

func (t *FuncTool) Schema() map[string]any

type ImageData

type ImageData struct {
	Data     string `json:"data,omitempty"`
	URL      string `json:"url,omitempty"`
	MimeType string `json:"mime_type,omitempty"`
}

ImageData holds image content as base64 data or a URL. When URL is set, providers pass it directly (no download/encoding needed). When Data is set, it is sent as a base64 data URL with MimeType. MimeType is required for base64 mode, optional for URL mode (provider infers it).

type InjectDisposition added in v1.5.7

type InjectDisposition string

InjectDisposition describes how an injected message was delivered.

const (
	InjectSteeredCurrentRun InjectDisposition = "steered_current_run"
	InjectResumedIdleRun    InjectDisposition = "resumed_idle_run"
	InjectQueued            InjectDisposition = "queued"
)

type InjectResult added in v1.5.7

type InjectResult struct {
	Disposition InjectDisposition
}

InjectResult reports the delivery outcome of Agent.Inject.

type LLMRequest

type LLMRequest struct {
	Messages []Message
	Tools    []ToolSpec
}

LLMRequest is the request passed to StreamFn.

type LLMResponse

type LLMResponse struct {
	Message Message
}

LLMResponse is the response from StreamFn.

type LoopConfig

type LoopConfig struct {
	Model         ChatModel
	StreamFn      StreamFn      // nil = use Model directly
	MaxTurns      int           // safety limit, default 10
	MaxRetries    int           // LLM call retry limit for retryable errors, default 3
	MaxToolErrors int           // consecutive tool failure threshold per tool, 0 = unlimited
	ThinkingLevel ThinkingLevel // reasoning depth

	// Two-stage pipeline: TransformContext -> ConvertToLLM
	TransformContext func(ctx context.Context, msgs []AgentMessage) ([]AgentMessage, error)
	ConvertToLLM     func(msgs []AgentMessage) []Message

	// CheckToolApproval is called after validation/preview and before execution.
	// Returning nil means no approval was required.
	// Returning a non-nil result applies the approval decision immediately.
	CheckToolApproval ToolApprovalFunc

	// GetApiKey resolves the API key before each LLM call.
	// The provider parameter identifies which provider is being called (e.g. "openai", "anthropic").
	// Enables per-provider key resolution, key rotation, OAuth tokens, and multi-tenant scenarios.
	// When nil or returns empty string, the model's default key is used.
	GetApiKey func(provider string) (string, error)

	// ThinkingBudgets maps each ThinkingLevel to a max thinking token count.
	// When set, the resolved budget is passed to the model alongside the level.
	ThinkingBudgets map[ThinkingLevel]int

	// SessionID enables provider-level session caching (e.g. Anthropic prompt cache).
	SessionID string

	// Steering: called after each tool execution to check for user interruptions.
	GetSteeringMessages func() []AgentMessage

	// FollowUp: called when the agent would otherwise stop.
	GetFollowUpMessages func() []AgentMessage

	// MaxRetryDelay caps the wait time between retries (including server-requested Retry-After).
	// Default: 60s. Set to prevent excessively long waits from overloaded providers.
	MaxRetryDelay time.Duration

	// Middlewares are applied around each tool execution (outermost first).
	// Use for logging, timing, argument/result modification, etc.
	Middlewares []ToolMiddleware

	// MaxToolConcurrency limits parallel tool execution.
	// 0 or 1 = sequential (default, backward compatible).
	// >1 = up to N tools execute concurrently within a single turn.
	MaxToolConcurrency int

	// ShouldEmitAbortMarker reports whether an abort marker message should be
	// emitted when the context is cancelled. When nil or returns false, the
	// cancellation is silent (legacy behavior). Set by Agent.Abort().
	ShouldEmitAbortMarker func() bool
}

LoopConfig configures the agent loop.

type Message

type Message struct {
	Role       Role           `json:"role"`
	Content    []ContentBlock `json:"content"`
	StopReason StopReason     `json:"stop_reason,omitempty"`
	Usage      *Usage         `json:"usage,omitempty"`
	Metadata   map[string]any `json:"metadata,omitempty"`
	Timestamp  time.Time      `json:"timestamp"`
}

Message is an LLM-level message with structured content blocks.

func AbortMsg added in v1.5.1

func AbortMsg(text, phase string) Message

AbortMsg creates an assistant abort marker message. phase is "inference" or "tool_execution".

func CollectMessages

func CollectMessages(msgs []AgentMessage) []Message

CollectMessages extracts concrete Messages from an AgentMessage slice, dropping custom types. Use this to serialize conversation history.

func DefaultConvertToLLM

func DefaultConvertToLLM(msgs []AgentMessage) []Message

DefaultConvertToLLM filters AgentMessages to LLM-compatible Messages. Custom message types are dropped; only user/assistant/system/tool messages pass through.

func RepairMessageSequence

func RepairMessageSequence(msgs []Message) []Message

RepairMessageSequence ensures tool call / tool result pairs are complete. Orphaned tool calls (no matching result) get a synthetic error result inserted. Orphaned tool results (no matching call) are removed. This prevents LLM providers from rejecting malformed message sequences.

func SystemMsg

func SystemMsg(text string) Message

SystemMsg creates a system message.

func ToolResultMsg

func ToolResultMsg(toolCallID string, content json.RawMessage, isError bool) Message

ToolResultMsg creates a tool result message.

func UserMsg

func UserMsg(text string) Message

UserMsg creates a user message from plain text.

func (Message) GetRole

func (m Message) GetRole() Role

func (Message) GetTimestamp

func (m Message) GetTimestamp() time.Time

func (Message) HasToolCalls

func (m Message) HasToolCalls() bool

HasToolCalls reports whether any tool call blocks exist.

func (Message) IsEmpty

func (m Message) IsEmpty() bool

IsEmpty reports whether the message has no meaningful content.

func (Message) TextContent

func (m Message) TextContent() string

TextContent returns the concatenated text from all text blocks.

func (Message) ThinkingContent

func (m Message) ThinkingContent() string

ThinkingContent returns the concatenated thinking text.

func (Message) ToolCalls

func (m Message) ToolCalls() []ToolCall

ToolCalls returns all tool call blocks.

type Previewer added in v1.5.1

type Previewer interface {
	Preview(ctx context.Context, args json.RawMessage) (json.RawMessage, error)
}

Previewer is an optional interface for tools that can compute a preview (e.g., diff) before execution. The agent loop calls Preview and emits the result as EventToolExecUpdate so the UI can display it before the tool runs.

type ProgressPayload added in v1.5.7

type ProgressPayload struct {
	Kind       ProgressPayloadKind `json:"kind"`
	Agent      string              `json:"agent,omitempty"`
	Tool       string              `json:"tool,omitempty"`
	Summary    string              `json:"summary,omitempty"`
	Delta      string              `json:"delta,omitempty"`
	Thinking   string              `json:"thinking,omitempty"`
	Message    string              `json:"message,omitempty"`
	Turn       int                 `json:"turn,omitempty"`
	Attempt    int                 `json:"attempt,omitempty"`
	MaxRetries int                 `json:"max_retries,omitempty"`
	IsError    bool                `json:"is_error,omitempty"`
	Args       json.RawMessage     `json:"args,omitempty"`
	Meta       json.RawMessage     `json:"meta,omitempty"`
}

ProgressPayload is the structured progress envelope emitted by tools.

type ProgressPayloadKind added in v1.5.7

type ProgressPayloadKind string

ProgressPayloadKind distinguishes structured progress update semantics.

const (
	ProgressToolStart   ProgressPayloadKind = "tool_start"
	ProgressToolDelta   ProgressPayloadKind = "tool_delta"
	ProgressThinking    ProgressPayloadKind = "thinking"
	ProgressSummary     ProgressPayloadKind = "summary"
	ProgressToolError   ProgressPayloadKind = "tool_error"
	ProgressTurnCounter ProgressPayloadKind = "turn_counter"
	ProgressRetry       ProgressPayloadKind = "retry"
)

type ProviderNamer

type ProviderNamer interface {
	ProviderName() string
}

ProviderNamer is an optional interface for ChatModel implementations to expose their provider name (e.g. "openai", "anthropic", "gemini"). Used by the agent loop to pass provider context to GetApiKey callbacks.

type ProxyEvent

type ProxyEvent struct {
	Type       ProxyEventType `json:"type"`
	Delta      string         `json:"delta,omitempty"`
	ToolCallID string         `json:"tool_call_id,omitempty"`
	ToolName   string         `json:"tool_name,omitempty"`
	StopReason StopReason     `json:"stop_reason,omitempty"`
	Usage      *Usage         `json:"usage,omitempty"`
	Err        error          `json:"-"`
}

ProxyEvent is a bandwidth-optimized event from a remote proxy server. The client reconstructs the full message incrementally from these deltas.

type ProxyEventType

type ProxyEventType string

ProxyEventType identifies proxy streaming event types. Proxy events are bandwidth-optimized: they carry only deltas, not the full partial message on each event.

const (
	ProxyEventTextDelta     ProxyEventType = "text_delta"
	ProxyEventThinkingDelta ProxyEventType = "thinking_delta"
	ProxyEventToolCallStart ProxyEventType = "toolcall_start"
	ProxyEventToolCallDelta ProxyEventType = "toolcall_delta"
	ProxyEventDone          ProxyEventType = "done"
	ProxyEventError         ProxyEventType = "error"
)

type ProxyModel

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

ProxyModel implements ChatModel by forwarding to a remote proxy server. It reconstructs streaming events from bandwidth-optimized ProxyEvents.

Usage:

proxy := agentcore.NewProxyModel(myProxyFn)
agent := agentcore.NewAgent(agentcore.WithModel(proxy))

func NewProxyModel

func NewProxyModel(fn ProxyStreamFn) *ProxyModel

NewProxyModel creates a ChatModel that delegates to a proxy stream function.

func (*ProxyModel) Generate

func (p *ProxyModel) Generate(ctx context.Context, messages []Message, tools []ToolSpec, opts ...CallOption) (*LLMResponse, error)

Generate collects the full streamed response synchronously.

func (*ProxyModel) GenerateStream

func (p *ProxyModel) GenerateStream(ctx context.Context, messages []Message, tools []ToolSpec, opts ...CallOption) (<-chan StreamEvent, error)

GenerateStream converts proxy events into standard StreamEvents.

func (*ProxyModel) SupportsTools

func (p *ProxyModel) SupportsTools() bool

SupportsTools reports that the proxy can handle tool calls.

type ProxyStreamFn

type ProxyStreamFn func(ctx context.Context, req *LLMRequest) (<-chan ProxyEvent, error)

ProxyStreamFn makes an LLM call through a remote proxy and returns a channel of bandwidth-optimized ProxyEvents.

type QueueMode

type QueueMode string

QueueMode controls how steering/follow-up queues are drained.

const (
	QueueModeAll        QueueMode = "all"
	QueueModeOneAtATime QueueMode = "one-at-a-time"
)

type RetryInfo

type RetryInfo struct {
	Attempt    int
	MaxRetries int
	Delay      time.Duration
	Err        error
}

RetryInfo carries retry context for EventRetry events.

type Role

type Role string

Role defines message roles.

const (
	RoleUser      Role = "user"
	RoleAssistant Role = "assistant"
	RoleSystem    Role = "system"
	RoleTool      Role = "tool"
)

type RunSummary added in v1.5.7

type RunSummary struct {
	TurnCount  int
	ToolCalls  int
	ToolErrors int
	EndReason  EndReason
}

RunSummary captures loop facts that are known at the end of a run. It intentionally excludes higher-level policy judgments.

type StopReason

type StopReason string

StopReason indicates why the LLM stopped generating.

const (
	StopReasonStop    StopReason = "stop"
	StopReasonLength  StopReason = "length"
	StopReasonToolUse StopReason = "toolUse"
	StopReasonError   StopReason = "error"
	StopReasonAborted StopReason = "aborted"
)

type StreamEvent

type StreamEvent struct {
	Type         StreamEventType
	ContentIndex int        // which content block is being updated
	Delta        string     // text/thinking/toolcall argument delta
	Message      Message    // partial (during streaming) or final (done)
	StopReason   StopReason // finish reason (for done events)
	Err          error      // for error events
}

StreamEvent is a streaming event from the LLM.

type StreamEventType

type StreamEventType string

StreamEventType identifies LLM streaming event types.

const (
	// Text content streaming
	StreamEventTextStart StreamEventType = "text_start"
	StreamEventTextDelta StreamEventType = "text_delta"
	StreamEventTextEnd   StreamEventType = "text_end"

	// Thinking/reasoning streaming
	StreamEventThinkingStart StreamEventType = "thinking_start"
	StreamEventThinkingDelta StreamEventType = "thinking_delta"
	StreamEventThinkingEnd   StreamEventType = "thinking_end"

	// Tool call streaming
	StreamEventToolCallStart StreamEventType = "toolcall_start"
	StreamEventToolCallDelta StreamEventType = "toolcall_delta"
	StreamEventToolCallEnd   StreamEventType = "toolcall_end"

	// Terminal events
	StreamEventDone  StreamEventType = "done"
	StreamEventError StreamEventType = "error"
)

type StreamFn

type StreamFn func(ctx context.Context, req *LLMRequest) (*LLMResponse, error)

StreamFn is an injectable LLM call function. When nil, the loop uses model.Generate / model.GenerateStream directly.

type SubAgentConfig

type SubAgentConfig struct {
	Name        string
	Description string
	// Model is resolved when each sub-agent run starts. Wrappers that swap
	// the underlying model at runtime are supported and take effect on the
	// next sub-agent run.
	Model        ChatModel
	SystemPrompt string
	Tools        []Tool
	StreamFn     StreamFn
	MaxTurns     int

	// Optional two-stage context pipeline (same as Agent-level).
	// When set, enables automatic context compaction for long-running sub-agents.
	TransformContext func(ctx context.Context, msgs []AgentMessage) ([]AgentMessage, error)
	ConvertToLLM     func(msgs []AgentMessage) []Message
}

SubAgentConfig defines a sub-agent's identity and capabilities.

type SubAgentTool

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

SubAgentTool implements the Tool interface. The main agent calls this tool to delegate tasks to specialized sub-agents with isolated contexts.

func NewSubAgentTool

func NewSubAgentTool(agents ...SubAgentConfig) *SubAgentTool

NewSubAgentTool creates a subagent tool from a set of agent configs.

func (*SubAgentTool) BackgroundTasks added in v1.5.3

func (t *SubAgentTool) BackgroundTasks() []BackgroundTask

BackgroundTasks returns a snapshot of all background tasks.

func (*SubAgentTool) Description

func (t *SubAgentTool) Description() string

func (*SubAgentTool) Execute

func (t *SubAgentTool) Execute(ctx context.Context, args json.RawMessage) (json.RawMessage, error)

func (*SubAgentTool) Label

func (t *SubAgentTool) Label() string

func (*SubAgentTool) Name

func (t *SubAgentTool) Name() string

func (*SubAgentTool) Schema

func (t *SubAgentTool) Schema() map[string]any

func (*SubAgentTool) SetBgOutputFactory added in v1.5.3

func (t *SubAgentTool) SetBgOutputFactory(fn func(taskID, agentName string) (io.WriteCloser, string, error))

SetBgOutputFactory sets the factory that creates output writers for background tasks. The factory receives the task ID and agent name, returns a writer, file path, and error. If not set, background output is not persisted.

func (*SubAgentTool) SetCreateModel added in v1.5.1

func (t *SubAgentTool) SetCreateModel(fn func(name string) (ChatModel, error))

SetCreateModel sets the factory for resolving model names (e.g. "haiku", "gpt-4o-mini") to ChatModel instances at runtime. Enables LLM to override the default model per call.

func (*SubAgentTool) SetNotifyFn added in v1.5.1

func (t *SubAgentTool) SetNotifyFn(fn func(AgentMessage))

SetNotifyFn sets the callback invoked when a background task completes. Typically bound to Agent.FollowUp so the main agent receives the result as a follow-up message.

func (*SubAgentTool) StopAllBackgroundTasks added in v1.5.3

func (t *SubAgentTool) StopAllBackgroundTasks() int

StopAllBackgroundTasks cancels all running background tasks.

func (*SubAgentTool) StopBackgroundTask added in v1.5.3

func (t *SubAgentTool) StopBackgroundTask(id string) bool

StopBackgroundTask cancels a running background task by ID.

type SwappableModel added in v1.5.7

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

SwappableModel wraps a ChatModel and allows replacing the underlying model at runtime. Swaps take effect on the next call.

func NewSwappableModel added in v1.5.7

func NewSwappableModel(initial ChatModel) *SwappableModel

func (*SwappableModel) Current added in v1.5.7

func (m *SwappableModel) Current() ChatModel

func (*SwappableModel) Generate added in v1.5.7

func (m *SwappableModel) Generate(ctx context.Context, messages []Message, tools []ToolSpec, opts ...CallOption) (*LLMResponse, error)

func (*SwappableModel) GenerateStream added in v1.5.7

func (m *SwappableModel) GenerateStream(ctx context.Context, messages []Message, tools []ToolSpec, opts ...CallOption) (<-chan StreamEvent, error)

func (*SwappableModel) ProviderName added in v1.5.7

func (m *SwappableModel) ProviderName() string

func (*SwappableModel) SupportsTools added in v1.5.7

func (m *SwappableModel) SupportsTools() bool

func (*SwappableModel) Swap added in v1.5.7

func (m *SwappableModel) Swap(next ChatModel)

type SystemBlock added in v1.5.2

type SystemBlock struct {
	Text         string `json:"text"`
	CacheControl string `json:"cache_control,omitempty"` // e.g. "ephemeral"
}

SystemBlock is one segment of a multi-part system prompt. Use with AgentContext.SystemBlocks for per-block cache control.

type ThinkingLevel

type ThinkingLevel string

ThinkingLevel configures the reasoning depth for models that support it.

const (
	ThinkingOff     ThinkingLevel = "off"
	ThinkingMinimal ThinkingLevel = "minimal"
	ThinkingLow     ThinkingLevel = "low"
	ThinkingMedium  ThinkingLevel = "medium"
	ThinkingHigh    ThinkingLevel = "high"
	ThinkingXHigh   ThinkingLevel = "xhigh"
)

type Tool

type Tool interface {
	Name() string
	Description() string
	Schema() map[string]any
	Execute(ctx context.Context, args json.RawMessage) (json.RawMessage, error)
}

Tool defines the minimal tool interface. Timeout control goes through context.Context. Tools can report execution progress via ReportToolProgress(ctx, payload).

type ToolApprovalDecision added in v1.5.6

type ToolApprovalDecision string

ToolApprovalDecision describes the outcome of a runtime approval check.

const (
	ToolApprovalAllowOnce    ToolApprovalDecision = "allow_once"
	ToolApprovalAllowSession ToolApprovalDecision = "allow_session"
	ToolApprovalAllowAlways  ToolApprovalDecision = "allow_always"
	ToolApprovalDeny         ToolApprovalDecision = "deny"
)

type ToolApprovalFunc added in v1.5.6

type ToolApprovalFunc func(ctx context.Context, req ToolApprovalRequest) (*ToolApprovalResult, error)

ToolApprovalFunc is called before tool execution when a runtime approval system is configured. Returning nil means "no approval needed". Returning a non-nil result applies the decision immediately.

type ToolApprovalRequest added in v1.5.6

type ToolApprovalRequest struct {
	Call      ToolCall
	ToolLabel string
	Summary   string
	Reason    string
	Preview   []byte
}

ToolApprovalRequest is sent to an approval callback before a tool executes. Approval systems can use Summary/Reason/Preview to present higher-signal UI.

type ToolApprovalResult added in v1.5.6

type ToolApprovalResult struct {
	Approved bool
	Decision ToolApprovalDecision
	Reason   string
}

ToolApprovalResult is returned by a runtime approval callback.

type ToolCall

type ToolCall struct {
	ID   string          `json:"id"`
	Name string          `json:"name"`
	Args json.RawMessage `json:"args"`
}

ToolCall represents a tool invocation request from the LLM.

type ToolExecUpdateKind added in v1.5.1

type ToolExecUpdateKind string

ToolExecUpdateKind distinguishes update payload semantics for tool_exec_update events.

const (
	ToolExecUpdatePreview  ToolExecUpdateKind = "preview"
	ToolExecUpdateProgress ToolExecUpdateKind = "progress"
)

type ToolExecuteFunc added in v1.5.1

type ToolExecuteFunc func(ctx context.Context, args json.RawMessage) (json.RawMessage, error)

ToolExecuteFunc is the function signature for tool execution. Used as the "next" parameter in middleware chains.

type ToolLabeler

type ToolLabeler interface {
	Label() string
}

ToolLabeler is an optional interface for tools to provide a human-readable label.

type ToolMiddleware added in v1.5.1

type ToolMiddleware func(ctx context.Context, call ToolCall, next ToolExecuteFunc) (json.RawMessage, error)

ToolMiddleware wraps tool execution with cross-cutting concerns. Call next to continue the chain; skip next to short-circuit execution. Example: logging, timing, argument/result modification, audit.

type ToolProgressFunc

type ToolProgressFunc func(progress ProgressPayload)

ToolProgressFunc is a callback for reporting tool execution progress. Tools call ReportToolProgress to emit partial results during long operations.

type ToolResult

type ToolResult struct {
	ToolCallID    string          `json:"tool_call_id"`
	ToolName      string          `json:"-"` // internal: for toolErrors tracking
	Content       json.RawMessage `json:"content,omitempty"`
	ContentBlocks []ContentBlock  `json:"-"` // rich content (images); not serialized
	IsError       bool            `json:"is_error,omitempty"`
	Details       any             `json:"details,omitempty"` // optional metadata for UI display/logging
}

ToolResult represents a tool execution outcome.

type ToolSpec

type ToolSpec struct {
	Name         string `json:"name"`
	Description  string `json:"description"`
	Parameters   any    `json:"parameters"`
	DeferLoading bool   `json:"defer_loading,omitempty"`
}

ToolSpec describes a tool for the LLM (name + description + JSON schema).

type Usage

type Usage struct {
	Input       int   `json:"input"`
	Output      int   `json:"output"`
	CacheRead   int   `json:"cache_read"`
	CacheWrite  int   `json:"cache_write"`
	TotalTokens int   `json:"total_tokens"`
	Cost        *Cost `json:"cost,omitempty"`
}

Usage tracks token consumption for a single LLM call.

Field semantics:

  • Input: prompt tokens sent to the model (includes cached tokens for some providers)
  • Output: completion tokens generated (includes reasoning tokens if applicable)
  • CacheRead: tokens served from prompt cache (Anthropic: cache_read_input_tokens)
  • CacheWrite: tokens written to prompt cache (Anthropic: cache_creation_input_tokens)
  • TotalTokens: provider-reported total, typically Input + Output
  • Cost: monetary cost computed from model pricing (nil if pricing unavailable)

func (*Usage) Add

func (u *Usage) Add(other *Usage)

Add accumulates another Usage into this one (nil-safe).

Directories

Path Synopsis
examples
multi command
single command
Package schema provides a fluent builder for JSON Schema objects.
Package schema provides a fluent builder for JSON Schema objects.

Jump to

Keyboard shortcuts

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