agentloop

package
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Jul 29, 2026 License: Apache-2.0 Imports: 38 Imported by: 0

Documentation

Index

Constants

View Source
const BasePrompt = `` /* 1956-byte string literal not displayed */

BasePrompt is the base system prompt for the agent.

Variables

View Source
var FinalResponseExtractor = llm.MustTagExtractor("final_response")

FinalResponseExtractor extracts content enclosed in <final_response>...</final_response> tags.

Functions

func Append added in v0.0.17

func Append[T any](m *MetadataStore, key string, items ...T)

Append appends items to the []T slice stored at key in a MetadataStore. If the key does not exist, a new slice is created. Panics if the existing value is not of type []T.

func ArrayParam

func ArrayParam(desc string, elemInfo *schema.ParameterInfo, required bool) *schema.ParameterInfo

ArrayParam creates an array parameter with element info.

func BoolParam

func BoolParam(desc string, required bool) *schema.ParameterInfo

BoolParam creates a boolean parameter.

func GetCurrentTime

func GetCurrentTime(timezone float64) string

GetCurrentTime returns the current time formatted for display.

func GetMeta added in v0.0.17

func GetMeta[T any](m *MetadataStore, key string) (T, bool)

GetMeta retrieves a typed value from a MetadataStore. Returns the typed value and true if the key exists and the value is assignable to T, zero value and false otherwise.

func IntParam

func IntParam(desc string, required bool) *schema.ParameterInfo

IntParam creates an integer parameter.

func NumberParam

func NumberParam(desc string, required bool) *schema.ParameterInfo

NumberParam creates a number parameter.

func ObjectParam

func ObjectParam(desc string, subParams map[string]*schema.ParameterInfo, required bool) *schema.ParameterInfo

ObjectParam creates an object parameter with sub-parameters.

func RegisterToolAlias added in v0.0.26

func RegisterToolAlias(alias, canonical string)

RegisterToolAlias registers alias as an alternative name for the canonical built-in tool name. logToolStart uses this map to log tool args even when the tool was created with a custom name. Tool constructors that support custom names call this automatically when a non-default name is used.

func RequestHitlInterrupt added in v0.1.0

func RequestHitlInterrupt(agentCtx AgentContext, reason string)

RequestHitlInterrupt signals a HITL interrupt from within a tool implementation. The tool should also return a descriptive message to the LLM explaining what the user needs to do. The agent loop will pause after the current tool batch completes, persist its state, and return TaskOutput.Interrupted = true.

This function is a no-op if HitlStore is not configured on the current agent.

func StringParam

func StringParam(desc string, required bool) *schema.ParameterInfo

StringParam creates a string parameter.

func StringParamEnum

func StringParamEnum(desc string, enumValues []string, required bool) *schema.ParameterInfo

StringParamEnum creates a string parameter with enum values.

func WithEnableFileTool

func WithEnableFileTool(v bool) func(o *BuiltinToolsOption)

WithEnableFileTool enables or disables the built-in file tools (read_file, write_file, edit_file, list_directory, glob, add_artifact).

func WithEnableTodoTool added in v0.0.20

func WithEnableTodoTool(v bool) func(o *BuiltinToolsOption)

WithEnableTodoTool enables or disables the built-in todo tools (add_todo, update_todo, list_todos, delete_todo).

Types

type AddArtifactArgs

type AddArtifactArgs struct {
	Path     string            `json:"path"`
	Metadata map[string]string `json:"metadata,omitempty"`
}

type AddTodoArgs

type AddTodoArgs struct {
	Todos []TodoItemInput `json:"todos"`
}

type Agent

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

Agent is a ReAct (Reasoning + Acting) agent that can process tasks using tools and skills. The graph is compiled once and can be reused across multiple Execute calls for efficiency. Each Execute call receives fresh skills and backend via taskInput, allowing for stateful backends. Capabilities:

  • Tool calling with automatic backend injection
  • Skills system with progressive disclosure
  • Token-aware message pruning

func NewAgent

func NewAgent(config AgentConfig, optCtx ...context.Context) (*Agent, error)

NewAgent creates a new ReAct agent.

func (*Agent) Execute

func (a *Agent) Execute(rail flow.Rail, req AgentRequest) (TaskOutput, error)

Execute runs the agent with the given request.

func (*Agent) Resume added in v0.1.0

func (a *Agent) Resume(rail flow.Rail, req AgentRequest) (TaskOutput, error)

Resume resumes an interrupted agent session. The session must have been previously interrupted (TaskOutput.Interrupted == true). req.SessionId must match the SessionId from the interrupted Execute or Resume call. req.UserInput is the human's response, appended to the restored conversation before the loop continues. All other AgentRequest fields work the same as Execute.

The persisted HITL state is deleted from HitlStore only on a clean finish (no error and not re-interrupted). On error the state is left untouched so the caller can retry. On re-interrupt, hitl_output overwrites the state with the new checkpoint.

type AgentConfig

type AgentConfig struct {
	// Name is an optional identifier for the agent used in logs.
	// If empty, defaults to "AgentLoop".
	Name string

	// ModelName is the model identifier passed to the underlying OpenAI-compatible
	// provider (e.g. "qwen3-max").
	ModelName string

	// ApiKey is the API key for the model provider.
	ApiKey string

	// ApiUrl is the base URL of the OpenAI-compatible API endpoint.
	// If empty, defaults to agents.AliBailianIntlBaseURL (see [agents.NewOpenAIChatModel]).
	ApiUrl string

	// Temperature controls sampling randomness for the model.
	// If 0, defaults to 0.7.
	Temperature float32

	// MaxRunSteps limits the maximum number of ReAct rounds (tool-call cycles) the agent may execute.
	// Enforced directly by the agent loop's own round counter (not by Eino's internal step counter),
	// so it maps 1:1 to actual chat-model calls regardless of graph topology (e.g. whether OutputCheck
	// or tools are enabled).
	// If 0 or negative, defaults to 5.
	MaxRunSteps int

	// Language specifies the language for agent responses.
	// If empty, defaults to "English".
	Language string

	// LogOnStart controls whether the agent logs when it starts processing.
	// If nil, defaults to true.
	LogOnStart *bool

	// LogOnEnd controls whether the agent logs token stats when it finishes.
	// If nil, defaults to true.
	LogOnEnd *bool

	// LogInputs controls whether the agent logs input messages to the model.
	// If nil, defaults to false.
	LogInputs *bool

	// LogOutputs controls whether the agent logs model and tool output content.
	// If nil, defaults to true.
	LogOutputs *bool

	// Tools is a list of custom tools to add to the built-in tools.
	// Built-in tools are always registered; this field adds additional tools.
	//
	// Create custom tools using helper functions:
	//   - [NewToolFunc] - for simple tools with map-based arguments
	//   - [NewCtxAwareToolFunc] - for tools needing AgentContext (Store, Todos)
	//   - [NewTypedToolFunc] - for tools with typed struct arguments
	//   - [NewTypedCtxAwareToolFunc] - for tools with typed arguments and AgentContext
	Tools []Tool

	// SystemPrompt is an optional task prompt.
	// If provided, it will be prepended to the base system prompt.
	SystemPrompt string

	// BackendFactory is a factory function that creates a fresh FileStore for each execution.
	// If nil, a new TmpFileStore will be created for each execution.
	// This allows stateful backends to be created fresh per execution.
	BackendFactory func() FileStore

	// Timezone is the timezone offset in hours for time display (default: 0, UTC).
	Timezone float64

	// MaxTokens is the maximum number of tokens allowed in the conversation history.
	// When exceeded, old messages will be pruned (except system messages).
	// If 0 or negative, no token limit is enforced.
	// Default: 0 (no limit)
	MaxTokens int

	// EnableModelsFetch enables runtime fetching of model context window sizes
	// from models.dev when the model is not found in the build-time generated map.
	// Fetched results are cached in memory for the process lifetime.
	EnableModelsFetch bool

	// EnableFileTool enables the built-in file tools: read_file, write_file, edit_file,
	// list_directory, glob, and add_artifact. When false, these tools are not registered.
	// If nil, defaults to true.
	EnableFileTool *bool

	// EnableTodoTool enables the built-in todo tools: add_todo, update_todo, list_todos,
	// delete_todo. When false, these tools are not registered.
	// If nil, defaults to false.
	EnableTodoTool *bool

	// EnableBashTool enables the built-in bash tool, which executes shell scripts in a
	// sandboxed environment (github.com/mark3labs/go-bash). When the configured FileStore
	// implements DirBackedFileStore, the sandbox shares that store's real directory, so
	// bash can operate on files written via write_file/read_file. When false, the tool is
	// not registered. If nil, defaults to false.
	EnableBashTool *bool

	// BashToolOptions configures the built-in bash tool (timeout, network access). Only
	// used when EnableBashTool is true. See WithBashTimeout, WithBashNetwork.
	BashToolOptions []BashToolOption

	// ToolEventCallback is called synchronously for each tool invocation during execution.
	// Receives a ToolEvent with the tool name and raw JSON args before the tool runs.
	// Must not block for long — it runs within the agent graph execution.
	// If nil, no events are emitted.
	ToolEventCallback func(event ToolEvent)

	// Compaction enables LLM-based context compaction when the conversation history
	// approaches MaxTokens. Older messages are summarized into a structured checkpoint;
	// recent messages are kept verbatim. Requires MaxTokens to be set.
	// If nil, defaults to false.
	Compaction *bool

	// CompactPreserveRecentTokens is the token budget for the verbatim recent tail kept after compaction.
	// Messages within this budget (newest first) are sent to the model as-is; older messages are summarized.
	// When MaxTokens is known, defaults to max(2000, min(8000, MaxTokens * 0.25)) — i.e., 25% of the
	// context window, clamped between 2k and 8k tokens. Set explicitly to override.
	CompactPreserveRecentTokens int

	// ToolOffloadTokenLimit is the token threshold above which a tool result is
	// offloaded to the backend store and replaced with a short preview + file pointer.
	// The agent can recover the full content by calling the read_file tool on the
	// saved path. nil uses the default threshold of 20,000 tokens. Set to a non-nil
	// pointer to 0 to disable offloading entirely.
	//
	// The following tools are never offloaded regardless of size: read_file,
	// write_file, edit_file, list_directory, glob, grep, delete.
	ToolOffloadTokenLimit *int

	// ToolOffloadResultsPathPrefix is the FileStore path prefix for offloaded tool
	// results. Each offloaded result is written to:
	//   {ToolOffloadResultsPathPrefix}/{sanitized_tool_call_id}
	// Defaults to "/large_tool_results" when empty.
	ToolOffloadResultsPathPrefix string

	// EnableToolOffload controls whether large tool results are offloaded to the
	// backend store and replaced with a preview + file pointer.
	// If nil, defaults to true. Set to a non-nil pointer to false to disable.
	EnableToolOffload *bool

	// Middleware is an ordered list of middleware to apply to the agent loop.
	// Middlewares are called in registration order for BeforeAgent, AfterAgent,
	// SystemPromptFragment, and Tools; and composed into chains for WrapModelCall
	// and WrapToolCall. Middleware cannot be registered after NewAgent() returns.
	Middleware []Middleware

	// OutputCheck is an optional callback invoked on each plain-text (non-tool-call) assistant
	// response before the agent accepts it as the final output. If OutputCheck returns a non-nil
	// error, its message is inserted into the conversation as a user message and the chat model
	// is called again so it can self-correct.
	//
	// OutputCheck can be used for output format validation, quality checks, security screening,
	// or any other per-response review. If nil, no check is performed.
	OutputCheck OutputCheckFunc

	// EnableTrace enables per-node execution tracing. When true, each graph node's input and
	// output are JSON-marshaled and collected in TaskOutput.TraceLogs. ChatModel entries include
	// the full message history per call, so TraceLogs can grow large on long multi-turn runs.
	// If nil, defaults to false.
	EnableTrace *bool

	// EnableHitlInterruptTool registers the built-in interrupt_for_human tool, allowing
	// the LLM to pause execution by calling it directly. Only takes effect when HitlStore
	// is also set. When false, tools can still trigger HITL via [RequestHitlInterrupt].
	EnableHitlInterruptTool bool

	// HitlStore persists interrupted session state for later resumption via [Agent.Resume].
	// When set, HITL is automatically enabled: tools may call [RequestHitlInterrupt] to
	// pause execution; the agent persists its state and returns TaskOutput.Interrupted = true.
	HitlStore HitlStore

	// Log user query, default true
	LogQuery *bool

	// ContentModeration is an optional callback to screen content at the boundary of agent execution.
	// It is called twice per Execute/Resume: once with contentType="INPUT" before the agent runs
	// (screening the user input), and once with contentType="OUTPUT" after the agent runs
	// (screening the agent's response). Returning ok=false aborts execution and surfaces the
	// reason as an error. If nil, no moderation is applied.
	ContentModeration ContentModerationFunc
}

AgentConfig is the configuration for creating an agent.

type AgentContext

type AgentContext struct {
	SessionId string
	UserInput string
	Store     FileStore
	Todos     *TodoManager
	Artifacts *ArtifactManager
	Metadata  *MetadataStore
	// contains filtered or unexported fields
}

AgentContext holds per-execution stateful components. Accessible from tool and middleware callbacks via the context.

type AgentRequest

type AgentRequest struct {
	// SessionId is an optional identifier for this execution.
	// If empty, a unique ID is generated automatically with the prefix "sess_".
	SessionId           string
	UserInput           string
	PreloadBackendFiles func(store FileStore) error                       // Optional callback to preload files into the backend before execution
	ArtifactCallback    func(store FileStore, artifacts []Artifact) error // Optional callback for artifacts
}

AgentRequest represents a request to execute an agent

type AgentSpec added in v0.0.15

type AgentSpec struct {
	// Name identifies the sub-agent; used by the LLM to select which agent to call.
	Name         string
	Capabilities string
	Builder      func(AgentContext) (*Agent, error)
}

AgentSpec defines a sub-agent that can be delegated tasks by the parent agent. Builder is called on each invocation with the current AgentContext; callers may cache the *Agent internally if construction is expensive.

func NewExplorerAgentSpec added in v0.0.26

func NewExplorerAgentSpec(name, modelName, host, apiKey string, tools []Tool) *AgentSpec

NewExplorerAgentSpec creates an AgentSpec for a general-purpose research sub-agent. Pass the returned spec to NewSubAgentTool to give a parent agent research capabilities.

name identifies the sub-agent; modelName is the model name, host is the API base URL, and apiKey is the API key used to construct the sub-agent's chat model. tools are the search/retrieval tools available to the explorer (e.g. TavilySearch). File tools are disabled; the explorer is read-only by design.

Example:

agentloop.NewSubAgentTool(
    agentloop.NewExplorerAgentSpec("explorer",
        "qwen3-max", agents.AliBailianCnBaseURL, apiKey,
        []agentloop.Tool{tavilyTool},
    ),
)

type Artifact

type Artifact struct {
	Path        string            // Backend file path
	SizeInBytes int64             // File size in bytes
	Meta        map[string]string // Additional metadata (title, url, etc.)
}

Artifact represents a discovered or created artifact during agent execution

type ArtifactManager

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

ArtifactManager manages artifacts collected during agent execution.

func NewArtifactManager

func NewArtifactManager() *ArtifactManager

NewArtifactManager creates a new artifact manager.

func (*ArtifactManager) AddArtifact

func (am *ArtifactManager) AddArtifact(artifact Artifact) error

AddArtifact adds a new artifact.

func (*ArtifactManager) GetArtifacts

func (am *ArtifactManager) GetArtifacts() []Artifact

GetArtifacts returns all artifacts (alias for ListArtifacts).

func (*ArtifactManager) ListArtifacts

func (am *ArtifactManager) ListArtifacts() []Artifact

ListArtifacts returns all artifacts.

type AutoTypedCtxAwareToolFunc added in v0.0.25

type AutoTypedCtxAwareToolFunc[T any] struct {
	// contains filtered or unexported fields
}

AutoTypedCtxAwareToolFunc is a tool that auto-deduces its parameter schema from T via JSON-schema reflection (using Eino's GoStruct2ParamsOneOf). It also has AgentContext access. Use NewAutoTypedCtxAwareToolFunc to construct it.

func (*AutoTypedCtxAwareToolFunc[T]) Description added in v0.0.25

func (t *AutoTypedCtxAwareToolFunc[T]) Description() string

Description returns the description of the tool.

func (*AutoTypedCtxAwareToolFunc[T]) Execute added in v0.0.25

func (t *AutoTypedCtxAwareToolFunc[T]) Execute(ctx context.Context, args map[string]interface{}) (string, error)

Execute is unused; AutoTypedCtxAwareToolFunc implements SelfInvokeTool.

func (*AutoTypedCtxAwareToolFunc[T]) ExecuteJson added in v0.0.25

func (t *AutoTypedCtxAwareToolFunc[T]) ExecuteJson(ctx context.Context, jsonArg string) (string, error)

ExecuteJson executes the tool with JSON arguments.

func (*AutoTypedCtxAwareToolFunc[T]) Name added in v0.0.25

func (t *AutoTypedCtxAwareToolFunc[T]) Name() string

Name returns the name of the tool.

func (*AutoTypedCtxAwareToolFunc[T]) Parameters added in v0.0.25

func (t *AutoTypedCtxAwareToolFunc[T]) Parameters() map[string]*schema.ParameterInfo

Parameters returns nil — schema is provided via ParamsOneOf instead.

func (*AutoTypedCtxAwareToolFunc[T]) ParamsOneOf added in v0.0.25

func (t *AutoTypedCtxAwareToolFunc[T]) ParamsOneOf() *schema.ParamsOneOf

ParamsOneOf returns the reflected parameter schema, satisfying deductedTool.

type BaseMiddleware added in v0.0.25

type BaseMiddleware struct{}

BaseMiddleware provides no-op defaults for all Middleware methods. Embed it and override only the hooks you need.

func (BaseMiddleware) AfterAgent added in v0.0.25

AfterAgent is a no-op. Override to add post-execution logic.

func (BaseMiddleware) BeforeAgent added in v0.0.25

func (BaseMiddleware) BeforeAgent(_ context.Context, _ AgentContext) error

BeforeAgent is a no-op. Override to add pre-execution logic.

func (BaseMiddleware) Name added in v0.0.25

func (BaseMiddleware) Name() string

Name returns an empty string. Override in your middleware to provide a unique name.

func (BaseMiddleware) SystemPromptFragment added in v0.0.25

func (BaseMiddleware) SystemPromptFragment(_ context.Context) string

SystemPromptFragment returns empty string. Override to inject prompt text.

func (BaseMiddleware) Tools added in v0.0.25

func (BaseMiddleware) Tools() []Tool

Tools returns nil. Override to contribute tools to the agent.

func (BaseMiddleware) WrapModelCall added in v0.0.25

WrapModelCall passes through to the next handler unchanged.

func (BaseMiddleware) WrapToolCall added in v0.0.25

WrapToolCall passes through to the next handler unchanged.

type BashArgs added in v0.1.0

type BashArgs struct {
	Script string `json:"script"`
}

BashArgs are the arguments accepted by the bash tool.

type BashToolOption added in v0.1.0

type BashToolOption func(*bashToolConfig)

BashToolOption configures the built-in bash tool. See WithBashTimeout, WithBashNetwork, and WithBashOutputSanitize.

func WithBashCommand added in v0.1.0

func WithBashCommand(name string, invoke func(ctx context.Context, args []string, c *CommandContext) CommandResult) BashToolOption

WithBashCommand registers an additional command available to bash scripts, on top of go-bash's built-in command set. A custom command overrides a built-in of the same name. Call multiple times to register more than one command:

WithBashCommand("mytool", func(ctx context.Context, args []string, c *CommandContext) CommandResult {
    return CommandResult{Stdout: "...", ExitCode: 0}
})

func WithBashNetwork added in v0.1.0

func WithBashNetwork(urlPrefixes ...string) BashToolOption

WithBashNetwork enables outbound network access for the bash tool's sandbox, restricted to the given URL prefixes (scheme+host[+port][+path prefix]). Private IP ranges are always denied. When not called, network access is disabled entirely.

func WithBashOutputSanitize added in v0.1.0

func WithBashOutputSanitize(sanitize func(command, stdout, stderr string) (string, string)) BashToolOption

WithBashOutputSanitize rewrites stdout and stderr returned by configured custom bash commands before the sandbox returns their command.Result. When a sanitizer is set, the built-in "history" command is also overridden so that its output is sanitized before being displayed to the agent.

func WithBashTimeout added in v0.1.0

func WithBashTimeout(d time.Duration) BashToolOption

WithBashTimeout sets the maximum duration a single bash tool call may run before being cancelled. Default: 30 seconds.

type BuiltinToolsOption

type BuiltinToolsOption struct {
	// EnableFileTool enables the file-related tools: read_file, write_file, edit_file,
	// list_directory, glob, and add_artifact. Default: false.
	EnableFileTool bool

	// EnableTodoTool enables the todo management tools: add_todo, update_todo, list_todos,
	// delete_todo. Default: false.
	EnableTodoTool bool
}

BuiltinToolsOption configures which built-in tools are registered.

type CommandContext added in v0.1.0

type CommandContext = command.Context

type CommandResult added in v0.1.0

type CommandResult = command.Result

type ContentModerationFunc added in v0.1.1

type ContentModerationFunc func(content string, contentType string) (intendedOutput string, ok bool)

ContentModerationFunc is called to screen content before or after agent execution. contentType is either "INPUT" (user input, before run) or "OUTPUT" (agent response, after run). Return ok=true to allow the content, or ok=false with an intended output string to block it; the intended output is returned to the caller as the agent's response instead of running further.

type DeleteTodoArgs

type DeleteTodoArgs struct {
	IDs []string `json:"ids"`
}

type DirBackedFileStore added in v0.1.0

type DirBackedFileStore interface {
	FileStore
	// RootDir returns the real directory backing this store, creating it if needed.
	RootDir() (string, error)
}

DirBackedFileStore is implemented by FileStore backends that expose a real on-disk directory whose relative paths mirror logical file paths, enabling tools (like the bash tool) to operate on the same files via a real filesystem.

type EditFileArgs

type EditFileArgs struct {
	Path       string `json:"path"`
	OldString  string `json:"old_string"`
	NewString  string `json:"new_string"`
	ReplaceAll bool   `json:"replace_all,omitempty"`
}

type FileInfo

type FileInfo struct {
	Path       string    `json:"path"`
	IsDir      bool      `json:"is_dir"`
	Size       int64     `json:"size"`
	ModifiedAt time.Time `json:"modified_at"`
}

FileInfo represents file metadata.

type FileStore

type FileStore interface {
	// ReadFile reads a file from the backend.
	ReadFile(ctx context.Context, path string) ([]byte, error)

	// WriteFile writes content to a file in the backend.
	WriteFile(ctx context.Context, path string, content []byte) error

	// ListDirectory lists files and directories in a path.
	ListDirectory(ctx context.Context, path string) ([]FileInfo, error)

	// FileExists checks if a file exists.
	FileExists(ctx context.Context, path string) (bool, error)

	// DeleteFile deletes a file.
	DeleteFile(ctx context.Context, path string) error
}

FileStore defines the interface for file operations. This abstraction allows different storage backends (filesystem, in-memory, etc.)

type GlobArgs

type GlobArgs struct {
	Pattern string `json:"pattern"`
}

type HitlState added in v0.1.0

type HitlState struct {
	Messages            []*schema.Message
	CompactionSummary   string
	OutputCheckAttempts int
	InterruptReason     string
}

HitlState holds the persisted agent state at the point of interruption. Saved by the agent when interrupted; loaded by Resume to continue execution.

type HitlStore added in v0.1.0

type HitlStore interface {
	// Save persists the HITL state for the given session.
	Save(ctx context.Context, sessionId string, state HitlState) error
	// Load retrieves the HITL state for the given session. existed=false if not found.
	Load(ctx context.Context, sessionId string) (state HitlState, existed bool, err error)
	// Delete removes the HITL state for the given session.
	Delete(ctx context.Context, sessionId string) error
}

HitlStore persists and retrieves HITL state between an interrupt and a resume. Keyed by SessionId. Implementations must be safe for concurrent use.

func NewMemHitlStore added in v0.1.0

func NewMemHitlStore() HitlStore

NewMemHitlStore returns a simple in-memory HitlStore suitable for testing and single-process use. State is lost when the process exits.

func NewRedisHitlStore added in v0.1.0

func NewRedisHitlStore(opts ...RedisHitlStoreOption) HitlStore

NewRedisHitlStore returns a HitlStore backed by Redis. Requires miso Redis middleware to be bootstrapped before use.

type ListDirectoryArgs

type ListDirectoryArgs struct {
	Path string `json:"path"`
}

type MetadataStore added in v0.0.17

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

MetadataStore is a concurrency-safe key-value store for sharing arbitrary metadata between tools and the invoker across a single agent execution.

Tools write metadata via AgentContext.Metadata during execution; the invoker reads the final snapshot from TaskOutput.Metadata after Execute returns.

func NewMetadataStore added in v0.0.17

func NewMetadataStore() *MetadataStore

NewMetadataStore creates a new MetadataStore.

func (*MetadataStore) All added in v0.0.17

func (m *MetadataStore) All() map[string]any

All returns a shallow copy of all key-value pairs.

func (*MetadataStore) Delete added in v0.0.17

func (m *MetadataStore) Delete(key string)

Delete removes the entry for the given key. No-op if the key does not exist.

func (*MetadataStore) Get added in v0.0.17

func (m *MetadataStore) Get(key string) (any, bool)

Get retrieves the value for the given key. Returns the value and true if found, zero value and false otherwise.

func (*MetadataStore) RunWithLock added in v0.0.26

func (m *MetadataStore) RunWithLock(fn func(m MetadataView))

RunWithLock acquires the write lock and calls fn with a lock-free MetadataView. Use this when multiple Get/Set/Delete operations must execute atomically.

func (*MetadataStore) Set added in v0.0.17

func (m *MetadataStore) Set(key string, value any)

Set stores a value under the given key, overwriting any existing value.

type MetadataView added in v0.0.26

type MetadataView interface {
	Set(key string, value any)
	Get(key string) (any, bool)
	Delete(key string)
}

MetadataView provides lock-free Get, Set, and Delete access to a MetadataStore. It is only valid for the duration of a RunWithLock callback.

type Middleware added in v0.0.25

type Middleware interface {
	// Name returns a unique identifier for this middleware.
	// Used as the key for per-middleware private state storage.
	Name() string

	// BeforeAgent is called once at the start of Agent.Execute(),
	// before the graph begins running. Returning a non-nil error aborts execution.
	BeforeAgent(ctx context.Context, agentCtx AgentContext) error

	// WrapModelCall is called on every LLM invocation in the loop.
	// Use it to inject prompt fragments, filter messages, or observe the model response.
	WrapModelCall(ctx context.Context, req *ModelCallRequest, next ModelCallHandler) (*ModelCallResponse, error)

	// WrapToolCall is called for every tool execution.
	// Use it to intercept results, enforce permissions, or log tool calls.
	WrapToolCall(ctx context.Context, req *ToolCallRequest, next ToolCallHandler) (*ToolCallResponse, error)

	// AfterAgent is called once after Agent.Execute() finishes (success or error).
	// Errors from AfterAgent are logged but do not suppress the result.
	AfterAgent(ctx context.Context, agentCtx AgentContext, res *TaskOutput, err error) error

	// Tools returns additional tools this middleware contributes to the agent.
	// Called once at NewAgent() time; tools are merged into the shared ToolRegistry.
	Tools() []Tool

	// SystemPromptFragment returns a string to append to the system prompt.
	// Called once per Execute() during prompt assembly, after the user's custom
	// prompt but before the base ReAct prompt. Return empty string to contribute nothing.
	SystemPromptFragment(ctx context.Context) string
}

Middleware is the core extension point for the agent loop. All methods have default no-op implementations via BaseMiddleware — embed it and override only what you need.

func BuildPreloadedSkills

func BuildPreloadedSkills(efs embed.FS, skillNames ...string) Middleware

BuildPreloadedSkills builds a skills Middleware from an embedded filesystem. The efs root must contain skill directories directly (each with a SKILL.md file). If skillNames are provided, only skills with matching directory names are included; if no skillNames are given, all top-level skill directories are included. The Middleware writes skill files into the agent's store during BeforeAgent so they are discoverable from the /skills/ directory on each execution.

Example:

//go:embed all:*
var skillsFS embed.FS

// Load all skills
agent, _ := agentloop.NewAgent(agentloop.AgentConfig{
    Middleware: []agentloop.Middleware{agentloop.BuildPreloadedSkills(skillsFS)},
})

// Load only specific skills
agent, _ := agentloop.NewAgent(agentloop.AgentConfig{
    Middleware: []agentloop.Middleware{agentloop.BuildPreloadedSkills(skillsFS, "humanizer", "web-research")},
})

type ModelCallHandler added in v0.0.25

type ModelCallHandler func(ctx context.Context, req *ModelCallRequest) (*ModelCallResponse, error)

ModelCallHandler is the next function in the WrapModelCall chain.

type ModelCallRequest added in v0.0.25

type ModelCallRequest struct {
	Messages []*schema.Message // Full message history sent to the model
	Task     string            // The original user task for this execution
}

ModelCallRequest is the input to WrapModelCall.

type ModelCallResponse added in v0.0.25

type ModelCallResponse struct {
	Message *schema.Message // The assistant reply
}

ModelCallResponse is the output of WrapModelCall.

type OutputCheckFunc added in v0.0.27

type OutputCheckFunc func(ctx context.Context, agentCtx AgentContext, attempt int, output string) (hint string, ok bool, err error)

OutputCheckFunc is a callback invoked on each final assistant response before the agent accepts it as the output.

agentCtx provides access to the current execution context (session ID, user input, file store, todos, artifacts, metadata), enabling checks that inspect or update agent state.

attempt is the 1-based invocation count for the current execution, so the callback can apply different logic on the first check versus subsequent retries (e.g. give up after N attempts).

Return values:

  • ok=true: output is accepted; agent proceeds to final_output.
  • ok=false: output is rejected; hint is inserted as a user message and the agent retries.
  • err!=nil: unexpected failure (e.g. network error); the agent aborts immediately.

OutputCheckFunc may be used for any per-response validation: output format compliance, quality assessment, security screening, and so on.

func FinalResponseTagOutputCheck added in v0.0.27

func FinalResponseTagOutputCheck(maxAttempts int) OutputCheckFunc

FinalResponseTagOutputCheck returns an OutputCheckFunc that rejects assistant responses not wrapped in <final_response>...</final_response> tags.

maxAttempts caps how many times the check will reject a response. Once attempt exceeds maxAttempts the check passes unconditionally, accepting whatever the model produced.

Example:

agent, _ := agentloop.NewAgent(agentloop.AgentConfig{
    OutputCheck: agentloop.FinalResponseTagOutputCheck(2),
})

func JsonOutputCheck added in v0.0.28

func JsonOutputCheck[T any](maxAttempts int) OutputCheckFunc

JsonOutputCheck returns an OutputCheckFunc that rejects assistant responses that cannot be parsed as valid JSON of type T (after stripping any <think>...</think> block).

maxAttempts caps how many times the check will reject a response. Once attempt exceeds maxAttempts the check passes unconditionally, accepting whatever the model produced.

Example:

agent, _ := agentloop.NewAgent(agentloop.AgentConfig{
    OutputCheck: agentloop.JsonOutputCheck[ClassificationOutput](2),
})

type PromptBuilder

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

PromptBuilder builds the system prompt for the agent.

func NewPromptBuilder

func NewPromptBuilder() *PromptBuilder

NewPromptBuilder creates a new prompt builder.

func (*PromptBuilder) Build

func (pb *PromptBuilder) Build(ctx context.Context) (*schema.Message, error)

Build builds the system prompt.

func (*PromptBuilder) WithCurrentTime

func (pb *PromptBuilder) WithCurrentTime(time string) *PromptBuilder

WithCurrentTime sets the current time.

func (*PromptBuilder) WithFileOps added in v0.0.25

func (pb *PromptBuilder) WithFileOps(enabled bool) *PromptBuilder

WithFileOps enables or disables the file operations prompt section. Enable this when file tools (read_file, write_file, etc.) are available to the agent.

func (*PromptBuilder) WithLanguage

func (pb *PromptBuilder) WithLanguage(language string) *PromptBuilder

WithLanguage sets the language for the agent.

func (*PromptBuilder) WithMiddlewareFragments added in v0.0.25

func (pb *PromptBuilder) WithMiddlewareFragments(fragments []string) *PromptBuilder

WithMiddlewareFragments appends middleware system prompt fragments. Fragments are injected after the custom prompt and before the base ReAct prompt.

func (*PromptBuilder) WithSkills

func (pb *PromptBuilder) WithSkills(skills *Skills) *PromptBuilder

WithSkills sets the skills middleware.

func (*PromptBuilder) WithTaskPrompt

func (pb *PromptBuilder) WithTaskPrompt(prompt string) *PromptBuilder

WithTaskPrompt sets a task prompt that provides task-specific guidance.

type ReadFileArgs

type ReadFileArgs struct {
	Path   string `json:"path"`
	Offset int    `json:"offset,omitempty"`
	Limit  int    `json:"limit,omitempty"`
}

type RedisHitlStoreOption added in v0.1.0

type RedisHitlStoreOption func(*redisHitlStore)

RedisHitlStoreOption configures a RedisHitlStore.

func WithRedisHitlKeyPattern added in v0.1.0

func WithRedisHitlKeyPattern(pat string) RedisHitlStoreOption

WithRedisHitlKeyPattern overrides the Redis key pattern. The pattern must contain one %v placeholder for the session ID. Default: "miso-agent:hitl:%v".

func WithRedisHitlTTL added in v0.1.0

func WithRedisHitlTTL(ttl time.Duration) RedisHitlStoreOption

WithRedisHitlTTL sets an expiry on persisted HITL state. Use 0 (the default) for no expiry.

type SelfInvokeTool

type SelfInvokeTool interface {
	ExecuteJson(ctx context.Context, jsonArg string) (string, error)
}

type SessionAware

type SessionAware interface {
	// OnSessionStart is called when an agent session begins, before any file operations.
	// Implementations should perform any initialisation here (e.g. creating a tmp directory).
	OnSessionStart(rail flow.Rail) error

	// OnSessionEnd is called when an agent session ends.
	// Implementations should release resources here (e.g. removing the tmp directory).
	OnSessionEnd(rail flow.Rail) error
}

SessionAware is implemented by FileStore backends that need lifecycle management tied to an agent session.

type Skill

type Skill struct {
	Metadata SkillMetadata
	Path     string
	Content  string // The markdown content (excluding YAML frontmatter)
}

Skill represents a loaded skill with its metadata and content.

func LoadSkill

func LoadSkill(path string, content []byte) (*Skill, error)

LoadSkill loads a skill from markdown content with YAML frontmatter. Format: --- name: skill-name description: skill description --- # Skill Content

func (*Skill) FormatForPrompt

func (s *Skill) FormatForPrompt() string

FormatForPrompt formats the skill for injection into the system prompt.

func (*Skill) FormatMetadataOnly

func (s *Skill) FormatMetadataOnly() string

FormatMetadataOnly formats only the skill metadata for progressive disclosure. This is used in the system prompt to show available skills without loading full content.

type SkillLoader

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

SkillLoader loads skills from a backend.

func NewSkillLoader

func NewSkillLoader(backend FileStore) *SkillLoader

NewSkillLoader creates a new skill loader.

func (*SkillLoader) LoadFromSource

func (l *SkillLoader) LoadFromSource(ctx context.Context, source string) (SkillsMap, error)

LoadFromSource loads skills from a single source directory. source may be either:

  • A parent directory containing skill subdirectories, each with a SKILL.md file.
  • A skill directory itself that directly contains a SKILL.md file.

func (*SkillLoader) LoadFromSources

func (l *SkillLoader) LoadFromSources(ctx context.Context, sources []string) (SkillsMap, error)

LoadFromSources loads skills from multiple sources. Sources are paths to skill directories (e.g., "/skills/user/", "/skills/project/"). Each source directory should contain skill subdirectories with SKILL.md files. Later sources override earlier sources for skills with the same name.

func (*SkillLoader) LoadSkillFile

func (l *SkillLoader) LoadSkillFile(ctx context.Context, path string) (*Skill, error)

LoadSkillFile loads a single skill from a SKILL.md file.

type SkillMetadata

type SkillMetadata struct {
	Name         string   `yaml:"name"`
	Description  string   `yaml:"description"`
	License      string   `yaml:"license,omitempty"`
	Compatible   string   `yaml:"compatibility,omitempty"`
	Metadata     string   `yaml:"metadata,omitempty"`
	AllowedTools []string `yaml:"allowed_tools,omitempty"`
}

SkillMetadata represents the metadata of a skill from YAML frontmatter.

type Skills

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

Skills injects loaded skills into the system prompt.

func NewSkills

func NewSkills(backend FileStore) *Skills

NewSkills creates a new skills manager.

func (*Skills) GetSkills

func (s *Skills) GetSkills() SkillsMap

GetSkills returns the loaded skills map.

func (*Skills) InjectMetadata

func (s *Skills) InjectMetadata(basePrompt string) string

InjectMetadata injects only skill metadata for progressive disclosure. The LLM is instructed to read full skill content on-demand using tools.

func (*Skills) Load

func (s *Skills) Load(ctx context.Context, sources []string) error

Load loads skills from the configured sources.

type SkillsMap

type SkillsMap map[string]*Skill

SkillsMap is a collection of skills keyed by name.

func (SkillsMap) Add

func (sm SkillsMap) Add(skill *Skill)

Add adds a skill to the map, overwriting if it exists.

func (SkillsMap) FormatMetadata

func (sm SkillsMap) FormatMetadata() string

FormatMetadata formats all skills with only metadata for progressive disclosure.

func (SkillsMap) Get

func (sm SkillsMap) Get(name string) (*Skill, bool)

Get retrieves a skill by name.

func (SkillsMap) List

func (sm SkillsMap) List() []*Skill

List returns all skills in the map.

type TaskOutput

type TaskOutput struct {
	Response   string         // Main response (research report)
	Artifacts  []Artifact     // Artifacts collected during execution
	Metadata   map[string]any // Snapshot of MetadataStore at end of execution
	TokenUsage TokenUsage     // Aggregate token usage across all LLM calls
	TraceLogs  []TraceEntry   // Per-node execution trace; populated when AgentConfig.EnableTrace is true, nil otherwise. Populated even when execution returns an error. ChatModel entries include the full message history per call, so size grows with each ReAct cycle.

	// Interrupted is true when the agent loop was paused for human input via HITL.
	// Use Agent.Resume to continue the session.
	Interrupted bool

	// InterruptReason is the human-readable reason for the interrupt provided by the tool.
	// Empty when Interrupted is false.
	InterruptReason string
}

TaskOutput represents the output from an agent execution

type TmpFileStore

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

TmpFileStore is a tmp-file-backed FileStore implementation. Each session gets its own tmp directory; all files written during the session are stored as individual tmp files inside that directory. The tmp directory is created lazily on the first WriteFile call. Call OnSessionEnd when the session is done to clean up.

TmpFileStore expects paths to already be normalized (forward slashes, no trailing slash) and free of traversal segments ("..") — it does not normalize or validate paths itself. Callers should go through [newValidatingFileStore] (applied automatically by Agent.Execute), which handles both centrally for any FileStore.

func NewTmpFileStore

func NewTmpFileStore() *TmpFileStore

NewTmpFileStore creates a new TmpFileStore.

func (*TmpFileStore) DeleteFile

func (b *TmpFileStore) DeleteFile(ctx context.Context, path string) error

DeleteFile removes a file entry and its underlying tmp file.

func (*TmpFileStore) FileExists

func (b *TmpFileStore) FileExists(ctx context.Context, path string) (bool, error)

FileExists checks whether a file or directory exists.

func (*TmpFileStore) ListDirectory

func (b *TmpFileStore) ListDirectory(ctx context.Context, path string) ([]FileInfo, error)

ListDirectory lists direct children of the given path.

func (*TmpFileStore) OnSessionEnd

func (b *TmpFileStore) OnSessionEnd(rail flow.Rail) error

OnSessionEnd removes the session tmp directory and all files inside it.

func (*TmpFileStore) OnSessionStart

func (b *TmpFileStore) OnSessionStart(rail flow.Rail) error

OnSessionStart is a no-op for TmpFileStore. The tmp directory is created lazily on the first WriteFile call.

func (*TmpFileStore) ReadFile

func (b *TmpFileStore) ReadFile(ctx context.Context, path string) ([]byte, error)

ReadFile reads a file from the tmp-file-backed store.

func (*TmpFileStore) RootDir added in v0.1.0

func (b *TmpFileStore) RootDir() (string, error)

RootDir returns the real on-disk directory backing this store, creating it if it doesn't exist yet. Files inside this directory mirror their logical paths.

func (*TmpFileStore) WriteFile

func (b *TmpFileStore) WriteFile(ctx context.Context, path string, content []byte) error

WriteFile writes content to a new tmp file inside the session directory. The session tmp directory is created lazily on the first call if OnSessionStart has not been called explicitly.

type TodoItem

type TodoItem struct {
	ID          string `json:"id"`
	Task        string `json:"task"`
	Status      string `json:"status"` // "pending", "completed"
	Description string `json:"description,omitempty"`
}

TodoItem represents a task in the todo list.

type TodoItemInput

type TodoItemInput struct {
	Task        string `json:"task"`
	Description string `json:"description,omitempty"`
}

type TodoManager

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

TodoManager manages the todo list for the agent.

func NewTodoManager

func NewTodoManager() *TodoManager

NewTodoManager creates a new todo manager.

func (*TodoManager) AddTodo

func (tm *TodoManager) AddTodo(task, description string) (string, error)

AddTodo adds a new todo item.

func (*TodoManager) AddTodos

func (tm *TodoManager) AddTodos(todos []TodoItem) ([]string, error)

AddTodos adds multiple todo items atomically.

func (*TodoManager) ClearCompleted

func (tm *TodoManager) ClearCompleted()

ClearCompleted removes all completed todos.

func (*TodoManager) DeleteTodo

func (tm *TodoManager) DeleteTodo(id string) error

DeleteTodo deletes a todo item.

func (*TodoManager) DeleteTodos

func (tm *TodoManager) DeleteTodos(ids []string) error

DeleteTodos deletes multiple todo items atomically.

func (*TodoManager) Format

func (tm *TodoManager) Format() string

Format returns a formatted string representation of all todos.

func (*TodoManager) FromState

func (tm *TodoManager) FromState(todos []TodoItem)

FromState restores the todos from state.

func (*TodoManager) GetTodo

func (tm *TodoManager) GetTodo(id string) (TodoItem, bool)

GetTodo returns a specific todo item.

func (*TodoManager) ListTodos

func (tm *TodoManager) ListTodos() []TodoItem

ListTodos returns all todo items.

func (*TodoManager) ToState

func (tm *TodoManager) ToState() []TodoItem

ToState returns the todos as a slice for state persistence.

func (*TodoManager) UpdateTodoStatus

func (tm *TodoManager) UpdateTodoStatus(id, status string) error

UpdateTodoStatus updates the status of a todo item.

type TokenUsage added in v0.0.25

type TokenUsage struct {
	PromptTokens     int // Total input tokens consumed across all LLM calls
	CompletionTokens int // Total output tokens generated across all LLM calls
	CachedTokens     int // Total prompt tokens served from cache across all LLM calls
}

TokenUsage tracks total token consumption across all LLM calls in a single agent execution.

type Tokenizer

type Tokenizer struct{}

Tokenizer counts tokens using a simple len/4 approximation.

func NewTokenizer

func NewTokenizer() Tokenizer

NewTokenizer creates a new Tokenizer.

func (Tokenizer) CountMessageTokens

func (t Tokenizer) CountMessageTokens(msg *schema.Message) int

CountMessageTokens returns the token count for a message. This follows OpenAI's token counting methodology for chat messages. See: https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb

func (Tokenizer) CountMessagesTokens

func (t Tokenizer) CountMessagesTokens(messages []*schema.Message) int

CountMessagesTokens returns the total token count for a slice of messages. Includes the 3 token priming for assistant reply.

func (Tokenizer) CountTokens

func (t Tokenizer) CountTokens(text string) int

CountTokens returns an approximate token count for the given text. Uses the same heuristic as opencode: 4 characters per token on average. This is model-agnostic and avoids model-specific tokenizer dependencies. Accuracy varies by content (~4 chars/token for English prose, less accurate for code or non-Latin scripts), but is sufficient for context window budgeting.

type Tool

type Tool interface {
	// Name returns the name of the tool.
	Name() string

	// Description returns a description of the tool.
	Description() string

	// Parameters returns the JSON schema for the tool parameters.
	Parameters() map[string]*schema.ParameterInfo

	// Execute executes the tool with the given arguments.
	Execute(ctx context.Context, args map[string]interface{}) (string, error)
}

Tool represents a tool that can be used by the agent.

func NewAutoTypedCtxAwareToolFunc added in v0.0.25

func NewAutoTypedCtxAwareToolFunc[T any](
	name string,
	description string,
	execute func(ctx context.Context, agentCtx AgentContext, args T) (string, error),
) Tool

NewAutoTypedCtxAwareToolFunc creates a tool whose parameter schema is auto-deduced from T via JSON-schema reflection. No manual ParameterInfo map is required.

Supported struct tags:

  • json:"name[,omitempty]" — field name; omitempty marks the field as optional
  • desc:"..." — field description (custom shorthand)
  • jsonschema:"required,enum=a,enum=b,minimum=0,..." — standard JSON schema keywords

Example:

type ReadFileArgs struct {
    Path   string `json:"path"             desc:"Absolute path to the file"`
    Offset int    `json:"offset,omitempty" desc:"Line to start from"`
    Limit  int    `json:"limit,omitempty"  desc:"Max lines to read"`
}

tool, err := NewAutoTypedCtxAwareToolFunc(
    "read_file",
    "Read file content",
    func(ctx context.Context, agentCtx AgentContext, args ReadFileArgs) (string, error) {
        content, err := agentCtx.Store.ReadFile(ctx, args.Path)
        return string(content), err
    },
)

func NewBashTool added in v0.1.0

func NewBashTool(opts ...BashToolOption) Tool

NewBashTool creates the built-in "bash" tool, which executes a bash script inside a sandboxed environment (github.com/mark3labs/go-bash). By default the sandbox has no network access and a 30 second execution timeout; use WithBashTimeout, WithBashNetwork, WithBashCommand, and WithBashOutputSanitize to change these defaults.

func NewCtxAwareToolFunc

func NewCtxAwareToolFunc(
	name string,
	description string,
	parameters map[string]*schema.ParameterInfo,
	execute func(ctx context.Context, agentCtx AgentContext, args map[string]interface{}) (string, error),
) Tool

NewCtxAwareToolFunc creates a tool that needs access to AgentContext (Store and Todos). The AgentContext is automatically injected via context by the agent loop.

Parameters should be built using the typed helper functions:

  • StringParam(desc, required) - for string parameters
  • IntParam(desc, required) - for integer parameters
  • NumberParam(desc, required) - for numeric parameters
  • BoolParam(desc, required) - for boolean parameters
  • ArrayParam(desc, elemInfo, required) - for array parameters
  • ObjectParam(desc, subParams, required) - for object parameters

Example:

NewCtxAwareToolFunc(
    "read_file",
    "Read file content",
    map[string]*schema.ParameterInfo{
        "path": StringParam("The absolute path to the file to read", true),
    },
    func(ctx context.Context, agentCtx AgentContext, args map[string]interface{}) (string, error) {
        path := cast.ToString(args["path"])
        content, err := agentCtx.Store.ReadFile(ctx, path)
        return string(content), err
    },
)

func NewInterruptForHumanTool added in v0.1.0

func NewInterruptForHumanTool() Tool

NewInterruptForHumanTool creates the built-in interrupt_for_human tool. The LLM calls this tool to pause execution and wait for human input.

func NewSubAgentTool added in v0.0.15

func NewSubAgentTool(specs ...*AgentSpec) Tool

NewSubAgentTool creates a tool named "task" that allows the agent to delegate work to one of the provided sub-agents. Each sub-agent is identified by AgentSpec.Name and described to the LLM via AgentSpec.Capabilities.

The compiled *Agent for each spec is lazily initialized on first use and reused across subsequent calls.

Note: sub-agents created via this tool are not permitted to create further sub-agents. Callers should not include a "task" tool in sub-agent configs.

func NewThinkTool

func NewThinkTool() Tool

NewThinkTool creates a think tool for strategic reflection on research progress and decision-making. This tool is not included in the built-in tools by default, but can be added by users if needed. Use this tool after each search to analyze results and plan next steps systematically. This creates a deliberate pause in the research workflow for quality decision-making.

When to use: - After receiving search results: What key information did I find? - Before deciding next steps: Do I have enough to answer comprehensively? - When assessing research gaps: What specific information am I still missing? - Before concluding research: Can I provide a complete answer now?

Reflection should address: 1. Analysis of current findings - What concrete information have I gathered? 2. Gap assessment - What crucial information is still missing? 3. Quality evaluation - Do I have sufficient evidence/examples for a good answer? 4. Strategic decision - Should I continue searching or provide my answer?

Example:

agent := agentloop.NewAgent(agentloop.AgentConfig{
    ModelName: "qwen3-max",
    ApiKey:    apiKey,
    Tools:     []agentloop.Tool{agentloop.NewThinkTool()},
})

func NewToolFunc

func NewToolFunc(
	name string,
	description string,
	parameters map[string]*schema.ParameterInfo,
	execute func(ctx context.Context, args map[string]interface{}) (string, error),
) Tool

NewToolFunc creates a new function-based tool.

Parameters should be built using the typed helper functions:

  • StringParam(desc, required) - for string parameters
  • IntParam(desc, required) - for integer parameters
  • NumberParam(desc, required) - for numeric parameters
  • BoolParam(desc, required) - for boolean parameters
  • ArrayParam(desc, elemInfo, required) - for array parameters
  • ObjectParam(desc, subParams, required) - for object parameters

Example:

NewToolFunc(
    "finish_tool",
    "Call this tool when you have completed the task",
    map[string]*schema.ParameterInfo{
        "response": StringParam("Your final answer to the task", false),
    },
    func(ctx context.Context, args map[string]interface{}) (string, error) {
        response := cast.ToString(args["response"])
        return response, nil
    },
)

func NewTransformCsvLuaTool added in v0.0.15

func NewTransformCsvLuaTool() Tool

func NewTypedCtxAwareToolFunc

func NewTypedCtxAwareToolFunc[T any](
	name string,
	description string,
	parameters map[string]*schema.ParameterInfo,
	execute func(ctx context.Context, agentCtx AgentContext, args T) (string, error),
) Tool

NewTypedCtxAwareToolFunc creates a tool that accepts typed arguments and has AgentContext access. The execute function receives a struct of type T instead of a map.

Parameters should be built using the typed helper functions:

  • StringParam(desc, required) - for string parameters
  • IntParam(desc, required) - for integer parameters
  • NumberParam(desc, required) - for numeric parameters
  • BoolParam(desc, required) - for boolean parameters
  • ArrayParam(desc, elemInfo, required) - for array parameters
  • ObjectParam(desc, subParams, required) - for object parameters

Example:

type ReadFileArgs struct {
    Path   string `json:"path"`
    Offset int    `json:"offset"`
    Limit  int    `json:"limit"`
}

NewTypedCtxAwareToolFunc(
    "read_file",
    "Read file content",
    map[string]*schema.ParameterInfo{
        "path":   StringParam("The absolute path to the file to read", true),
        "offset": IntParam("Optional: Line number to start reading from", false),
        "limit":  IntParam("Optional: Maximum number of lines to read", false),
    },
    func(ctx context.Context, agentCtx AgentContext, args ReadFileArgs) (string, error) {
        // args is already typed as ReadFileArgs
        // No need for cast.ToString or cast.ToInt
        content, err := agentCtx.Store.ReadFile(ctx, args.Path)
        return string(content), err
    },
)

func NewTypedToolFunc

func NewTypedToolFunc[T any](
	name string,
	description string,
	parameters map[string]*schema.ParameterInfo,
	execute func(ctx context.Context, args T) (string, error),
) Tool

NewTypedToolFunc creates a tool that accepts typed arguments via JSON deserialization. The execute function receives a struct of type T instead of a map.

Parameters should be built using the typed helper functions:

  • StringParam(desc, required) - for string parameters
  • IntParam(desc, required) - for integer parameters
  • NumberParam(desc, required) - for numeric parameters
  • BoolParam(desc, required) - for boolean parameters
  • ArrayParam(desc, elemInfo, required) - for array parameters
  • ObjectParam(desc, subParams, required) - for object parameters

Example:

type ReadFileArgs struct {
    Path   string `json:"path"`
    Offset int    `json:"offset"`
    Limit  int    `json:"limit"`
}

NewTypedToolFunc(
    "read_file",
    "Read file content",
    map[string]*schema.ParameterInfo{
        "path":   StringParam("The absolute path to the file to read", true),
        "offset": IntParam("Optional: Line number to start reading from", false),
        "limit":  IntParam("Optional: Maximum number of lines to read", false),
    },
    func(ctx context.Context, args ReadFileArgs) (string, error) {
        // args is already typed as ReadFileArgs
        // No need for cast.ToString or cast.ToInt
        return "file content", nil
    },
)

type ToolCallHandler added in v0.0.25

type ToolCallHandler func(ctx context.Context, req *ToolCallRequest) (*ToolCallResponse, error)

ToolCallHandler is the next function in the WrapToolCall chain.

type ToolCallRequest added in v0.0.25

type ToolCallRequest struct {
	Name     string                 // Tool name
	Args     map[string]interface{} // Parsed arguments
	RawInput string                 // Original JSON string from the LLM
}

ToolCallRequest is the input to WrapToolCall.

type ToolCallResponse added in v0.0.25

type ToolCallResponse struct {
	Result  string // String result returned to the LLM
	IsError bool   // When true, the result is an error message (LLM can self-correct)
}

ToolCallResponse is the output of WrapToolCall.

type ToolEvent added in v0.0.18

type ToolEvent struct {
	Kind ToolEventKind
	Name string // tool name
	Args string // raw JSON args string
}

ToolEvent is emitted during agent execution for each tool invocation. If ToolEventCallback is set in AgentConfig, it is called synchronously for each event.

type ToolEventKind added in v0.0.18

type ToolEventKind string

ToolEventKind identifies the kind of tool event emitted during agent execution.

const (
	// ToolEventKindCall fires when the LLM invokes a tool, before execution begins.
	ToolEventKindCall ToolEventKind = "call"
	// ToolEventKindResult fires after a tool finishes execution, with its result.
	ToolEventKindResult ToolEventKind = "result"
)

type ToolFunc

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

ToolFunc is a function-based tool implementation.

func (*ToolFunc) Description

func (t *ToolFunc) Description() string

Description returns the description of the tool.

func (*ToolFunc) Execute

func (t *ToolFunc) Execute(ctx context.Context, args map[string]interface{}) (string, error)

Execute executes the tool with the given arguments.

func (*ToolFunc) Name

func (t *ToolFunc) Name() string

Name returns the name of the tool.

func (*ToolFunc) Parameters

func (t *ToolFunc) Parameters() map[string]*schema.ParameterInfo

Parameters returns the JSON schema for the tool parameters.

type ToolRegistry

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

Registry manages tool registration and retrieval.

func BuiltinTools

func BuiltinTools(ops ...func(o *BuiltinToolsOption)) *ToolRegistry

BuiltinTools returns the built-in tools configured by the provided options. By default (no options), no tools are registered; use WithEnableFileTool or WithEnableTodoTool to opt in.

func NewToolRegistry

func NewToolRegistry() *ToolRegistry

NewRegistry creates a new tool registry.

func (*ToolRegistry) Get

func (r *ToolRegistry) Get(name string) (Tool, bool)

Get retrieves a tool by name.

func (*ToolRegistry) List

func (r *ToolRegistry) List() []Tool

List returns all registered tools.

func (*ToolRegistry) Merge

func (r *ToolRegistry) Merge(other *ToolRegistry)

Merge merges another registry into this one.

func (*ToolRegistry) Register

func (r *ToolRegistry) Register(tool Tool)

Register registers a tool in the registry.

func (*ToolRegistry) ToEinoTools

func (r *ToolRegistry) ToEinoTools() []tool.BaseTool

ToEinoTools converts the registry to Eino tool instances.

func (*ToolRegistry) ToEinoToolsWithChain added in v0.0.25

func (r *ToolRegistry) ToEinoToolsWithChain(middlewares []Middleware) []tool.BaseTool

ToEinoToolsWithChain converts the registry to Eino tool instances with a per-tool WrapToolCall middleware chain. When middlewares is empty, equivalent to ToEinoTools.

type TraceEntry added in v0.0.27

type TraceEntry struct {
	Node      string          `json:"node"`
	Component string          `json:"component"`
	Input     json.RawMessage `json:"input,omitempty"`
	Output    json.RawMessage `json:"output,omitempty"`
}

TraceEntry records the input and output of a single node execution in the agent graph.

type TypedCtxAwareToolFunc

type TypedCtxAwareToolFunc[T any] struct {
	// contains filtered or unexported fields
}

TypedCtxAwareToolFunc is a tool that accepts typed arguments and has AgentContext access.

func (*TypedCtxAwareToolFunc[T]) Description

func (t *TypedCtxAwareToolFunc[T]) Description() string

Description returns the description of the tool.

func (*TypedCtxAwareToolFunc[T]) Execute

func (t *TypedCtxAwareToolFunc[T]) Execute(ctx context.Context, args map[string]interface{}) (string, error)

Execute executes the tool with the given arguments (untyped).

func (*TypedCtxAwareToolFunc[T]) ExecuteJson

func (t *TypedCtxAwareToolFunc[T]) ExecuteJson(ctx context.Context, jsonArg string) (string, error)

ExecuteJson executes the tool with JSON arguments.

func (*TypedCtxAwareToolFunc[T]) Name

func (t *TypedCtxAwareToolFunc[T]) Name() string

Name returns the name of the tool.

func (*TypedCtxAwareToolFunc[T]) Parameters

func (t *TypedCtxAwareToolFunc[T]) Parameters() map[string]*schema.ParameterInfo

Parameters returns the JSON schema for the tool parameters.

type TypedToolFunc

type TypedToolFunc[T any] struct {
	// contains filtered or unexported fields
}

TypedToolFunc is a tool that accepts typed arguments via JSON deserialization.

func (*TypedToolFunc[T]) Description

func (t *TypedToolFunc[T]) Description() string

Description returns the description of the tool.

func (*TypedToolFunc[T]) Execute

func (t *TypedToolFunc[T]) Execute(ctx context.Context, args map[string]interface{}) (string, error)

Execute executes the tool with the given arguments (untyped).

func (*TypedToolFunc[T]) ExecuteJson

func (t *TypedToolFunc[T]) ExecuteJson(ctx context.Context, jsonArg string) (string, error)

ExecuteJson executes the tool with JSON arguments.

func (*TypedToolFunc[T]) Name

func (t *TypedToolFunc[T]) Name() string

Name returns the name of the tool.

func (*TypedToolFunc[T]) Parameters

func (t *TypedToolFunc[T]) Parameters() map[string]*schema.ParameterInfo

Parameters returns the JSON schema for the tool parameters.

type UpdateTodoArgs

type UpdateTodoArgs struct {
	ID     string `json:"id,omitempty"`
	Status string `json:"status,omitempty"`
}

type WriteFileArgs

type WriteFileArgs struct {
	Path    string `json:"path"`
	Content string `json:"content"`
}

Jump to

Keyboard shortcuts

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