Documentation
¶
Overview ¶
Package tool provides a unified ToolRegistry that normalizes built-in tools and MCP server tools under a single namespace and resolution scheme.
Built-in tools are registered under their bare name (e.g. "git_diff"). MCP tools follow the namespace convention "mcp.<server>.<tool>". Workflows reference tools by their qualified name; the registry resolves them unambiguously and detects collisions at registration time.
Index ¶
- Variables
- func IsMCPName(name string) bool
- func IsMCPWildcard(name string) bool
- func ParseMCPName(qualified string) (server, toolName string, err error)
- func ParseMCPWildcard(name string) (server string, err error)
- func RegisterAskUser(reg *Registry, handler AskUserHandler) error
- func RegisterClawAll(reg *Registry, defaults ClawDefaults) error
- func RegisterClawBuiltins(reg *Registry, workspace string) error
- func RegisterClawBuiltinsWithEnv(reg *Registry, workspace string, bashExtraEnv []string) error
- func RegisterClawComputerUse(reg *Registry) error
- func RegisterClawConfig(reg *Registry, configMap map[string]any) error
- func RegisterClawCron(reg *Registry, cronReg *clawteam.CronRegistry) error
- func RegisterClawLSP(reg *Registry, lspReg *clawlsp.Registry) error
- func RegisterClawMCPResources(reg *Registry, provider clawmcp.Provider) error
- func RegisterClawPlanMode(reg *Registry, state *clawtools.PlanModeState) error
- func RegisterClawReadImage(reg *Registry) error
- func RegisterClawSimple(reg *Registry) error
- func RegisterClawSkill(reg *Registry, workDir string) error
- func RegisterClawSubagents(reg *Registry, runner SubagentRunner) error
- func RegisterClawTasks(reg *Registry, taskReg *clawtask.Registry) error
- func RegisterClawTeams(reg *Registry, teamReg *clawteam.TeamRegistry) error
- func RegisterClawTodo(reg *Registry) error
- func RegisterClawTool(reg *Registry, t api.Tool, ...) error
- func RegisterClawToolSearch(reg *Registry, snapshot ToolSnapshot) error
- func RegisterClawWebSearch(reg *Registry) error
- func RegisterClawWorkers(reg *Registry, workerReg *clawworker.WorkerRegistry) error
- func SchemaFingerprint(schema json.RawMessage) string
- type AskUserHandler
- type ClassifierChecker
- type ClassifierLogger
- type ClawDefaults
- type Origin
- type OriginKind
- type Policy
- type PolicyContext
- type Registry
- func (r *Registry) Len() int
- func (r *Registry) List() []*ToolDef
- func (r *Registry) ListByOrigin(kind OriginKind) []*ToolDef
- func (r *Registry) ListByServer(server string) []*ToolDef
- func (r *Registry) RegisterBuiltin(name string, desc string, schema json.RawMessage, ...) error
- func (r *Registry) RegisterMCP(server, toolName, desc string, schema json.RawMessage, ...) error
- func (r *Registry) Resolve(ref string) (*ToolDef, error)
- func (r *Registry) ResolveAll(refs []string) ([]llmtypes.LLMTool, error)
- func (r *Registry) ResolveMap(refs []string) (map[string]llmtypes.LLMTool, error)
- type Rule
- type RulePolicy
- type SubagentRunner
- type ToolChecker
- type ToolDef
- type ToolSnapshot
- type VarRule
Constants ¶
This section is empty.
Variables ¶
var ErrToolDenied = fmt.Errorf("tool: denied by policy")
ErrToolDenied is returned when a tool call is rejected by the policy.
Functions ¶
func IsMCPWildcard ¶
IsMCPWildcard returns true if name matches the MCP server wildcard pattern "mcp.<server>.*".
func ParseMCPName ¶
ParseMCPName splits "mcp.<server>.<tool>" into server and tool name. Returns an error if the format is invalid.
func ParseMCPWildcard ¶
ParseMCPWildcard extracts the server name from a wildcard pattern "mcp.<server>.*". Returns an error if the format is invalid.
func RegisterAskUser ¶
func RegisterAskUser(reg *Registry, handler AskUserHandler) error
RegisterAskUser registers claw-code-go's native `ask_user` tool. The handler controls behaviour: when nil, the default raises delegate.ErrAskUser so iterion's pause/resume flow takes over (CLI prompt → answer injection on resume). Tests and headless runners supply a handler that returns an Answer directly so the workflow proceeds inline.
The tool is available to any node with `interaction:` enabled; iterion's executor auto-includes it in such nodes' resolved tool list so workflow authors don't need to add `ask_user` to their `tools:` field.
func RegisterClawAll ¶
func RegisterClawAll(reg *Registry, defaults ClawDefaults) error
RegisterClawAll registers the full curated set of claw tools (file IO, shell, search, web fetch, simple utilities, todo, subagents, plan mode, tasks, workers, teams, cron, MCP resources, LSP, tool_search) against reg using the registries and per-session state in defaults. It is the preferred one-shot entry point for hosts that want every iterion-supported tool surfaced without thinking about which family to wire.
Tools not yet usable from a workflow because the LLM would call them without context (web_search → needs BRAVE_API_KEY, computer_use → needs vision-capable model) are gated by explicit opt-in flags on ClawDefaults.
Calling this twice on the same registry will fail on the second call due to duplicate-name detection in the registry.
func RegisterClawBuiltins ¶
RegisterClawBuiltins registers the standard claw-code-go built-in tools against the given Registry, making them callable by claw-backend agents that declare e.g. `tools: [read_file, write_file, bash]` in their .iter fixture.
Workspace is forwarded to the bash tool for command validation; pass an empty string to skip workspace-based validation. Pass an empty string when registering on a registry that may be reused across workspaces.
The set is intentionally curated — these are the seven workflow-grade tools that map cleanly onto file IO, shell, search, and HTTP fetch. Specialised tools (todo_write, plan_mode, agent, mcp_*, ...) live in claw-code-go's internal/tools/ and are not auto-registered here; callers that need them should import claw-code-go/pkg/api/tools and register individual entries via RegisterClawTool.
func RegisterClawBuiltinsWithEnv ¶
RegisterClawBuiltinsWithEnv is RegisterClawBuiltins plus an optional extraEnv slice (KEY=value entries) that the bash tool will append to the inherited environment on every call. Use this when iterion is invoked outside its devbox/nix shell and the caller wants to surface the project toolchain (go, gofmt, ...) to the LLM-driven shell so fixers can validate their patches in-loop. Pass nil for plain inheritance.
func RegisterClawComputerUse ¶
RegisterClawComputerUse registers the desktop-control tools that require an X11 display — screenshot and the unified computer_use action dispatcher (left_click / right_click / middle_click / double_click / type / key / mouse_move / cursor_position / left_click_drag). Kept out of the default RegisterClawBuiltins set because most iterion workflows are headless; opt in via Defaults.IncludeComputerUse when you have an agent targeting a display (Xvfb covered by the live coverage test).
On a host without xdotool / ImageMagick `import` (or without a display), each call returns ErrComputerUseUnavailable wrapped — agents can detect the gap with errors.Is rather than parsing strings.
func RegisterClawConfig ¶
RegisterClawConfig registers the `config` tool against a host-supplied flat configuration map. Pass an empty map (not nil) if you have no configuration to expose — the tool will report `found: false` for every key, which is still a valid live result.
func RegisterClawCron ¶
func RegisterClawCron(reg *Registry, cronReg *clawteam.CronRegistry) error
RegisterClawCron registers the four cron_* tools that share a *team.CronRegistry. Cron entries hold scheduled task prompts.
func RegisterClawLSP ¶
RegisterClawLSP registers the `lsp` action-dispatcher tool. The lsp.Registry tracks connected language servers; build it once via clawlsp.NewRegistry().
func RegisterClawMCPResources ¶
RegisterClawMCPResources registers list_mcp_resources, read_mcp_resource and mcp_auth against the supplied Provider. The Provider is the one bridge between iterion's MCP manager and claw's resource introspection tools — passing nil falls back to an empty in-process Registry, which is fine for tests but not for hosts that already manage their own MCP servers.
func RegisterClawPlanMode ¶
func RegisterClawPlanMode(reg *Registry, state *clawtools.PlanModeState) error
RegisterClawPlanMode registers `enter_plan_mode` and `exit_plan_mode`. Both tools share a *PlanModeState so they can coordinate the active flag and on-disk persistence directory.
func RegisterClawReadImage ¶
RegisterClawReadImage registers `read_image` only — the file/URL loader that returns a base64 content block downstream multimodal agents can splice into their next message. Unlike screenshot / computer_use this tool does not require a display, so it's safe in headless workflows.
func RegisterClawSimple ¶
RegisterClawSimple registers the no-dependency claw tools that don't fit naturally into the file-IO/shell/HTTP set RegisterClawBuiltins covers: send_user_message, remote_trigger, sleep, notebook_edit, repl, structured_output. These are useful for nodes that want process-level utilities (timing, cell edits, REPL evaluation) but don't need a registry plumbed in.
func RegisterClawSkill ¶
RegisterClawSkill registers the `skill` tool, looking up skills at <workDir>/.claude/skills/. Pass an empty workDir to resolve against the process CWD.
func RegisterClawSubagents ¶
func RegisterClawSubagents(reg *Registry, runner SubagentRunner) error
RegisterClawSubagents registers the `agent` tool. When `runner` is nil, the registration falls back to claw's metadata-only stub — useful for stand-alone tests where actually launching a child conversation is out of scope. When `runner` is non-nil, it is invoked directly: the LLM's tool_use lands in the runner, which is expected to coordinate the child loop.
func RegisterClawTasks ¶
RegisterClawTasks registers the seven task_* tools (task_create, task_get, task_list, task_output, task_stop, task_update, run_task_packet). All share the same *task.Registry; pass a single instance built via clawtask.NewRegistry().
func RegisterClawTeams ¶
func RegisterClawTeams(reg *Registry, teamReg *clawteam.TeamRegistry) error
RegisterClawTeams registers the four team_* tools that share a *team.TeamRegistry. Teams are named groupings of task IDs.
func RegisterClawTodo ¶
RegisterClawTodo registers the `todo_write` tool for read/write of the project todo list at .claude/todos.json. No dependency.
func RegisterClawTool ¶
func RegisterClawTool(reg *Registry, t api.Tool, exec func(ctx context.Context, input map[string]any) (string, error)) error
RegisterClawTool registers a single claw-code-go tool against the registry. Use this to add specialised tools that RegisterClawBuiltins does not include by default.
func RegisterClawToolSearch ¶
func RegisterClawToolSearch(reg *Registry, snapshot ToolSnapshot) error
RegisterClawToolSearch registers the `tool_search` meta-tool. The snapshot closure is invoked on every call to capture the live tool catalog; pass nil to use an empty haystack (degraded but valid).
func RegisterClawWebSearch ¶
RegisterClawWebSearch registers the `web_search` tool. Reads BRAVE_API_KEY (or compatible) at execute time; absence surfaces as a tool error.
func RegisterClawWorkers ¶
func RegisterClawWorkers(reg *Registry, workerReg *clawworker.WorkerRegistry) error
RegisterClawWorkers registers the nine worker_* tools that share a *worker.WorkerRegistry. Workers are subprocess agents the runtime spawns and observes; the registry tracks their lifecycle.
func SchemaFingerprint ¶
func SchemaFingerprint(schema json.RawMessage) string
SchemaFingerprint computes a deterministic SHA-256 hex digest of a JSON schema. The input is unmarshalled and re-marshalled to produce canonical (sorted-key, compact) JSON before hashing. Returns an empty string for nil or empty input.
Types ¶
type AskUserHandler ¶
AskUserHandler is invoked when the LLM calls ask_user. Returning an Answer + nil error completes the call inline (no workflow pause); returning an error of type *delegate.ErrAskUser triggers iterion's pause/resume flow. nil falls back to the latter (default behaviour).
type ClassifierChecker ¶
type ClassifierChecker struct {
Classifier permissions.Classifier
Base ToolChecker
Logger ClassifierLogger
}
ClassifierChecker wraps a permissions.Classifier (typically LLMClassifier chained over RuleClassifier) into iterion's ToolChecker interface. The classifier is consulted first and short-circuits on Allow/Deny; Ask falls through to the optional base checker.
A nil ClassifierChecker.Base treats Ask as Allow (the static policy is optional). Use BuildChecker as the base to keep workflow-level allowlists and per-node overrides intact while letting an LLMClassifier veto or pre-approve calls.
Logger is optional; when set, classifier errors and JSON decoding failures are surfaced at Warn level. Without a logger, errors fall through silently to the base checker (legacy behavior).
func (*ClassifierChecker) CheckContext ¶
func (cc *ClassifierChecker) CheckContext(pctx PolicyContext) error
CheckContext implements ToolChecker.
type ClassifierLogger ¶
type ClassifierLogger interface {
Warn(format string, args ...any)
Debug(format string, args ...any)
}
ClassifierLogger is the minimal logging surface ClassifierChecker uses to surface classifier errors and malformed inputs without coupling the tool package to a concrete logger. Both methods accept printf-style arguments.
log.Logger satisfies this interface implicitly via its Warn/Debug methods.
type ClawDefaults ¶
type ClawDefaults struct {
// Workspace is forwarded to bash for command validation and to the
// skill tool for skill lookup. Leave empty to skip workspace
// gating.
Workspace string
// Tasks, Workers, Teams, Crons, LSP hold the registries each tool
// family needs. Leave nil to have RegisterClawAll allocate a fresh
// empty registry.
Tasks *clawtask.Registry
Workers *clawworker.WorkerRegistry
Teams *clawteam.TeamRegistry
Crons *clawteam.CronRegistry
LSP *clawlsp.Registry
// MCPProvider feeds list_mcp_resources / read_mcp_resource /
// mcp_auth. Hosts (e.g. iterion's MCP manager) implement the
// Provider interface to avoid double-connecting servers; tests can
// pass a Registry-backed provider via clawmcp.NewRegistryProvider.
// Leave nil for RegisterClawAll to wire an empty in-process
// Registry-backed provider — useful for stand-alone claw smoke
// tests, not for hosts that have their own MCP infrastructure.
MCPProvider clawmcp.Provider
// Subagent, when non-nil, replaces claw's default metadata-only
// agent executor with a real child-conversation runner. Hosts
// build this via model.NewSubagentRunner. When nil, the agent
// tool stays a stub (smoke-test parity).
Subagent SubagentRunner
// AskUser, when non-nil, replaces the default ask_user handler
// (which raises delegate.ErrAskUser to trigger pause/resume) with
// an inline handler. Tests use this to auto-answer the LLM so the
// workflow continues without pausing.
AskUser AskUserHandler
// PlanMode is shared by enter_plan_mode and exit_plan_mode so the
// pair can coordinate. Nil disables plan_mode tooling.
PlanMode *clawtools.PlanModeState
// IncludeWebSearch toggles registration of the `web_search` tool.
// Off by default because it falls back to scraping DuckDuckGo Lite
// when BRAVE_API_KEY is unset, which is brittle; tests typically
// override the URL via env to point at a fixture.
IncludeWebSearch bool
// IncludeComputerUse toggles screenshot + computer_use registration.
// Off by default since both require an X11 display. read_image is
// always registered (no display needed).
IncludeComputerUse bool
// Config, when non-nil, is exposed via the `config` tool. Leave
// nil to surface an empty map — the tool will still register but
// every key lookup reports `found: false`.
Config map[string]any
// BashExtraEnv, when non-empty, is appended to the inherited
// environment of every bash tool invocation (KEY=value entries).
// Use this to surface a project-managed toolchain (devbox / nix /
// asdf) bin path so the LLM-driven shell can run go/gofmt/etc.
// even when the operator did not prefix the iterion launch with
// `devbox run --`. Nil/empty means plain os.Environ() inheritance.
BashExtraEnv []string
}
ClawDefaults bundles the registries and per-session state the optional claw tool families need. Hosts (e.g. iterion's CLI) build one ClawDefaults per run and pass it to RegisterClawAll, which wires every supported tool against shared in-memory state.
Field zero-values are populated lazily by RegisterClawAll so callers can opt into specific subsystems by leaving the rest at zero.
type Origin ¶
type Origin struct {
Kind OriginKind // builtin or mcp
Server string // MCP server name (empty for built-ins)
}
Origin describes the provenance of a tool.
type OriginKind ¶
type OriginKind int
OriginKind discriminates built-in vs MCP tools.
const ( OriginBuiltin OriginKind = iota OriginMCP )
func (OriginKind) String ¶
func (ok OriginKind) String() string
type Policy ¶
type Policy struct {
// AllowedTools is the list of tool name patterns.
// nil = open (everything allowed). Empty slice = deny all.
AllowedTools []string
}
Policy controls which tools may be executed during a run. It enforces an allowlist of tool name patterns. If the allowlist is nil (zero-value), all tools are allowed (open policy). An empty non-nil allowlist denies everything.
Pattern syntax:
- "*" → allow all tools
- "git_diff" → exact match on qualified name
- "mcp.github.*" → prefix match: any tool under the mcp.github namespace
- "run_command" → exact match on a built-in
func DenyAllPolicy ¶
func DenyAllPolicy() *Policy
DenyAllPolicy returns a policy that denies every tool.
func (*Policy) CheckContext ¶
func (p *Policy) CheckContext(ctx PolicyContext) error
CheckContext implements ToolChecker for the static Policy. It delegates to Check, ignoring all context fields except ToolName.
type PolicyContext ¶
type PolicyContext struct {
Ctx context.Context
NodeID string
NodeKind string // "agent", "judge", "tool", etc.
ToolName string
Input json.RawMessage // nil when unavailable
Vars map[string]interface{} // workflow vars, read-only
}
PolicyContext carries evaluation context for dynamic policies.
Ctx is the caller's request context. Checkers that perform I/O (LLM classifiers, remote rule lookups) must honour it for cancellation and deadlines. A nil Ctx is treated as context.Background by the classifier wrapper for backward compatibility, but callers should always populate it.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry is a thread-safe store for tool definitions. It enforces unique qualified names and provides resolution by name.
func (*Registry) ListByOrigin ¶
func (r *Registry) ListByOrigin(kind OriginKind) []*ToolDef
ListByOrigin returns tools filtered by origin kind.
func (*Registry) ListByServer ¶
ListByServer returns tools from a specific MCP server.
func (*Registry) RegisterBuiltin ¶
func (r *Registry) RegisterBuiltin(name string, desc string, schema json.RawMessage, exec func(ctx context.Context, input json.RawMessage) (string, error)) error
RegisterBuiltin adds a built-in tool. The name must not contain dots. Returns an error if the name collides with an existing registration.
func (*Registry) RegisterMCP ¶
func (r *Registry) RegisterMCP(server, toolName, desc string, schema json.RawMessage, exec func(ctx context.Context, input json.RawMessage) (string, error)) error
RegisterMCP adds an MCP tool with the qualified name "mcp.<server>.<tool>". Both server and toolName must be non-empty and must not contain dots. Returns an error on collision.
func (*Registry) Resolve ¶
Resolve looks up a tool by its reference name. Resolution rules:
- Exact match on qualified name.
- If ref has no dots and there is exactly one MCP tool whose bare name matches, return it (convenience shorthand). If multiple MCP tools share the same bare name, return an ambiguity error.
Returns an error if the tool is not found or is ambiguous.
func (*Registry) ResolveAll ¶
ResolveAll resolves a list of tool references and returns the corresponding llmtypes.LLMTool slice. It stops at the first resolution error.
type Rule ¶
type Rule struct {
NodeIDs []string // nil = any node
NodeKind string // "" = any kind
VarMatch map[string]interface{} // nil = any vars
Allow []string // patterns to allow if this rule matches
Deny bool // if true, deny matched tools instead
}
Rule is a single conditional rule in a RulePolicy.
type RulePolicy ¶
type RulePolicy struct {
Rules []Rule
Fallback *Policy // nil = open (allow all if no rule matched)
}
RulePolicy evaluates an ordered list of conditional rules using first-match-wins semantics. If no rule matches, the Fallback policy is consulted. A nil Fallback means open (allow all).
func (*RulePolicy) CheckContext ¶
func (rp *RulePolicy) CheckContext(ctx PolicyContext) error
CheckContext implements ToolChecker.
type SubagentRunner ¶
SubagentRunner is the host-supplied closure invoked when the LLM calls the agent tool. It receives the validated input map, spawns a child LLM conversation (typically against the same model registry the parent uses), and returns the child's final result formatted as JSON. Returning a string + nil error treats the call as successful; any non-nil error is surfaced to the LLM as a tool error.
type ToolChecker ¶
type ToolChecker interface {
CheckContext(ctx PolicyContext) error
}
ToolChecker is the interface for contextual tool policy evaluation.
func BuildChecker ¶
func BuildChecker(workflowPatterns []string, nodeOverrides map[string][]string, varRules []VarRule) ToolChecker
BuildChecker constructs a ToolChecker from workflow-level patterns, optional per-node overrides, and optional var-conditional rules. Returns a simple *Policy when no overrides or rules are needed.
type ToolDef ¶
type ToolDef struct {
// QualifiedName is the unique key in the registry.
// Built-ins: "git_diff"
// MCP tools: "mcp.github.create_issue"
QualifiedName string
// Description explains what the tool does.
Description string
// InputSchema is the JSON Schema for the tool's input parameters.
InputSchema json.RawMessage
// Execute runs the tool with the given JSON input.
Execute func(ctx context.Context, input json.RawMessage) (string, error)
// Origin tracks where this tool came from.
Origin Origin
}
ToolDef is the registry's canonical tool representation. Both built-in and MCP tools are stored as ToolDefs.
func (*ToolDef) ToDelegateDef ¶
ToDelegateDef converts a ToolDef into a delegate.ToolDef, which is the execution contract consumed by the backend dispatch layer.
type ToolSnapshot ¶
ToolSnapshot returns the set of tools the model should see as the search haystack. Hosts pass a closure (instead of a static slice) so the snapshot is captured at execute time, after every other tool has been registered.