Creating a Custom Tool
To create a tool, you need to implement theagents.Tool interface:
The hastekit.NewTool Helper
If you don’t need the full control of agents.BaseTool, hastekit.NewTool turns any
func(ctx, In) (Out, error) into a tool. The input JSON schema is derived from the
argument struct, and arguments/results are marshalled for you:
Both
agents.BaseTool-based tools and hastekit.NewTool tools implement
hastekit.Tool and can be mixed into the same Tools slice.
Tool Annotations
Tools can advertise what they do. The hints mirror MCP’s tool annotations, so hints read off an MCP server and hints declared on a local function tool are the same thing — one policy can read both.agents.BaseTool-based tool, set the Annotations field directly:
Reading the hints back
AnnotationsOf returns nil for a tool that carries none, and the nil is usable: every Is* helper is nil-safe.
Every hint is a pointer, so “nothing was said” stays distinguishable from “false was said”. Prefer the
Is* helpers over reading the fields directly: they are nil-safe and apply MCP’s defaults, which are deliberately conservative — an unset DestructiveHint reads as destructive, an unset ReadOnlyHint as not read-only. A read-only tool is never destructive and is always idempotent, whatever those hints say.
IsDeclaredDestructive() is the variant that asks whether the tool actually said it may destroy state, rather than assuming the worst when nothing was said. It is usually the one a hook gating tool calls wants: an unannotated tool has made no claim, and gating on the absence of a claim would put every tool written before annotations behind a prompt.
Reporting Progress
A long-running tool can emit progress updates that stream to the client on the same channel as the rest of the run. Callparams.ReportProgress — it is nil-safe, so tools can call it unconditionally regardless of which runtime is executing them:
tool.progress chunks:
Progress should increase monotonically across a call; Total is optional (0 means unknown). The shape mirrors MCP’s notifications/progress, so MCP tools map their server-sent progress onto the same chunks.