Documentation
¶
Overview ¶
Package tools: grep is a pure-Go recursive search over the workspace — no dependency on an external ripgrep/grep binary being installed, in keeping with Kram's "never crash / always works" goal. It costs some performance on very large trees versus a real ripgrep, which is an accepted v0 trade-off.
Package tools: LSP tools give the model real semantic navigation (diagnostics, go-to-definition, find-references) on top of the grep/glob/read_file tools, which find text but don't understand structure. Backed by internal/lsp, which lazily starts one language server per language the first time it's needed and reuses that connection afterward.
Package tools is the daemon's tool registry: the concrete capabilities (file I/O, search, shell) the agent loop can call, each scoped to a session's workspace directory so a tool call can never read or write outside the project it was invoked for.
Index ¶
- func WithApprover(ctx context.Context, a Approver) context.Context
- func WithAsker(ctx context.Context, a Asker) context.Context
- func WithDepth(ctx context.Context, depth int) context.Context
- type ApprovalDecision
- type Approver
- type Asker
- type Delegator
- type MetadataProvider
- type Registry
- func (r *Registry) AllTools() []ToolInfo
- func (r *Registry) Definitions() []openai.Tool
- func (r *Registry) Execute(ctx context.Context, name string, args json.RawMessage) (string, error)
- func (r *Registry) RegisterMCP(m *mcp.Manager)
- func (r *Registry) SetDelegator(d Delegator)
- func (r *Registry) Skills() []Skill
- func (r *Registry) StopBackgroundProcesses()
- func (r *Registry) StopLSPServers()
- func (r *Registry) ToolMetadata(name string) ToolMetadata
- type Skill
- type TodoItem
- type Tool
- type ToolInfo
- type ToolMetadata
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func WithApprover ¶
WithApprover attaches the approver for the current turn to ctx — called by agent.runLoop before executing tools, mirroring WithAsker.
func WithAsker ¶
WithAsker attaches the asker for the current turn to ctx — called by agent.runLoop before executing tools, mirroring WithDepth.
Types ¶
type ApprovalDecision ¶
type ApprovalDecision string
ApprovalDecision is the user's answer to a policy-gated tool call.
const ( ApprovalOnce ApprovalDecision = "once" ApprovalAlways ApprovalDecision = "always" ApprovalDeny ApprovalDecision = "deny" )
type Approver ¶
type Approver interface {
Approve(ctx context.Context, toolName, subject string) (ApprovalDecision, error)
}
Approver asks the user to sign off on a tool call the permission policy marked Ask — implemented by agent.Service, injected per-turn via context, same pattern ask.go's Asker uses. Deliberately a separate interface from Asker: ask_question means "I don't have enough information to proceed"; an approval means "I know exactly what I want to do, but policy requires sign-off first." Conflating the two would make a policy-driven pause look to the model (and the user) like the agent being unsure, which it isn't.
type Asker ¶
type Asker interface {
Ask(ctx context.Context, question string, options []string) (string, error)
}
Asker pauses the current turn to get a real answer from the user — implemented by agent.Service, injected per-call via context (the same pattern depth.go uses) rather than through Registry, since unlike delegation this needs the *current turn's* live event channel and session ID, not just a fixed dependency wired in once at startup.
type Delegator ¶
type Delegator interface {
RunTask(ctx context.Context, goal, taskContext, model string, depth int) (string, error)
}
Delegator runs one subtask to completion in a fresh, isolated child session and returns its final answer. Implemented by agent.Service; declared here (not imported from the agent package) because agent already depends on Registry for its own tool calls — agent importing tools importing agent would be a cycle. Registry.SetDelegator wires the concrete implementation in after both are constructed.
type MetadataProvider ¶ added in v0.2.2
type MetadataProvider interface {
ToolMetadata() ToolMetadata
}
MetadataProvider is implemented by a Tool that wants a hand-curated prompt summary instead of the automatic Description()-derived one.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry holds every tool available to the agent loop for one workspace.
func NewRegistry ¶
NewRegistry builds the default tool set scoped to workspace — every file and shell tool refuses to operate outside this directory. st, if non-nil, backs the memory_write/memory_search tools (cross-session memory, scoped to this workspace plus store.GlobalScope) and session_search (deterministic full-text search over real conversation history, a distinct concern from curated memory — see internal/daemon/store/search.go); passing nil omits those tools entirely rather than registering ones that would always fail. disabled names every tool (or skill — they share one namespace) turned off via the CLI's tools/skills screen; nil or empty means everything's on. Taking a plain map here rather than importing internal/toolsettings keeps this package from depending on the settings-storage format — daemon.go loads the store and passes its Disabled() map in.
func (*Registry) AllTools ¶
AllTools returns every registered tool (including disabled ones), name order, for the settings screen — Definitions() deliberately can't be reused here since it already filters disabled tools out.
func (*Registry) Definitions ¶
Definitions returns every *enabled* tool's definition in the gateway's wire format, ready to attach to a ChatCompletionRequest — a disabled tool is invisible to the model entirely, not just refused if called. A tool the permission policy denies unconditionally (see permission.Evaluator.FullyDenied) is hidden the same way: a capability the model can never successfully use shouldn't cost tokens in the tool schema. A tool denied only for *some* patterns stays visible, since it's still sometimes usable — the policy is enforced at call time either way.
func (*Registry) Execute ¶
Execute runs a named tool, or returns an error result (not a Go error) if the name is unknown, disabled, or blocked by permission policy — the agent loop feeds this text straight back to the model as the tool's result either way, so the model can see and recover from a bad or unavailable tool name itself. The disabled check here is defense in depth: Definitions() already keeps a disabled tool out of what's offered, but a model can still try to call a tool name it saw in an earlier turn before it was disabled.
Every tool call — built-in, custom (manifest), and MCP-backed alike — funnels through this one method, which is what makes them all subject to the same permission policy without each tool implementation needing to know policy exists.
func (*Registry) RegisterMCP ¶
RegisterMCP adds every tool from every connected MCP server to the registry, plus four generic tools covering resources and prompts (mcp_resource_list/read, mcp_prompt_list/get) — those aren't per-server-per-item like tools are (a server can expose an unbounded, changing set of resources), so they're cross-cutting tools that take a server name as an argument rather than one registered tool per item. Called after NewRegistry because connecting to servers is I/O that can block or fail, and the registry has to exist (and the daemon has to be able to start) either way.
func (*Registry) SetDelegator ¶
SetDelegator wires the concrete subagent runner into the registry's delegate_task tool, after both the registry and the agent.Service that implements Delegator exist — daemon.go calls this once during startup. Until it's called, delegate_task exists (the model can see it in tool definitions) but reports itself unavailable rather than being hidden, which would otherwise require rebuilding the registry after the agent service is constructed.
func (*Registry) Skills ¶
Skills lists every discovered skill (project + global), disabled state included — same purpose as AllTools but for skills, which aren't registered as one fixed Tool each the way built-ins are.
func (*Registry) StopBackgroundProcesses ¶
func (r *Registry) StopBackgroundProcesses()
StopBackgroundProcesses kills every process started by run_background — called on daemon shutdown so a background dev server doesn't outlive the daemon that started it as an orphan.
func (*Registry) StopLSPServers ¶
func (r *Registry) StopLSPServers()
StopLSPServers shuts down every language server this registry's LSP tools started, if any — called on daemon shutdown for the same reason as StopBackgroundProcesses: a language server is a subprocess Kram started, so it's Kram's job to make sure it doesn't outlive the daemon as an orphan. A workspace that never called an lsp_* tool never started any server, so this is a no-op in the common case.
func (*Registry) ToolMetadata ¶ added in v0.2.2
func (r *Registry) ToolMetadata(name string) ToolMetadata
ToolMetadata looks up name's hand-curated metadata, or derives a fallback from its Description() (first sentence only, to stay short — several Description()s run 3-5 sentences, appropriate for the wire schema but too long for a one-line prompt overview) if it doesn't implement MetadataProvider, isn't registered, or has an empty Summary. Never returns a value with an empty Summary for a registered tool — every tool gets *some* usable line.
type Skill ¶
type Skill struct {
Name string `json:"name"`
Description string `json:"description"`
Path string `json:"path"` // SKILL.md path, for error messages / the toggle UI
Scope string `json:"scope"` // "project" or "global"
Disabled bool `json:"disabled"` // set by Registry.Skills(), not discoverSkills itself
Body string `json:"-"` // everything after the frontmatter
}
Skill is one discovered skill: a folder containing a SKILL.md with a small frontmatter block (name, description) followed by the actual instructions as markdown. This is the same shape opencode's Agent Skills, Hermes Agent's agentskills.io-based skills, and OpenClaude's DiscoverSkillsTool all converge on — a lightweight open convention, not something Kram invented.
type TodoItem ¶
type TodoItem struct {
Content string `json:"content"`
Status string `json:"status"` // "pending", "in_progress", "completed"
}
TodoItem is one entry in the project's task list.
type Tool ¶
type Tool interface {
Name() string
Description() string
// Schema is the JSON Schema (as a raw object) describing the tool's
// arguments, passed straight through to the gateway/provider.
Schema() json.RawMessage
// Execute runs the tool and returns its result as text — every tool's
// output is text, even for structured data (JSON-encoded as a string),
// since that's what every provider's tool-result message expects.
Execute(ctx context.Context, args json.RawMessage) (string, error)
}
Tool is one callable capability the agent loop can offer the model.
type ToolInfo ¶
ToolInfo is one entry in the registry's full listing (AllTools) — every tool that exists, regardless of enabled state, for the CLI's tools/skills toggle screen.
type ToolMetadata ¶ added in v0.2.2
type ToolMetadata struct {
Summary string
// PreferOver names another tool this one should be reached for
// instead of, when relevant — e.g. run_background over bash for a
// dev server. Empty when there's no such competing default.
PreferOver string
}
ToolMetadata is a short, prompt-facing summary of a tool — distinct from and shorter than its Description() (which stays in full in the wire schema, for once the model has already selected the tool as a candidate and needs the complete picture). A tool with no hand-curated ToolMetadata still gets one via Registry.ToolMetadata's fallback — that's the point: a tool can't vanish from a generated overview just because nobody wrote a Summary for it yet, which is exactly the bug that motivated this (21 of 38 registered tools were never mentioned in the hand-maintained prompt prose — see DECISIONS.md).
Source Files
¶
- approval.go
- artifact_read.go
- ask.go
- background.go
- bash.go
- customtools.go
- delegate.go
- delete_file.go
- depth.go
- edit_file.go
- git.go
- glob.go
- grep.go
- ignore.go
- list_dir.go
- lsp.go
- mcp.go
- memory.go
- move_file.go
- outputfilter.go
- read_file.go
- session_search.go
- skillinstall.go
- skills.go
- snapshot.go
- spill.go
- todo.go
- toolmetadata.go
- tools.go
- web_fetch.go
- write_file.go