Skip to content

Tools

pkg/agent/tool/ defines the tool framework an agent uses to take action — interfaces, the registry, middleware (logging, retry, idempotency, schema-validation), human-input plumbing, and interrupt support. pkg/agent/builtin/ is the catalogue of ready-to-use tools the framework ships with — helix.shell.exec, helix.fs.read, helix.web.fetch, the helix.* developer helpers, and more — that agents reference from YAML as type: function tools.

What it does

A tool, to the agent, is a JSON-shaped function the LLM can call:

type Tool interface {
    Info() *ToolInfo            // name, description, JSON Schema, categories
    Invoke(ctx context.Context, arguments string) (string, error)
}

Two variants extend the base interface for richer protocols:

type StreamableTool interface {
    Tool
    StreamInvoke(ctx context.Context, arguments string) (*llm.StreamReader, error)
}

type MultimodalTool interface {
    Tool
    InvokeMultimodal(ctx context.Context, arguments string) ([]llm.ContentPart, error)
}

The agent calls Info().ToDefinition() to build the llm.ToolDefinition passed to the model with WithTools, then calls Invoke on whichever tool the LLM picks. Tools are stored on the agent in a Registry (thread-safe map). FuncTool[T] wraps a typed Go function (auto-unmarshals args into T); SimpleTool wraps a function that takes a raw JSON string.

Middleware family

Middleware = func(Tool) Tool — compose cross-cutting concerns around any tool without modifying it:

  • WithLogging() — slog Add / Invoke / result logging.
  • WithRetry(policy) — configurable retry (MaxAttempts, Backoff exponential/linear/constant, RetryOn clauses for transient errors and http_status lists). NewTransient(err, after) wraps an error as retryable with a RetryAfter hint. HTTP errors can be classified via ClassifyHTTPError.
  • WithIdempotency(policy) — caches results by key extractor + scope (run / session / global) in a pluggable IdempotentStore (in-memory ships built-in). Eliminates duplicate work when the LLM re-issues the same call.
  • WithResultSchema(schema) — JSON-Schema-validates the tool's STRING result against a small subset of JSON Schema (top-level type, required, properties.type, enum). Fails fast on malformed results.

Interrupt + human input

  • tool.Interrupt(info) — return this error from inside a tool to pause the agent's run cleanly. The agent surfaces an *InterruptError to the caller, who can checkpoint and resume via the Runner.
  • tool.WithHumanInput(ctx, fn) / tool.RequestHumanInput(ctx, req) — a tool can ask the human for input mid-execution. The agent's OnToolHumanInput callback is plumbed onto the context for the run.

Tool definitions in YAML

AgentDefinition.Tools is a list of ToolDefinition:

tools:
  - name: read-file
    type: function           # function | pipeline | mcp | a2a | connector
    function: fs.read        # builtin function ID
    description: Read a file from disk
  - name: query-db
    type: pipeline
    pipeline_id: sql-query
    description: Query the application database

Tool types:

  • function — bind to a pkg/agent/builtin function by ID.
  • pipeline — invoke a Helix route by pipeline_id. The agent sends the args as the exchange body and reads the route's output back; useful for "the tool IS itself a Helix flow".
  • mcp — call an external MCP server tool (pkg/component/mcp).
  • a2a — call an external A2A agent (pkg/component/a2a).
  • connector — invoke a registered connector (pkg/connector/connectors/all).

Built-in tool catalogue

pkg/agent/builtin/ registers a global catalogue. Reference any of these IDs from YAML as type: function + function: <id>.

File system (fs)

ID Description
fs.read Read a file. Optional offset (start line, 0-based) and limit (line count).
fs.write Write content to a file; creates the path, overwrites if it exists.
fs.edit Find-and-replace text in a file. Requires old_string to match exactly; replace_all: true allowed when multiple matches exist.
fs.list List files / directories. recursive: true descends; auto-skips node_modules, __pycache__, target, vendor, hidden dirs. Result capped at 500 entries.
fs.glob Find files matching a glob (e.g. *.go). Result capped at 200 matches.
fs.grep Text search across files. include glob filter, max_results (default 50). Skips binaries (.exe, .bin, .so, …).
fs.mkdir Create a directory and its parents.
fs.delete Delete a file or empty directory.

All fs.* tools respect SetAllowedPaths([...]) — empty (default) = no restriction; non-empty = paths must be under one of the allowed base directories. The working directory is honored from ShellConfig.WorkDir.

Shell (shell)

ID Description
shell.exec Execute a shell command and return combined stdout + stderr. Used for builds, tests, git commands.

Web (web)

ID Description
web.fetch HTTP GET / POST with optional headers and body. Returns the response body.

Geo (geo)

Pure-Go geospatial helpers backed by pkg/geo (the same core as the geo:// component and the sl::gis Starlang module). Points are [lon, lat] (WGS84); geometries are WKT or GeoJSON.

ID Description
geo.distance Great-circle distance in meters between two [lon,lat] points.
geo.bearing Initial compass bearing in degrees (0–360, clockwise from north) from point a to point b.
geo.geohash Encode a [lon,lat] point as a geohash string. precision is the character count (default 7, ~150 m cells).
geo.within Report whether a [lon,lat] point lies inside an area (a Polygon/MultiPolygon as WKT or GeoJSON).
geo.centroid Return the centroid of a geometry (WKT or GeoJSON) as a GeoJSON Point.
geo.area Geodesic area of a polygonal geometry (WKT or GeoJSON) in square meters.
geo.parse Parse a geometry (WKT or GeoJSON) and return it in the requested form. to=geojson (default) or to=wkt.

Data + math (data, math)

ID Description
data.json_parse Parse a JSON string; returns a formatted version. Validates structure.
data.json_format Pretty-print a JSON string with indentation.
data.csv_parse Parse CSV text into JSON records (first row treated as headers).
math.eval Evaluate +, -, *, /, parentheses.

XLSX (xlsx)

Constant-memory, paged readers for .xlsx workbooks — built on the same streaming row iterator as the xlsx:// component's stream=true mode. Use these for agent-driven inspection of large spreadsheets (page a window of rows on demand, without loading the file); use the xlsx:// component for route-based bulk ingestion. Unlike fs.read (which is line-based and loads the whole file), these decode the workbook and stream rows.

ID Description
xlsx.read_rows Read a bounded page of rows from one sheet (file, sheet, offset, limit, has_header). Streams row-by-row, so paging deep into a million-row sheet stays constant-memory. Returns rows keyed by header plus has_more for pagination.
xlsx.list_sheets List a workbook's sheet names in order — discover which sheets to page with xlsx.read_rows.

CSV (csv)

Constant-memory, paged reader for delimited-text (CSV/TSV) files — the same encoding/csv streaming core as the csv:// component's stream=true mode. Prefer it over fs.read for CSV: fs.read loads the whole file and returns raw text, while this pages parsed records.

ID Description
csv.read_rows Read a bounded page of rows from a CSV/TSV file (file, offset, limit, has_header, delimiter). Streams row-by-row, so paging deep into a million-row file stays constant-memory. Returns rows keyed by header plus has_more for pagination.

Time (time)

ID Description
time.now Current UTC time. Default RFC3339; pass a Go layout to override.
time.now_in_tz Current time in a named IANA timezone (e.g. America/New_York).

Helix developer tooling (helix)

Designed for the Helix Studio "build me a flow" workflow.

ID Description
helix.validate Run helix validate against a flow.yaml / .json and return stdout+stderr.
helix.run Run a flow in the foreground with a short timeout (default 10s). Returns combined output and exit code.
helix.test Run declarative helix test cases. Deterministic tests need no LLM key.
helix.docs_search Substring search across docs/ Markdown.
helix.examples_search Substring search across examples/ YAML/JSON.
helix.init Scaffold a Helix project via helix create <name> — agents/, tools/, pipelines/, routes/, mcps/, prompts/, etc.
helix.schema Return the authoritative Helix DSL schema (workflow / step / agent / tool / transform / test / rag).
helix.check_env Walk YAML and report every ${ENV_VAR} reference, marking which are set / missing.
helix.write_env_template Generate .env.example listing every referenced env var.
helix.explain_error Diagnose a Helix runtime / validation error against known patterns; returns CAUSE / FIX / WHERE / NEXT.
helix.propose_architecture Read a spec / PRD and emit a structured planning outline (sections, requirement IDs, component layout).
helix.track_requirements Cross-reference FR-/NFR-/REQ- IDs in a spec against the project's flow files.
helix.write_workflow Emit a guaranteed-valid workflow YAML from structured args. Auto-validates.
helix.write_app Assemble a runnable app.yaml by merging agent / workflow / tool YAMLs. Auto-discovers files.
helix.write_agent Emit a guaranteed-valid agent definition YAML.
helix.write_test Emit a deterministic test case under tests/<name>.yaml, deriving input.uri from the referenced workflow. Auto-runs helix test.
helix.write_pipeline Emit a guaranteed-valid pipeline YAML (including RAG ingest/retrieve).
helix.fix_starlang Lint + autofix a Starlang transform expression (Python-dict literals, missing body = read(payload, ...), etc.).
helix.write_rag_ingest Emit a complete rag-ingest → rag-chunk → rag-embed → rag-store pipeline with dimension alignment.
helix.write_rag_retrieve Emit a complete rag-embed → rag-retrieve → rag-synthesize pipeline.

The full registry is enumerated via builtin.Global().List() and serialised by builtin.ListJSON() (used by the Studio Designer dropdown).

Skill tools (registered when an agent has skills)

When skills: is present, the framework injects three more tools via the SkillToolset (pkg/agent/skilltoolset):

  • list_skills — list available skill names + descriptions.
  • load_skill — load a skill's full instructions.
  • load_skill_resource — read a file under a skill's references/, assets/, or scripts/ directories.

See skills.

Configuration

AgentDefinition.Tools per-entry shape (full schema in pkg/workflow/definition.go):

Field Type Description
name string Name exposed to the LLM.
type string function / pipeline / mcp / a2a / connector.
function string (for type: function) builtin ID.
pipeline_id string (for type: pipeline) route to invoke.
description string What the tool does — the LLM reads this to decide when to call.
parameters block JSON Schema for the args. Inferred from the builtin when omitted.
categories list Policy labels (payment, pii, external_write) — approval_categories: can refer to these.
retry block Per-tool override of tool_retry.
idempotent block { enabled, scope, ttl } — wraps the tool in WithIdempotency.

Behavior notes

  • Tool categories are coarse policy labels. ApprovalCategories matches them; Tool.Info().HasCategory(cat) is the runtime check.
  • RequiresApproval flag (legacy) is honored when policy: tagged, but the category-based approach is preferred — it scales without having to mark every sensitive tool individually.
  • The middleware family is also exposed at the YAML level: tool_retry: on the agent, plus idempotent: and retry: per tool definition. Hook order is fixed by the reifier so behaviour is deterministic across reloads.
  • For full developer ergonomics in Studio, every helix.* tool has a Label (Designer dropdown) and rich Description (what the LLM sees) — they're the same struct.

Example

A minimal coder agent with shell + filesystem access:

agents:
  - id: coder
    type: react
    model: { provider: anthropic, model: claude-sonnet-4-7 }
    system_prompt: |
      You are an expert Go developer working in the user's repo.
    tools:
      - { name: read-file,  type: function, function: fs.read }
      - { name: write-file, type: function, function: fs.write }
      - { name: edit-file,  type: function, function: fs.edit }
      - { name: list-dir,   type: function, function: fs.list }
      - { name: grep,       type: function, function: fs.grep }
      - { name: shell,      type: function, function: shell.exec,
          categories: [external_write] }
    approval_policy: tagged
    approval_categories: [external_write]

Source

  • pkg/agent/tool/tool.go — interfaces, FuncTool / SimpleTool, Registry, WithLogging.
  • pkg/agent/tool/retry.go — RetryPolicy, backoffs, WithRetry, ClassifyHTTPError.
  • pkg/agent/tool/idempotent.go — IdempotentPolicy, MemoryIdempotentStore, WithIdempotency.
  • pkg/agent/tool/schema.go — WithResultSchema, JSON-Schema lite validator.
  • pkg/agent/tool/interrupt.go — tool.Interrupt, *InterruptError.
  • pkg/agent/tool/human_input.go — RequestHumanInput, WithHumanInput.
  • pkg/agent/tool/context.go — WithRunID, WithSessionID.
  • pkg/agent/builtin/registry.go — BuiltinFunc, global registry.
  • pkg/agent/builtin/{fs,shell,web,data,time,helix,helix_write,helix_env,helix_arch,helix_debug}.go — the registered functions.

See also

  • react, supervisor — how the loop invokes tools.
  • skills — list_skills / load_skill / load_skill_resource and progressive disclosure.
  • guardrails — tool_args and tool_result guard stages.
  • memory — the other agent state subsystem.