Help us shape the future of Go! Take the 2026 Go Developer Survey

tools

package
v0.11.1 Latest Latest
Warning

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

Go to latest
Published: Oct 31, 2026 License: MIT Imports: 43 Imported by: 0

Documentation

Overview

Package tools implements the agent's file and shell tools, sandboxed to a root directory.

Index

Constants

View Source
const (
	MaxAskUserQuestion = 2000
	MaxAskUserOption   = 200
	MinAskUserOptions  = 2
	MaxAskUserOptions  = 6
)

ask_user argument limits, in characters.

View Source
const (
	DirRead  = "read"
	DirWrite = "write"
)

Additional directory modes.

View Source
const (
	MemorySearchToolName = "memory_search"
	MemoryListToolName   = "memory_list"
)

Read-only project memory tools, offered with remember (MemoryTools).

View Source
const (
	// DefaultMaxProcesses bounds concurrent background processes when
	// Executor.MaxProcesses is 0.
	DefaultMaxProcesses = 4
	// DefaultProcessBufferBytes caps each background process's retained
	// output when Executor.ProcessBufferBytes is 0.
	DefaultProcessBufferBytes = 1 << 20
)
View Source
const (
	UntrustedWebFetch = "web_fetch"
	UntrustedMCP      = "mcp"
)

Untrusted-content sources a tool result can come from. Project memory (#170) and the untrusted-content lockdown (#171) share this one definition, so a result that keeps memory writes pending is exactly a result that can taint a locked-down run. The names match the untrusted_content.sources values lockdown.SourceWebFetch and lockdown.SourceMCP.

View Source
const (
	DefaultWebFetchMaxBytes       = 2 << 20 // 2 MiB
	DefaultWebFetchTimeoutSeconds = 20
	MaxWebFetchTimeoutSeconds     = 120
	// MaxWebFetchRedirects is how many redirects one fetch follows.
	MaxWebFetchRedirects = 5
)

Web fetch limits and defaults.

View Source
const (
	WebFetchDeniedScheme      = "only http and https URLs are allowed"
	WebFetchDeniedCredentials = "URLs with credentials are not allowed"
	WebFetchDeniedHost        = "host not in web_fetch.allowed_domains"
	WebFetchDeniedNonPublic   = "host resolves to a loopback, link-local or private address"
	WebFetchDeniedRedirects   = "too many redirects"
)

Web fetch denial reasons, recorded as denied_reason.

View Source
const (
	WorkerToolName      = "worker"
	ApplyWorkerToolName = "apply_worker"
)

WorkerToolName runs an implementation subtask in a child agent confined to its own Git worktree; ApplyWorkerToolName applies a worker's commit to the working tree. The agent loop runs both; the executor never does.

View Source
const ApplyPatchToolName = "apply_patch"

ApplyPatchToolName is the opt-in multi-file patch tool.

View Source
const AskUserToolName = "ask_user"

AskUserToolName is the opt-in tool that ends a run with one question for the user. The agent loop handles its calls; the executor never runs them.

View Source
const ContainerLabel = "tinyagent"

ContainerLabel marks containers started by tinyagent.

View Source
const DefaultMaxImageBytes = 5 << 20

DefaultMaxImageBytes caps one image's raw size when max_image_bytes is unset.

View Source
const DefaultToolOutputDir = ".tinyagent/tool-output"

DefaultToolOutputDir is where saved tool output goes, relative to --cwd.

View Source
const DelegateToolName = "delegate"

DelegateToolName is the opt-in tool that hands a task to a read-only subagent with a fresh context.

View Source
const LSPToolName = "lsp"

LSPToolName is the opt-in read-only language-server tool.

View Source
const MaxExtraDirs = 10

MaxExtraDirs caps the number of additional directories one run may use.

View Source
const MaxLSPLocations = 100

MaxLSPLocations caps the locations one lsp call lists.

View Source
const MaxPatchBytes = 1 << 20

MaxPatchBytes caps one apply_patch input.

View Source
const PlanToolName = "update_plan"

PlanToolName is the opt-in plan tool.

View Source
const RememberToolName = "remember"

RememberToolName is the opt-in project memory tool (memory.enabled). It saves short notes about the project for later runs; writes never change the current run's prompt.

View Source
const SandboxHelperArg = "__sandbox_exec"

SandboxHelperArg is argv[1] of the re-executed tinyagent that applies the Linux sandbox and then execs the command. It is not a user-facing flag.

View Source
const UndoDir = ".tinyagent/undo"

UndoDir is where per-session file snapshots live, relative to the working directory. Its contents are local state and must never be committed.

View Source
const UndoToolName = "undo_file"

UndoToolName is the built-in tool that restores a file's session snapshot.

View Source
const ViewImageToolName = "view_image"

ViewImageToolName is the opt-in image tool (--images).

View Source
const WebFetchDeniedLockdown = "host not in untrusted_content.lockdown.web_fetch_allowed_domains after taint"

WebFetchDeniedLockdown is the denied_reason of a hop the untrusted-content lockdown Gate refused.

View Source
const WebFetchToolName = "web_fetch"

WebFetchToolName is the opt-in web_fetch tool.

Variables

View Source
var CoreEnv = []string{"PATH", "HOME", "USER", "LOGNAME", "SHELL", "LANG", "LC_*", "TERM", "TZ", "TMPDIR"}

CoreEnv is the allowlist command_env inherit: core keeps. LC_* is a glob.

View Source
var ProviderEnv = []string{"OPENAI_API_KEY", "ANTHROPIC_API_KEY", "OPENROUTER_API_KEY"}

ProviderEnv are tinyagent's own provider credentials, always withheld by exclude_secrets.

View Source
var SandboxBackends = []string{"auto", "landlock", "bwrap"}

SandboxBackends are the sandbox_backend values. auto prefers Bubblewrap with Landlock stacked inside and falls back to Landlock alone; landlock and bwrap insist on one. On macOS only auto (Seatbelt) applies.

Functions

func ApplyPatch added in v0.5.0

func ApplyPatch(root, input string) (string, error)

ApplyPatch parses input, checks every operation before writing anything, then applies the operations in order. A write failure after the check stops the run and reports which operations were applied; those are not rolled back.

func ApplyPatchPaths added in v0.8.0

func ApplyPatchPaths(input string) []string

ApplyPatchPaths returns the paths (and move destinations) named in an apply_patch input, in patch order, without applying it. A malformed patch yields nil. It is used by the permissions policy to match path rules against an apply_patch call's files.

func ApplyPatchSpec added in v0.5.0

func ApplyPatchSpec() model.ToolSpec

ApplyPatchSpec returns the apply_patch definition.

func ApplyWorkerSpec added in v0.8.0

func ApplyWorkerSpec() model.ToolSpec

ApplyWorkerSpec describes the apply_worker tool.

func AskUserSpec added in v0.5.0

func AskUserSpec() model.ToolSpec

AskUserSpec describes the ask_user tool.

func Bash

func Bash(ctx context.Context, root, command string, timeout time.Duration) (string, error)

Bash runs command in a fresh `bash -c` process in root. On timeout the whole process group is killed so background children do not linger.

func BashStream added in v0.4.0

func BashStream(ctx context.Context, root, command string, timeout time.Duration, live io.Writer) (string, error)

BashStream is Bash that also copies output to live, if non-nil, as it is produced. The returned result is the same as Bash's.

func ContainerRunNetwork added in v0.9.0

func ContainerRunNetwork(runArgs []string) string

ContainerRunNetwork returns the network mode container run arguments set with --network or --net (the last one wins), or "" when they set none.

func DelegateSpec added in v0.5.0

func DelegateSpec() model.ToolSpec

DelegateSpec describes the delegate tool.

func EditFile

func EditFile(root, path, oldStr, newStr string, replaceAll bool) (int, error)

EditFile replaces the single occurrence of oldStr with newStr, or every occurrence if replaceAll is set, and returns the number of replacements.

func ExtraDirsNotice added in v0.5.0

func ExtraDirsNotice(dirs []ExtraDir) string

ExtraDirsNotice is the system prompt section that tells the model which additional directories it may use, or "" when there are none.

func Grep

func Grep(root, pattern, path, include string, ignoreCase, fixedStrings bool) (string, error)

Grep returns lines matching pattern as "file:line: content". Binary and very large files are skipped. A non-empty include glob limits the search to matching files, using the same rules as ListFiles: a glob without "/" matches base names, a glob with "/" matches paths relative to the searched directory. When path is a single file, include is ignored. ignoreCase enables case-insensitive matching of file contents only. fixedStrings treats pattern as literal text instead of a Go regular expression.

func GrepWithContext added in v0.4.0

func GrepWithContext(root, pattern, path, include string, ignoreCase, fixedStrings bool, contextLines int) (string, error)

GrepWithContext returns matches with up to contextLines surrounding lines.

func LSPSpec added in v0.5.0

func LSPSpec() model.ToolSpec

LSPSpec returns the lsp definition.

func ListFiles

func ListFiles(root, path, pattern string) (string, error)

ListFiles lists the entries of a directory, or, with a pattern, walks it recursively and returns matching files. A pattern without "/" matches base names; a pattern with "/" matches paths relative to the listed directory.

func LoadImageFile added in v0.5.0

func LoadImageFile(path string, maxBytes int) (model.Image, error)

LoadImageFile reads a user-chosen image file (an --image attachment). The path is not sandboxed. The type is sniffed from content, and the image's Label is the file's base name, so no absolute path reaches the model.

func MemoryListSpec added in v0.9.0

func MemoryListSpec() model.ToolSpec

MemoryListSpec describes memory_list.

func MemorySearchSpec added in v0.9.0

func MemorySearchSpec() model.ToolSpec

MemorySearchSpec describes memory_search.

func ParseAskUser added in v0.5.0

func ParseAskUser(arguments string) (question string, options []string, reason string)

ParseAskUser validates ask_user arguments. It returns the trimmed question and options, or the reason they are malformed.

func PlanSpec added in v0.5.0

func PlanSpec() model.ToolSpec

PlanSpec returns the update_plan definition.

func ProbeSandbox added in v0.11.0

func ProbeSandbox(backend string, network bool, allowed []string) (string, []string, error)

ProbeSandbox reports the engine NewSandboxBackend would pick, without creating anything, for --check.

func ReadFile

func ReadFile(root, path string, offset, limit int) (string, error)

ReadFile returns a file's contents. A positive offset (1-based start line) or limit (max lines) returns just that range, ending in a "[lines A-B of N]" note when the range isn't the whole file.

func Redacts added in v0.5.0

func Redacts(name string) bool

Redacts reports whether redact_secrets masks name's results: every tool (bash, the process tools, web_fetch, MCP tools) except the built-in file tools.

func RememberSpec added in v0.9.0

func RememberSpec() model.ToolSpec

RememberSpec describes the remember tool with the default entry size.

func RememberSpecFor added in v0.9.0

func RememberSpecFor(max int) model.ToolSpec

RememberSpecFor describes the remember tool for entries of at most max characters (memory.toml max_entry_size).

func ReservedToolNames added in v0.5.0

func ReservedToolNames() []string

ReservedToolNames are the built-in tool names, including opt-in ones, that a command tool may not use.

func Resolve

func Resolve(root, path string) (string, error)

Resolve maps a path relative to root (or absolute inside root) to an absolute path, rejecting anything that escapes root. The check is lexical; symlinks inside root that point outside it are followed.

func ResolveOutputDir added in v0.5.0

func ResolveOutputDir(root, dir string) (string, error)

ResolveOutputDir checks that dir (relative to root, or absolute) is a directory strictly inside root and returns its absolute path. An empty dir means DefaultToolOutputDir.

func RunSandboxHelper added in v0.5.0

func RunSandboxHelper(args []string) int

RunSandboxHelper applies the Landlock policy in args (see wrap) to the current thread and execs the command. It only returns on failure. The helper modes are net-allow, net-deny and net-port=<port> (connect only to that port); net-proxy=<port>:<socket> (see runProxied); and net-probe.

func SetProcessGroup added in v0.5.0

func SetProcessGroup(cmd *exec.Cmd)

SetProcessGroup makes cancelling cmd kill its whole process group, as for bash. On Windows only the process itself is killed.

func SniffImage added in v0.5.0

func SniffImage(data []byte) string

SniffImage returns the MIME type of an accepted image format, decided by content rather than file extension, or "" for anything else.

func Specs

func Specs(readOnly ...bool) []model.ToolSpec

Specs returns the OpenAI tool definitions for all tools.

func StripExtraDirsNotice added in v0.5.0

func StripExtraDirsNotice(system string) string

StripExtraDirsNotice removes an ExtraDirsNotice section from a system prompt, so a prompt can be compared regardless of which directories it listed.

func Truncate added in v0.5.0

func Truncate(s string, max int) string

Truncate caps s at max characters, keeping its head and tail; 0 means unlimited. It is the same cap applied to tool output.

func TruncateWithNotice added in v0.5.0

func TruncateWithNotice(body, notice string, max int) (string, bool)

TruncateWithNotice cuts body so body, a newline, and notice together fit in max bytes, keeping notice whole at the end. It returns ok false when notice itself does not fit; callers then fall back to Truncate.

func UntrustedHistoryCall added in v0.9.0

func UntrustedHistoryCall(name string, externalTools []string) bool

UntrustedHistoryCall reports whether a recorded call to the tool name brought untrusted content into a checkpoint's history: a web_fetch call, or a call to one of the checkpoint's external tools. It is the UntrustedSource rule for a run that only exists as a trajectory.

func ValidDirMode added in v0.5.0

func ValidDirMode(m string) bool

ValidDirMode reports whether m is a supported additional directory mode.

func ValidSandboxBackend added in v0.11.0

func ValidSandboxBackend(b string) bool

ValidSandboxBackend reports whether b is a sandbox_backend value ("" is auto).

func ValidateAccessPattern added in v0.5.0

func ValidateAccessPattern(p string) error

ValidateAccessPattern reports whether p is a supported file_access pattern: non-empty, no "!" negation, and valid glob syntax.

func ViewImage added in v0.5.0

func ViewImage(root, path string, maxBytes int) (string, *model.Image, error)

ViewImage reads an image under root. The text names the path, MIME type, and size, followed by the image's placeholder.

func ViewImageSpec added in v0.5.0

func ViewImageSpec() model.ToolSpec

ViewImageSpec returns the view_image definition.

func WebFetchSpec added in v0.5.0

func WebFetchSpec() model.ToolSpec

WebFetchSpec returns the web_fetch definition.

func WithTaskType added in v0.11.0

func WithTaskType(s model.ToolSpec, types []string) model.ToolSpec

WithTaskType adds the optional task_type argument, one of types, to a delegate or worker spec; with no types it returns s unchanged.

func WorkerSpec added in v0.8.0

func WorkerSpec() model.ToolSpec

WorkerSpec describes the worker tool.

func WriteFile

func WriteFile(root, path, content string) error

Types

type AccessPattern added in v0.8.0

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

AccessPattern is a compiled gitignore-style pattern, in the same syntax as file_access, for matching one slash-separated relative path. It is used by the permissions policy's path matcher.

func CompileAccessPattern added in v0.8.0

func CompileAccessPattern(p string) (*AccessPattern, error)

CompileAccessPattern compiles one gitignore-style pattern for matching a relative path (slash-separated, relative to the working directory).

func (*AccessPattern) Match added in v0.8.0

func (a *AccessPattern) Match(relPath string) bool

Match reports whether relPath matches the pattern. relPath is relative to the working directory, slash-separated; the final segment is treated as a file (not a directory), so directory-only patterns (a trailing "/") do not match it.

type CommandEnv added in v0.5.0

type CommandEnv struct {
	Inherit        string // all, core or none
	ExcludeSecrets bool
	Vars           []string // KEY=VALUE entries given to every command
	Passed         []string // sorted names in Vars
	Withheld       []string // sorted names in tinyagent's environment not in Vars
	Missing        []string // pass entries that matched nothing
}

CommandEnv is the environment computed once per run from a command_env policy. Only names are meant to be shown; Vars holds the values.

func NewCommandEnv added in v0.5.0

func NewCommandEnv(p config.CommandEnv, environ []string) *CommandEnv

NewCommandEnv applies p to environ (typically os.Environ()): the inherit base, then exclude_secrets, exclude, pass and set, in that order.

func (*CommandEnv) Describe added in v0.5.0

func (c *CommandEnv) Describe() string

Describe is the one-line summary printed at startup. It names no values.

type CommandTool added in v0.5.0

type CommandTool struct {
	Name        string
	Description string
	Schema      *outschema.Schema
	Argv        []string // template; placeholders are whole elements
	Timeout     time.Duration
	Dir         string // absolute working directory inside Root
}

CommandTool is a checked command_tools entry: a model-callable tool that runs a fixed argv, filled in with schema-checked arguments, without a shell, in the run's environment.

func NewCommandTools added in v0.5.0

func NewCommandTools(defs []config.CommandTool, root string, bashTimeoutSec int) ([]*CommandTool, error)

NewCommandTools checks the command_tools definitions for a run rooted at root; bashTimeoutSec is the default timeout. Errors name the tool and key.

func (*CommandTool) Expand added in v0.5.0

func (c *CommandTool) Expand(raw string) ([]string, []string)

Expand checks raw arguments against the schema and returns the argv to run, or the validation problems.

func (*CommandTool) Spec added in v0.5.0

func (c *CommandTool) Spec() model.ToolSpec

Spec is the tool definition offered to the model.

type Container added in v0.5.0

type Container struct {
	Runtime string // docker or podman
	Image   string
	ID      string
	Mount   string // host directory mounted at the same path
	// Extra are additional directories mounted at the same paths; read
	// mode ones are mounted read-only.
	Extra []ExtraDir
	// contains filtered or unexported fields
}

Container runs commands with `<runtime> exec` in one container per run, with the workspace bind-mounted at the same path.

func StartContainer added in v0.5.0

func StartContainer(ctx context.Context, rt, image string, runArgs []string, root string, extra []ExtraDir) (*Container, error)

StartContainer checks that runtime is usable and starts a container from image with root mounted at the same path, plus each additional directory in extra at its own path (read-only for read mode). It fails rather than falling back to the host. runArgs are extra `run` arguments, after the defaults.

func (*Container) Close added in v0.5.0

func (c *Container) Close() error

Close stops and removes the container. It is safe on a nil Container.

func (*Container) Command added in v0.5.0

func (c *Container) Command(ctx context.Context, root, command string) *exec.Cmd

func (*Container) Describe added in v0.5.0

func (c *Container) Describe() string

Describe is the one-line summary printed at startup.

func (*Container) Exec added in v0.5.0

func (c *Container) Exec(ctx context.Context, root string, argv []string) *exec.Cmd

Exec runs argv in the container without a shell; the container's PATH finds argv[0].

func (*Container) LockdownNetworkPrepared added in v0.9.0

func (c *Container) LockdownNetworkPrepared() bool

LockdownNetworkPrepared reports whether PrepareLockdownNetwork readied the container's network switch.

func (*Container) LockdownProxyErr added in v0.9.0

func (c *Container) LockdownProxyErr() error

LockdownProxyErr returns why the container could not join the lockdown proxy's network at taint (it then has no network), nil otherwise.

func (*Container) LockdownProxyNetwork added in v0.9.0

func (c *Container) LockdownProxyNetwork() string

LockdownProxyNetwork returns the internal network the container joins at taint, "" without a lockdown proxy.

func (*Container) PrepareLockdownNetwork added in v0.9.0

func (c *Container) PrepareLockdownNetwork(ctx context.Context) (denied bool, err error)

PrepareLockdownNetwork readies the container so the first taint can take its network away with RemoveLockdownNetwork. denied is true when the container already has no network (--network none in run_args), so there is nothing to remove. It fails when the network can't be removed by disconnecting runtime networks: host networking, another container's or a namespace's network, rootless slirp4netns or pasta networking.

func (*Container) PrepareLockdownProxy added in v0.9.0

func (c *Container) PrepareLockdownProxy(ctx context.Context, allowed []string) error

PrepareLockdownProxy readies the opt-in container lockdown proxy: it creates an --internal runtime network, starts a proxy limited to allowed (untrusted_content.lockdown.allowed_domains) on that network's gateway address, and arranges for RemoveLockdownNetwork to connect the container to the network after disconnecting it, so later commands reach only those hosts, through HTTP_PROXY and friends. Call it after PrepareLockdownNetwork found a network to remove. On any error it cleans up and leaves the network switch as it was: commands then have no network after taint.

func (*Container) RemoveLockdownNetwork added in v0.9.0

func (c *Container) RemoveLockdownNetwork(ctx context.Context) error

RemoveLockdownNetwork disconnects the container from every network PrepareLockdownNetwork found, for the rest of the run, and checks that none is left. Processes already running in the container lose their network too. Commands started while it runs wait for it; if it fails, every later command fails instead of running with network. It runs once; later calls return the first result.

func (*Container) TakeNetworkDenials added in v0.9.0

func (c *Container) TakeNetworkDenials() []sandboxnet.Denial

TakeNetworkDenials returns the requests the container lockdown proxy refused since the last call.

type ContainerNetworkCheck added in v0.9.0

type ContainerNetworkCheck struct {
	// Mode is the network mode the container would start with: the
	// --network (or --net) value in container.run_args, or the runtime's
	// default ("bridge", or podman's rootless default).
	Mode string
	// FromRunArgs is true when container.run_args set Mode.
	FromRunArgs bool
	// Denied: the container would have no network at all (--network none).
	Denied bool
	// Err is set when Mode can't be removed by disconnecting runtime
	// networks, so a run would refuse commands after taint.
	Err error
	// Unknown explains why the mode couldn't be predicted (the runtime
	// couldn't be asked). A run inspects the started container and decides
	// then.
	Unknown string
}

ContainerNetworkCheck is what --check predicts lockdown (#171) will do with the container's network at taint, without starting a container.

func CheckContainerLockdownNetwork added in v0.9.0

func CheckContainerLockdownNetwork(ctx context.Context, runtime string, runArgs []string) ContainerNetworkCheck

CheckContainerLockdownNetwork predicts, for --check, how lockdown will handle the network of a container started by runtime (docker when empty) with runArgs. It reads --network from runArgs; without one, docker's default is a bridge network, and for podman it asks `podman info` whether podman runs rootless, whose default (slirp4netns or pasta) can't be disconnected. It never starts a container.

type DeniedError added in v0.5.0

type DeniedError struct {
	Path    string // the path as the caller named it
	List    string // "deny_read" or "deny_write"
	Pattern string // the rule that matched, as configured
}

DeniedError is returned for a call that touches a denied path.

func (*DeniedError) Error added in v0.5.0

func (e *DeniedError) Error() string

type Environment added in v0.5.0

type Environment interface {
	// Command returns an unstarted `bash -c command` that runs in root.
	// Cancelling ctx must kill the command and everything it spawned.
	Command(ctx context.Context, root, command string) *exec.Cmd
	// Exec returns an unstarted command that runs argv directly, without a
	// shell, in root. argv[0] is looked up on the environment's PATH.
	// Cancelling ctx must kill the command and everything it spawned.
	Exec(ctx context.Context, root string, argv []string) *exec.Cmd
}

Environment decides where bash and start_process commands run.

type Executor

type Executor struct {
	Root           string // absolute working directory
	ReadOnly       bool   // permits only read_file, list_files, and grep
	BashTimeout    time.Duration
	MaxOutputChars int // 0 = unlimited
	// MaxProcesses bounds concurrently running background processes
	// (0 = DefaultMaxProcesses).
	MaxProcesses int
	// ProcessBufferBytes caps the output kept per background process
	// (0 = DefaultProcessBufferBytes); older output is dropped.
	ProcessBufferBytes int
	// Env decides where bash and start_process commands run. nil means
	// Local{}: on the host, unsandboxed.
	Env Environment
	// Stream receives bash output as it is produced when a call sets
	// stream: true. nil discards it (the result is unchanged either way).
	Stream io.Writer
	// CommandTools are the configured command_tools (never offered or run
	// in read-only mode). CommandLog, when set, gets one line per call
	// with the final argv.
	CommandTools  []*CommandTool
	CommandLog    io.Writer
	ExternalSpecs []model.ToolSpec
	// ExternalCall runs a tool from ExternalSpecs. ok is false when name is
	// not an external tool; isErr marks a failed call.
	ExternalCall func(ctx context.Context, name, args string) (out string, isErr, ok bool)
	// Plan offers the opt-in update_plan tool (also in read-only mode). The
	// agent handles its calls; the executor only advertises it.
	Plan bool
	// Images offers the opt-in view_image tool (also in read-only mode) and
	// lets ExternalCallImages pass MCP images through. MaxImageBytes caps
	// one image (0 = DefaultMaxImageBytes).
	Images        bool
	MaxImageBytes int
	// ExternalCallImages, when set and Images is on, replaces ExternalCall
	// and also returns the result's images.
	ExternalCallImages func(ctx context.Context, name, args string) (out string, images []model.Image, isErr, ok bool)
	// Skills, when it holds at least one skill, adds the read-only skill
	// tool (also in read-only mode). nil or empty offers nothing.
	Skills *skills.Set
	// ApplyPatch offers the opt-in apply_patch tool (never in read-only
	// mode).
	ApplyPatch bool
	// Delegate offers the opt-in delegate tool (also in read-only mode).
	// The agent loop runs its calls; the executor never does.
	Delegate bool
	// TaskTypes, when set, adds an optional task_type argument to the
	// delegate and worker tools (the models.delegated.routes types).
	TaskTypes []string
	// WebFetch, when set, offers the opt-in web_fetch tool (also in
	// read-only mode). nil leaves it off.
	WebFetch *WebFetcher
	// LSP, when set, offers the opt-in read-only lsp tool (also in
	// read-only mode) and, with AfterEdit, appends language-server
	// diagnostics to write_file, edit_file and apply_patch results. nil
	// leaves both off.
	LSP *LSP
	// AskUser offers the opt-in ask_user tool (also in read-only mode).
	// The agent loop handles its calls; the executor never runs them.
	AskUser bool
	// OutputFiles, when set, saves the full text of over-limit results to a
	// per-run file and keeps that directory out of grep and list_files
	// walks. nil keeps plain truncation.
	OutputFiles *OutputFiles
	// FileAccess denies the built-in file tools access to configured paths
	// (file_access config). nil denies nothing. It does not apply to bash,
	// start_process, hooks or MCP servers.
	FileAccess *FileAccess
	// ExtraDirs are additional directories outside Root that the built-in
	// file tools may reach by absolute path (additional_dirs). Read-mode
	// directories, and all of them in read-only mode, refuse writes. nil
	// keeps the tools inside Root.
	ExtraDirs []ExtraDir
	// Redactor, when set (redact_secrets), masks known secret values in
	// the results of every tool except the built-in file tools, before
	// truncation, saving and hooks. nil masks nothing.
	Redactor *eventlog.Redactor
	// Workers offers the opt-in worker and apply_worker tools (never in
	// read-only mode). The agent loop runs their calls; the executor never
	// does.
	Workers bool
	// Only, when set, restricts the catalog and dispatch to these tool
	// names (a worker's configured tools). nil allows the whole catalog.
	Only []string
	// Remember, when set, offers the opt-in remember tool (never in
	// read-only mode) and writes through it to the project memory store
	// (memory.enabled). Once a web_fetch or external (MCP) tool runs, its
	// later writes are saved pending as untrusted. nil leaves it off.
	Remember *memory.Writer
	// MemoryTools offers the read-only memory_search and memory_list tools
	// next to remember (never in read-only mode); they read Remember's
	// store.
	MemoryTools bool

	// UndoSession names this run's undo snapshot directory under
	// .tinyagent/undo. Empty generates one on first use.
	UndoSession string
	// contains filtered or unexported fields
}

Executor runs tool calls against files under Root.

func (*Executor) Catalog added in v0.4.0

func (e *Executor) Catalog() []model.ToolSpec

Catalog returns the fixed built-in, command and explicitly configured external tools. In read-only mode it returns only the read-only built-ins: command and external MCP tools must never be offered (or dispatched, see Run) when only read_file, list_files, and grep are available.

func (*Executor) Close added in v0.4.0

func (e *Executor) Close() string

Close kills every background process still registered and returns a summary of each (status and output tail), or "" if there were none. Call it when the run ends so nothing is left running.

func (*Executor) CommandToolArgv added in v0.8.0

func (e *Executor) CommandToolArgv(name, raw string) []string

CommandToolArgv returns the resolved argv for a call to the command tool named name, or nil when name is not a command tool (or its arguments are invalid). It is used by the permissions policy to match command rules against a command tool's final argv without running it.

func (*Executor) FormatCorrection added in v0.5.0

func (e *Executor) FormatCorrection(reason string) string

FormatCorrection is the tool result sent to the model for a format error.

func (*Executor) FormatError added in v0.5.0

func (e *Executor) FormatError(call model.ToolCall) string

FormatError reports why call is not a usable tool call, or "" when it is well formed. A format error is a call whose arguments are not valid JSON or not a JSON object, whose name is not in the catalog, or whose arguments miss a required field or give a field the wrong JSON type. Failures that happen while a well-formed call runs are not format errors.

In read-only mode a built-in tool outside the read-only set is not a format error: it keeps its read-only denial.

func (*Executor) LimitResult added in v0.5.0

func (e *Executor) LimitResult(call model.ToolCall, out string, isErr bool) Result

LimitResult bounds out like any other tool result: truncated to MaxOutputChars, or saved to a per-run file when OutputFiles is set.

func (*Executor) Permits added in v0.5.0

func (e *Executor) Permits(name string) bool

Permits reports whether a call to name would be dispatched: name is in the catalog, which in read-only mode holds only the read-only built-ins.

func (*Executor) Processes added in v0.5.0

func (e *Executor) Processes() []RegisteredProcess

Processes lists the registered background processes in start order.

func (*Executor) ReadProcess added in v0.4.0

func (e *Executor) ReadProcess(ctx context.Context, id string, waitMs, tail int) (string, error)

ReadProcess returns output produced since the last read. With waitMs > 0 it blocks up to that long for new output; with tail > 0 it returns only the last tail lines.

func (*Executor) Run

func (e *Executor) Run(ctx context.Context, call model.ToolCall) string

Run executes one tool call and returns text for the model. Tool failures are reported as text so the model can recover; Run never returns an error.

func (*Executor) RunResult added in v0.5.0

func (e *Executor) RunResult(ctx context.Context, call model.ToolCall) Result

RunResult is RunWithImages plus where an over-limit result was saved.

func (*Executor) RunWithError added in v0.4.0

func (e *Executor) RunWithError(ctx context.Context, call model.ToolCall) (string, bool)

RunWithError executes a tool call and reports whether execution failed. The returned text is still suitable for passing back to the model.

func (*Executor) RunWithImages added in v0.5.0

func (e *Executor) RunWithImages(ctx context.Context, call model.ToolCall) (string, []model.Image, bool)

RunWithImages is RunWithError plus any images the result carries (only with Images on). The text already holds a placeholder for each image.

func (*Executor) StartProcess added in v0.4.0

func (e *Executor) StartProcess(command string) (string, error)

StartProcess launches command with bash -c (in e.Env) in the background and returns its id with any output produced in the first moment.

func (*Executor) StopProcess added in v0.4.0

func (e *Executor) StopProcess(id string, tail int) (string, error)

StopProcess kills id's whole process group and reports its exit status and unread output (the last tail lines when tail > 0).

func (*Executor) UntrustedSource added in v0.9.0

func (e *Executor) UntrustedSource(name string) string

UntrustedSource reports which untrusted source a result of the tool name brings into context: UntrustedWebFetch for web_fetch when it is enabled, UntrustedMCP for an external (MCP) tool, and "" for every other tool. It decides by tool, never by content.

type ExtraDir added in v0.5.0

type ExtraDir struct {
	Path string `json:"path"`
	Mode string `json:"mode"`
}

ExtraDir is a directory outside the root that the built-in file tools may reach (additional_dirs config, --add-dir-read and --add-dir-write). Path is absolute, clean and symlink-resolved; Mode is DirRead or DirWrite.

func ResolveExtraDirs added in v0.5.0

func ResolveExtraDirs(root string, dirs []ExtraDir, readOnly bool) ([]ExtraDir, error)

ResolveExtraDirs validates dirs for a run rooted at root (canonical) and returns them with each path made absolute (relative paths are taken from root), cleaned and symlink-resolved. It rejects missing paths, files, filesystem roots, paths equal to, inside or containing root, entries that overlap one another, invalid modes and more than MaxExtraDirs entries. With readOnly, every directory is returned in read mode.

type FileAccess added in v0.5.0

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

FileAccess is the compiled file_access policy for the built-in file tools: gitignore-style deny_read and deny_write patterns relative to Root. A nil *FileAccess denies nothing. deny_read paths are also write-denied.

It covers only tinyagent's in-process file tools (read_file, write_file, edit_file, apply_patch, list_files, grep, view_image). bash, start_process, hooks and MCP servers are not affected.

func NewFileAccess added in v0.5.0

func NewFileAccess(root string, denyRead, denyWrite []string) (*FileAccess, error)

NewFileAccess compiles the patterns for root. It returns nil, and no error, when both lists are empty.

func (*FileAccess) AddDirs added in v0.5.0

func (f *FileAccess) AddDirs(dirs []ExtraDir)

AddDirs makes the rules also apply inside each additional directory, relative to that directory. It is a no-op on a nil *FileAccess.

func (*FileAccess) CheckRead added in v0.5.0

func (f *FileAccess) CheckRead(full, name string) error

CheckRead returns a *DeniedError when full (an absolute path under the root, as returned by Resolve) or its symlink-resolved target matches a deny_read rule. name is the path as the caller gave it.

func (*FileAccess) CheckWrite added in v0.5.0

func (f *FileAccess) CheckWrite(full, name string) error

CheckWrite is CheckRead for writes: deny_read rules apply too.

func (*FileAccess) Counts added in v0.5.0

func (f *FileAccess) Counts() (read, write int)

Counts returns the number of deny_read and deny_write rules.

func (*FileAccess) Hidden added in v0.5.0

func (f *FileAccess) Hidden(full string) bool

Hidden reports whether a walk should hide full: it matches a deny_read rule, directly or through its symlink target.

func (*FileAccess) Rules added in v0.5.0

func (f *FileAccess) Rules() (read, write []string)

Rules returns the configured deny_read and deny_write patterns.

type LSP added in v0.5.0

type LSP struct {
	Manager *lsp.Manager
	// AfterEdit appends diagnostics to edit results.
	AfterEdit bool
	// Wait is the longest wait for diagnostics.
	Wait time.Duration
	// Max caps the diagnostics listed per file.
	Max int
	// Warnings also reports warnings (severity: warning).
	Warnings bool
}

LSP connects the executor to the configured language servers.

type Local added in v0.5.0

type Local struct {
	Sandbox *Sandbox
	// CommandEnv, when non-nil, is the whole environment commands get;
	// nil inherits tinyagent's.
	CommandEnv *CommandEnv
}

Local runs commands on the host, confined by Sandbox if it is non-nil.

func (Local) Command added in v0.5.0

func (l Local) Command(ctx context.Context, root, command string) *exec.Cmd

func (Local) Exec added in v0.5.0

func (l Local) Exec(ctx context.Context, root string, argv []string) *exec.Cmd

Exec runs argv without a shell. Unsandboxed, argv[0] is looked up on the command_env PATH (tinyagent's own without a policy); sandboxed, the sandbox wrapper looks it up on the PATH the command gets.

func (Local) TakeNetworkDenials added in v0.5.0

func (l Local) TakeNetworkDenials() []sandboxnet.Denial

TakeNetworkDenials returns the requests the sandbox allowlist proxy refused since the last call.

type OutputFiles added in v0.5.0

type OutputFiles struct {
	Root  string // absolute working root (--cwd)
	Dir   string // absolute output directory, inside Root
	RunID string
	// Warn, when set, reports the first save failure of the run.
	Warn func(string)
	// contains filtered or unexported fields
}

OutputFiles saves the full text of tool results that exceed the output limit, one file per tool call, in a per-run directory under Dir. The model sees a bounded preview plus a notice naming the file, which it can page with read_file (offset/limit) or search with grep.

func NewOutputFiles added in v0.5.0

func NewOutputFiles(root, dir string, now time.Time) (*OutputFiles, error)

NewOutputFiles validates dir and returns a store with a fresh run id. No directory is created until the first result is saved.

func (*OutputFiles) Contains added in v0.5.0

func (o *OutputFiles) Contains(p string) bool

Contains reports whether the absolute path p is the output directory or inside it.

func (*OutputFiles) Prune added in v0.5.0

func (o *OutputFiles) Prune(maxRuns int) error

Prune deletes the oldest earlier run directories so at most maxRuns remain (maxRuns 0 keeps all). It runs at startup, before the current run saves anything, and only touches directories named like run ids; other files are left alone.

func (*OutputFiles) RunDir added in v0.5.0

func (o *OutputFiles) RunDir() string

RunDir is the absolute directory holding this run's files.

type ReadDirError added in v0.5.0

type ReadDirError struct {
	Path string // the path as the caller named it
	Dir  string // the additional directory
}

ReadDirError is returned for a write to a read-mode additional directory.

func (*ReadDirError) Error added in v0.5.0

func (e *ReadDirError) Error() string

type RegisteredProcess added in v0.5.0

type RegisteredProcess struct {
	ID      string
	PID     int
	Command string
	Running bool
}

RegisteredProcess describes one background process still registered.

type Result added in v0.5.0

type Result struct {
	Text    string
	Images  []model.Image
	IsError bool
	// OutputFile is the saved full output (relative to Root, slash
	// separated) when OutputFiles is on and the text was over the limit.
	OutputFile  string
	OutputBytes int
	// Notice is the line ending Text that points at the saved file (or, for
	// read_file, at the rest of the file); empty when none was added.
	Notice string
	// Paths are the absolute paths a successful built-in file tool call
	// touched: read_file, write_file, edit_file, view_image and lsp's
	// path, list_files and grep's path argument (default "."), and every
	// file an apply_patch call added, updated, deleted or moved. They may
	// lie outside Root (additional directories); nil for other tools and
	// for failed calls.
	Paths []string
	// Instructions is the suffix of Text holding scoped AGENTS.md blocks
	// appended by the agent loop; feedback re-truncation keeps it whole.
	Instructions string
	// Redactions counts the secret values Redactor masked in the result.
	Redactions int
}

Result is one tool call's outcome for the model.

type Sandbox added in v0.5.0

type Sandbox struct {
	Backend  string   // e.g. "bwrap + landlock (ABI 6)", "landlock (ABI 6)" or "seatbelt"
	Writable []string // directories commands may write, including Tmp
	Network  bool
	// AllowedDomains, when set, are the only hosts commands may reach, over
	// HTTP and HTTPS through a proxy tinyagent runs outside the sandbox.
	AllowedDomains []string
	Tmp            string // per-run temporary directory, exported as TMPDIR

	// Warnings are notes about the backend choice, such as auto falling
	// back to Landlock alone because AppArmor blocks bwrap.
	Warnings []string
	// contains filtered or unexported fields
}

Sandbox confines bash and start_process commands (and everything they spawn) at the OS level: writes are limited to Writable, and outbound network is denied unless Network is set, or limited to AllowedDomains through a filtering proxy. Reads stay unrestricted.

func CommandSandbox added in v0.9.0

func CommandSandbox(env Environment) *Sandbox

CommandSandbox returns the sandbox that confines env's commands, or nil when they run unsandboxed or in a container.

func NewSandbox added in v0.5.0

func NewSandbox(root string, extra []string, network bool, allowed []string) (*Sandbox, error)

NewSandbox checks that this host can enforce the policy and creates the per-run temp directory. It fails rather than returning a weaker sandbox. root and extra must be existing directories. A non-empty allowed list (sandbox_allowed_domains entries) starts the filtering proxy; it can't be combined with network.

func NewSandboxBackend added in v0.11.0

func NewSandboxBackend(backend, root string, extra []string, network bool, allowed []string) (*Sandbox, error)

NewSandboxBackend is NewSandbox with the sandbox_backend setting.

func (*Sandbox) Cleanup added in v0.5.0

func (s *Sandbox) Cleanup()

Cleanup stops the allowlist proxy and removes the per-run temp directory.

func (*Sandbox) Command added in v0.9.0

func (s *Sandbox) Command(ctx context.Context, argv []string) *exec.Cmd

Command returns argv confined by the sandbox, like bash commands are.

func (*Sandbox) Describe added in v0.5.0

func (s *Sandbox) Describe() string

Describe is the one-line summary printed at startup.

func (*Sandbox) DirectUntilTaint added in v0.9.0

func (s *Sandbox) DirectUntilTaint() bool

DirectUntilTaint reports whether commands keep their direct network (sandbox_network) until the first taint, when the lockdown takes it away (PrepareLockdownNetwork succeeded). Background processes started before then keep theirs, so the lockdown stops them at taint.

func (*Sandbox) LockdownConfinable added in v0.9.0

func (s *Sandbox) LockdownConfinable() bool

LockdownConfinable reports whether the untrusted-content lockdown (issue #171) can keep commands running after taint: their network is denied, or limited by the allowlist proxy, which NarrowNetwork can restrict further. sandbox_network gives commands direct network, which is confinable only once PrepareLockdownNetwork has readied its switch.

func (*Sandbox) NarrowNetwork added in v0.9.0

func (s *Sandbox) NarrowNetwork(allowed []string) error

NarrowNetwork restricts the allowlist proxy, for the rest of the run, to hosts in both sandbox_allowed_domains and allowed (the untrusted_content.lockdown.allowed_domains entries), and closes the connections opened before. Background processes started earlier go through the same proxy, so they are narrowed too. With network denied there is nothing to narrow. A sandbox_network sandbox readied by PrepareLockdownNetwork loses its direct network instead: later commands get the network prepared there (allowed was fixed then). It fails for a sandbox lockdown can't confine.

func (*Sandbox) NetworkMode added in v0.5.0

func (s *Sandbox) NetworkMode() string

NetworkMode describes the network policy: denied, allowed, or allowlist with its entries.

func (*Sandbox) PrepareLockdownNetwork added in v0.9.0

func (s *Sandbox) PrepareLockdownNetwork(allowed []string) error

PrepareLockdownNetwork readies a sandbox_network sandbox for the untrusted-content lockdown: at the first taint NarrowNetwork takes its commands' direct network away. Commands started after that have their network denied when allowed (untrusted_content.lockdown.allowed_domains) is empty, or reach only those hosts through a proxy tinyagent starts now. It fails, leaving the sandbox unchanged, when the sandbox has no direct network, allowed is invalid, or this host can't deny the network (or create the network namespace the proxy needs); lockdown then refuses commands after taint. Call it once, before the run starts and before workers copy the sandbox.

func (*Sandbox) Proxied added in v0.9.0

func (s *Sandbox) Proxied() bool

Proxied reports whether commands reach the network through the allowlist proxy after taint: the sandbox_allowed_domains proxy, or the lockdown proxy PrepareLockdownNetwork started.

func (*Sandbox) TakeNetworkDenials added in v0.5.0

func (s *Sandbox) TakeNetworkDenials() []sandboxnet.Denial

TakeNetworkDenials returns the requests the allowlist proxy refused since the last call.

type WebFetchRecord added in v0.5.0

type WebFetchRecord struct {
	URL          string
	FinalURL     string
	Status       int
	ContentType  string
	Bytes        int
	Truncated    bool
	Duration     time.Duration
	DeniedReason string
	Error        string
}

WebFetchRecord describes one fetch for events and verbose output.

func (WebFetchRecord) Fields added in v0.5.0

func (r WebFetchRecord) Fields() map[string]any

Fields returns the record as web_fetch event fields.

type WebFetcher added in v0.5.0

type WebFetcher struct {
	// Domains are the configured web_fetch.allowed_domains entries.
	Domains []string

	MaxBytes int
	Timeout  time.Duration
	// UserAgent is sent with every request.
	UserAgent string

	// Resolve and Dial default to the system resolver and a net.Dialer;
	// tests replace them.
	Resolve func(ctx context.Context, host string) ([]netip.Addr, error)
	Dial    func(ctx context.Context, network, addr string) (net.Conn, error)
	// Gate, when set, is checked for every request hop after the
	// allowlist (the untrusted-content lockdown sets it); an error
	// refuses the hop before any connection.
	Gate func(host string, port int) error
	// contains filtered or unexported fields
}

WebFetcher runs web_fetch calls. It fetches in tinyagent's own process, never through bash, a sandbox or proxy environment variables, and only from hosts its rules allow.

func NewWebFetcher added in v0.5.0

func NewWebFetcher(domains []string, maxBytes int, timeout time.Duration, userAgent string) (*WebFetcher, error)

NewWebFetcher returns a fetcher for allowlist entries in the sandbox_allowed_domains syntax. An empty allowlist or a bad entry is an error. maxBytes and timeout of 0 use the defaults.

func (*WebFetcher) Fetch added in v0.5.0

func (f *WebFetcher) Fetch(ctx context.Context, rawURL string) (string, error)

Fetch fetches rawURL and returns the header line and text.

func (*WebFetcher) TakeRecords added in v0.5.0

func (f *WebFetcher) TakeRecords() []WebFetchRecord

TakeRecords returns the fetches made since the last call.

Jump to

Keyboard shortcuts

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