Documentation
¶
Overview ¶
Package ext provides the extension registration surface for piglet.
App is the central API through which all extensions — both compiled-in and external — register their capabilities. It supports five primitives:
- Inject: add text to the system prompt (App.RegisterPromptSection)
- React: respond to triggers (App.RegisterTool, App.RegisterCommand)
- Intercept: modify or block tool calls (App.RegisterInterceptor)
- Hook: process user messages before the LLM (App.RegisterMessageHook)
- Observe: react to lifecycle events (App.RegisterEventHandler)
Package ext provides the extension API for piglet. Extensions are plain functions that receive *App and register capabilities.
Index ¶
- Constants
- func BoolArg(args map[string]any, key string, fallback bool) bool
- func CompactWithCircuitBreaker(fn func(ctx context.Context, msgs []core.Message) ([]core.Message, error), ...) func(ctx context.Context, msgs []core.Message) ([]core.Message, error)
- func IntArg(args map[string]any, key string, fallback int) int
- func StringArg(args map[string]any, key string) string
- func TextResult(text string) *core.ToolResult
- type Action
- type ActionAttachImage
- type ActionDetachImage
- type ActionExec
- type ActionNotify
- type ActionQuit
- type ActionRunAsync
- type ActionSendMessage
- type ActionSetSessionTitle
- type ActionSetStatus
- type ActionShowMessage
- type ActionShowPicker
- type ActionSwapSession
- type AgentAPI
- type AgentReader
- type AgentWriter
- type App
- func (a *App) AvailableModels() []core.Model
- func (a *App) BackgroundSafeTools() []core.Tool
- func (a *App) Bind(agent AgentAPI, opts ...BindOption)
- func (a *App) CWD() string
- func (a *App) CancelBackground()
- func (a *App) Commands() map[string]*Command
- func (a *App) Compactor() *Compactor
- func (a *App) ConversationMessages() []core.Message
- func (a *App) CoreTools() []core.Tool
- func (a *App) DispatchEvent(ctx context.Context, evt core.Event)
- func (a *App) EnqueueAction(action Action)
- func (a *App) ExtInfos() []ExtInfo
- func (a *App) FindTool(name string) *core.Tool
- func (a *App) ForkSession() (string, int, error)
- func (a *App) IsBackgroundRunning() bool
- func (a *App) LoadSession(path string) error
- func (a *App) Notify(msg string)
- func (a *App) PendingActions() []Action
- func (a *App) PromptSections() []PromptSection
- func (a *App) Provider() core.StreamProvider
- func (a *App) Providers() map[string]*ProviderConfig
- func (a *App) RegisterCommand(c *Command)
- func (a *App) RegisterCompactor(c Compactor)
- func (a *App) RegisterEventHandler(h EventHandler)
- func (a *App) RegisterExtInfo(info ExtInfo)
- func (a *App) RegisterInterceptor(i Interceptor)
- func (a *App) RegisterMessageHook(h MessageHook)
- func (a *App) RegisterPromptSection(s PromptSection)
- func (a *App) RegisterProvider(name string, cfg *ProviderConfig)
- func (a *App) RegisterRenderer(typ string, r Renderer)
- func (a *App) RegisterShortcut(s *Shortcut)
- func (a *App) RegisterStatusSection(s StatusSection)
- func (a *App) RegisterStreamProvider(api string, factory StreamProviderFactory)
- func (a *App) RegisterTool(t *ToolDef)
- func (a *App) Renderers() map[string]Renderer
- func (a *App) RequestQuit()
- func (a *App) ResolveModel(id string) (core.Model, core.StreamProvider, error)
- func (a *App) RunBackground(prompt string) error
- func (a *App) RunMessageHooks(ctx context.Context, msg string) ([]string, error)
- func (a *App) SendMessage(content string)
- func (a *App) SessionTitle() string
- func (a *App) Sessions() ([]SessionSummary, error)
- func (a *App) SetConversationMessages(msgs []core.Message)
- func (a *App) SetModel(m core.Model)
- func (a *App) SetProvider(p core.StreamProvider)
- func (a *App) SetSessionTitle(title string) error
- func (a *App) SetStatus(key, text string)
- func (a *App) Shortcuts() map[string]*Shortcut
- func (a *App) ShowMessage(text string)
- func (a *App) ShowPicker(title string, items []PickerItem, onSelect func(PickerItem))
- func (a *App) StatusSections() []StatusSection
- func (a *App) Steer(content string)
- func (a *App) StreamProvider(api string, model core.Model) (core.StreamProvider, bool)
- func (a *App) SwitchModel(id string) error
- func (a *App) SyncModels() (int, error)
- func (a *App) SystemPrompt() string
- func (a *App) ToggleStepMode() bool
- func (a *App) ToolDefs() []*ToolDef
- func (a *App) Tools() []string
- func (a *App) UnregisterExtension(name string)
- type BindOption
- type Command
- type Compactor
- type EventHandler
- type ExtInfo
- type Extension
- type Interceptor
- type InterruptBehavior
- type MessageHook
- type ModelManager
- type PickerItem
- type PromptSection
- type ProviderConfig
- type Renderer
- type SessionManager
- type SessionSummary
- type Shortcut
- type StatusSection
- type StatusSide
- type StreamProviderFactory
- type ToolDef
Constants ¶
const ( StatusKeyApp = "app" StatusKeyModel = "model" StatusKeyMouse = "mouse" StatusKeyBg = "bg" StatusKeyTokens = "tokens" StatusKeyCost = "cost" StatusKeyQueue = "queue" StatusKeyPromptBudget = "prompt-budget" )
Built-in status section keys.
Variables ¶
This section is empty.
Functions ¶
func CompactWithCircuitBreaker ¶ added in v0.17.0
func CompactWithCircuitBreaker( fn func(ctx context.Context, msgs []core.Message) ([]core.Message, error), maxFails int, cooldown time.Duration, ) func(ctx context.Context, msgs []core.Message) ([]core.Message, error)
CompactWithCircuitBreaker wraps a compact function with retry protection. After maxFails consecutive failures, compaction is disabled for cooldown duration.
func IntArg ¶ added in v0.5.0
IntArg extracts an integer argument from a tool call's args map. JSON numbers decode as float64, so both float64 and int are handled.
func TextResult ¶ added in v0.5.0
func TextResult(text string) *core.ToolResult
TextResult builds a ToolResult containing a single text block.
Types ¶
type Action ¶ added in v0.4.0
type Action interface {
// contains filtered or unexported methods
}
Action represents an intent requested by an extension command or shortcut. Commands enqueue actions; the TUI drains and applies them after the handler returns.
type ActionAttachImage ¶ added in v0.5.0
type ActionAttachImage struct{ Image any }
ActionAttachImage attaches an image to the next message. Image is typed as any to avoid importing core.ImageContent.
type ActionDetachImage ¶ added in v0.5.0
type ActionDetachImage struct{}
ActionDetachImage removes a pending image attachment.
type ActionExec ¶ added in v0.5.0
type ActionExec struct{ Cmd any }
ActionExec hands the terminal to an external process (e.g., $EDITOR). Cmd is typed as any to avoid importing os/exec from ext/. The TUI asserts *exec.Cmd and uses tea.ExecProcess.
type ActionNotify ¶ added in v0.4.0
type ActionNotify struct{ Message string }
ActionNotify sends a transient notification.
type ActionRunAsync ¶ added in v0.5.0
type ActionRunAsync struct{ Fn func() Action }
ActionRunAsync runs Fn in a goroutine. The returned Action (if non-nil) is enqueued when Fn completes. Use for expensive event handler work.
type ActionSendMessage ¶ added in v0.16.8
type ActionSendMessage struct{ Content string }
ActionSendMessage injects a user message into the agent loop.
type ActionSetSessionTitle ¶ added in v0.5.0
type ActionSetSessionTitle struct{ Title string }
ActionSetSessionTitle sets the current session's title.
type ActionSetStatus ¶ added in v0.4.0
type ActionSetStatus struct{ Key, Text string }
ActionSetStatus updates a status bar widget (e.g. "model").
type ActionShowMessage ¶ added in v0.4.0
type ActionShowMessage struct{ Text string }
ActionShowMessage displays a message in the conversation view.
type ActionShowPicker ¶ added in v0.4.0
type ActionShowPicker struct {
Title string
Items []PickerItem
OnSelect func(PickerItem)
}
ActionShowPicker opens a modal picker.
type ActionSwapSession ¶ added in v0.4.0
type ActionSwapSession struct{ Session any }
ActionSwapSession replaces the active session. Session is typed as any to avoid importing session/ from ext/.
type AgentAPI ¶
type AgentAPI interface {
AgentReader
AgentWriter
}
AgentAPI is the subset of *core.Agent that the extension runtime needs. Using an interface keeps ext/ from depending on agent implementation details.
Removed from interface (used only via *core.Agent in tui/ and cmd/):
- SetTools, SetTurnContext, IsRunning
type AgentReader ¶ added in v0.16.8
type AgentReader interface {
Messages() []core.Message
StepMode() bool
Provider() core.StreamProvider
System() string
}
AgentReader provides read-only access to agent state.
type AgentWriter ¶ added in v0.16.8
type AgentWriter interface {
Steer(msg core.Message)
FollowUp(msg core.Message)
SetModel(m core.Model)
SetProvider(p core.StreamProvider)
SetMessages(msgs []core.Message)
SetStepMode(on bool)
}
AgentWriter provides mutation access to the agent.
type App ¶
type App struct {
// contains filtered or unexported fields
}
App is the single extension API surface. Extensions receive this in their factory function and call methods to register tools, commands, etc.
After registration, Bind() wires the runtime references (agent, session) so runtime methods like SendMessage() and Model() work.
CAPABILITY GATE — before adding a new callback or field to App, answer:
- Can this be a Tool? → RegisterTool (agent-callable action)
- Can this be a Command? → RegisterCommand (user-invoked /slash)
- Can this be a Shortcut? → RegisterShortcut (keyboard binding)
- Can this be a PromptSection? → RegisterPromptSection (system prompt injection)
- Can this be an Interceptor? → RegisterInterceptor (before/after tool hook)
- Can this be a MessageHook? → RegisterMessageHook (before user message reaches LLM)
Only add a new BindOption/callback when NONE of the above apply — typically for TUI-specific lifecycle that extensions cannot express through existing primitives (e.g. session swapping, background agent management). See ext/architecture_test.go for automated boundary enforcement.
func (*App) AvailableModels ¶ added in v0.4.0
AvailableModels returns all registered models.
func (*App) BackgroundSafeTools ¶ added in v0.4.0
BackgroundSafeTools returns core.Tool slice filtered to tools marked BackgroundSafe.
func (*App) Bind ¶
func (a *App) Bind(agent AgentAPI, opts ...BindOption)
Bind wires the runtime references after the agent and session are created. Must be called before runtime methods (SendMessage, Model, etc.) are used.
func (*App) CancelBackground ¶ added in v0.4.0
func (a *App) CancelBackground()
CancelBackground stops the running background agent. No-op if not bound or not running.
func (*App) ConversationMessages ¶
ConversationMessages returns a snapshot of the conversation history.
func (*App) CoreTools ¶
CoreTools converts registered ToolDefs into core.Tool slice for the agent. Wraps each tool's Execute with the interceptor chain.
func (*App) DispatchEvent ¶ added in v0.5.0
DispatchEvent sends an agent event to all registered event handlers. Called by the TUI or runPrint as events are drained from the agent channel. Handlers run synchronously in priority order. Returned actions are enqueued.
func (*App) EnqueueAction ¶ added in v0.5.0
EnqueueAction adds an action to the pending queue. Used by the TUI to re-enqueue results from ActionRunAsync.
func (*App) FindTool ¶ added in v0.5.0
FindTool looks up a tool by name and returns a core.Tool with interceptors applied. Returns nil if no tool with that name is registered.
func (*App) ForkSession ¶ added in v0.4.0
ForkSession forks the current session into a new branch.
func (*App) IsBackgroundRunning ¶ added in v0.4.0
IsBackgroundRunning returns whether a background agent is currently active.
func (*App) LoadSession ¶ added in v0.4.0
LoadSession opens a session by path and enqueues a swap.
func (*App) PendingActions ¶ added in v0.4.0
PendingActions returns and clears all queued actions.
func (*App) PromptSections ¶
func (a *App) PromptSections() []PromptSection
PromptSections returns all registered prompt sections, sorted by order.
func (*App) Provider ¶ added in v0.5.0
func (a *App) Provider() core.StreamProvider
Provider returns the current agent's streaming provider.
func (*App) Providers ¶
func (a *App) Providers() map[string]*ProviderConfig
Providers returns all registered provider configs.
func (*App) RegisterCommand ¶
RegisterCommand adds a slash command.
func (*App) RegisterCompactor ¶ added in v0.5.0
RegisterCompactor sets the conversation compactor. Only one compactor is active at a time (last-write-wins).
func (*App) RegisterEventHandler ¶ added in v0.5.0
func (a *App) RegisterEventHandler(h EventHandler)
RegisterEventHandler adds a handler that reacts to agent lifecycle events. Sorted by priority ascending (lower = earlier).
func (*App) RegisterExtInfo ¶ added in v0.2.0
RegisterExtInfo records metadata about a loaded extension.
func (*App) RegisterInterceptor ¶
func (a *App) RegisterInterceptor(i Interceptor)
RegisterInterceptor adds a tool interceptor. Sorted by priority descending.
func (*App) RegisterMessageHook ¶ added in v0.5.0
func (a *App) RegisterMessageHook(h MessageHook)
RegisterMessageHook adds a hook that runs before user messages reach the LLM. Sorted by priority ascending (lower = earlier).
func (*App) RegisterPromptSection ¶
func (a *App) RegisterPromptSection(s PromptSection)
RegisterPromptSection adds a section to the system prompt.
func (*App) RegisterProvider ¶
func (a *App) RegisterProvider(name string, cfg *ProviderConfig)
RegisterProvider adds a custom LLM provider.
func (*App) RegisterRenderer ¶
RegisterRenderer adds a custom message type renderer.
func (*App) RegisterShortcut ¶
RegisterShortcut adds a keyboard shortcut.
func (*App) RegisterStatusSection ¶ added in v0.5.0
func (a *App) RegisterStatusSection(s StatusSection)
RegisterStatusSection adds a status bar section. Overwrites if a section with the same key already exists.
func (*App) RegisterStreamProvider ¶ added in v0.16.11
func (a *App) RegisterStreamProvider(api string, factory StreamProviderFactory)
RegisterStreamProvider registers a factory that creates StreamProviders for the given API type.
func (*App) RegisterTool ¶
RegisterTool adds a tool. Overwrites if name already exists.
func (*App) ResolveModel ¶ added in v0.5.0
ResolveModel returns a model and configured provider for the given model ID without switching the main agent. Used by sub-agents to run on different models.
func (*App) RunBackground ¶ added in v0.4.0
RunBackground starts a background agent with the given prompt. Returns an error if not bound or if a background agent is already running.
func (*App) RunMessageHooks ¶ added in v0.5.0
RunMessageHooks executes all message hooks in priority order. Returns collected non-empty context strings for ephemeral injection.
func (*App) SendMessage ¶
SendMessage enqueues an ActionSendMessage that the TUI will pick up and feed into the agent loop as a follow-up user message.
func (*App) SessionTitle ¶ added in v0.5.0
SessionTitle returns the current session's title (empty if not set).
func (*App) Sessions ¶ added in v0.4.0
func (a *App) Sessions() ([]SessionSummary, error)
Sessions returns all sessions, newest first.
func (*App) SetConversationMessages ¶
SetConversationMessages replaces the conversation history.
func (*App) SetProvider ¶ added in v0.3.0
func (a *App) SetProvider(p core.StreamProvider)
SetProvider swaps the agent's streaming provider.
func (*App) SetSessionTitle ¶ added in v0.4.0
SetSessionTitle updates the current session's title.
func (*App) ShowMessage ¶
ShowMessage displays a message in the TUI.
func (*App) ShowPicker ¶
func (a *App) ShowPicker(title string, items []PickerItem, onSelect func(PickerItem))
ShowPicker shows a picker/modal in the TUI.
func (*App) StatusSections ¶ added in v0.5.0
func (a *App) StatusSections() []StatusSection
StatusSections returns all registered status sections.
func (*App) StreamProvider ¶ added in v0.16.11
StreamProvider returns a provider for the given API type and model, if a factory is registered.
func (*App) SwitchModel ¶ added in v0.4.0
SwitchModel activates a model by its "provider/id" key. Updates the agent's model and provider, and enqueues a status update.
func (*App) SyncModels ¶ added in v0.4.0
SyncModels updates the model catalog from an external source.
func (*App) SystemPrompt ¶ added in v0.5.0
SystemPrompt returns the current agent's system prompt.
func (*App) ToggleStepMode ¶
ToggleStepMode toggles step mode and returns the new state.
func (*App) UnregisterExtension ¶ added in v0.16.11
UnregisterExtension removes all registrations associated with the named extension. Used by the supervisor when restarting a crashed extension process.
type BindOption ¶
type BindOption func(*App)
BindOption configures optional runtime callbacks for sync operations that cannot be expressed as fire-and-forget actions.
func WithCancelBackground ¶ added in v0.4.0
func WithCancelBackground(fn func()) BindOption
WithCancelBackground sets the callback to cancel the running background agent.
func WithIsBackgroundRunning ¶ added in v0.4.0
func WithIsBackgroundRunning(fn func() bool) BindOption
WithIsBackgroundRunning sets the callback to check if a background agent is active.
func WithModelManager ¶ added in v0.4.0
func WithModelManager(mm ModelManager) BindOption
WithModelManager binds the model manager.
func WithRunBackground ¶ added in v0.4.0
func WithRunBackground(fn func(prompt string) error) BindOption
WithRunBackground sets the callback to start a background agent.
func WithSessionManager ¶ added in v0.4.0
func WithSessionManager(sm SessionManager) BindOption
WithSessionManager binds the session manager.
type Command ¶
type Command struct {
Name string
Description string
Handler func(args string, app *App) error
Complete func(prefix string) []string // tab completion; nil = no completion
Immediate bool // if true, executes during streaming without queuing
}
Command is a slash command registered by an extension.
type Compactor ¶ added in v0.5.0
type Compactor struct {
Name string
Threshold int // token threshold for auto-compact; 0 = use config default
Compact func(ctx context.Context, messages []core.Message) ([]core.Message, error)
}
Compactor controls conversation compaction (summarization to save tokens). Register one via App.RegisterCompactor. The Compact function receives all messages and returns the compacted set — giving full control over what to keep and how to summarize.
type EventHandler ¶ added in v0.5.0
type EventHandler struct {
Name string
Priority int
// Filter limits which events this handler sees. nil = all events.
Filter func(core.Event) bool
// Handle processes the event. Returns an optional Action to enqueue.
// Return nil for no action.
Handle func(ctx context.Context, evt core.Event) Action
}
EventHandler reacts to agent lifecycle events (Observe primitive). Lower priority runs first. Handle must be fast (<50ms) — return ActionRunAsync for expensive work.
type ExtInfo ¶ added in v0.2.0
type ExtInfo struct {
Name string // human-readable name
Version string // semver or empty
Kind string // "builtin" or "external"
Runtime string // "go", "bun", "node", "python", etc.
Tools []string // tool names registered by this extension
Commands []string // command names registered by this extension
Interceptors []string // interceptor names
EventHandlers []string // event handler names
Shortcuts []string // shortcut keys
MessageHooks []string // message hook names
Compactor string // compactor name, empty if none
PromptSections []string // prompt section titles
StreamProviders []string // stream provider API types (e.g. "openai")
}
ExtInfo describes a loaded extension for /extensions listing.
type Extension ¶
Extension is a function that registers tools, commands, interceptors, etc. Built-in tools and external extensions use the same signature.
type Interceptor ¶
type Interceptor struct {
Name string
Priority int
// Before is called before tool execution.
// Return allow=false to block the tool call.
// Return modified args to transform input.
Before func(ctx context.Context, toolName string, args map[string]any) (allow bool, modifiedArgs map[string]any, err error)
// After is called after tool execution.
// Return modified result to transform output.
After func(ctx context.Context, toolName string, result any) (any, error)
}
Interceptor wraps tool execution with before/after hooks. Higher priority runs first. Use priority 2000+ for security, 1000+ for logging.
type InterruptBehavior ¶ added in v0.17.0
type InterruptBehavior int
InterruptBehavior controls how a tool reacts to steering (mid-turn user input).
const ( // InterruptCancel cancels the tool on steer and discards its result (default). InterruptCancel InterruptBehavior = iota // InterruptBlock keeps the tool running when steered; the steer is queued // for after the tool completes. InterruptBlock )
type MessageHook ¶ added in v0.5.0
type MessageHook struct {
Name string
Priority int
// OnMessage sees the user message before the LLM call.
// Returns additional context to inject for this turn only (ephemeral).
// Empty string = no injection. Error = abort the message.
OnMessage func(ctx context.Context, msg string) (string, error)
}
MessageHook runs before a user message is sent to the LLM. Lower priority runs first (same convention as prompt sections).
type ModelManager ¶ added in v0.4.0
type ModelManager interface {
// Available returns all registered models.
Available() []core.Model
// Switch activates a model by its "provider/id" key.
// Returns the model and a configured streaming provider.
// The implementation handles provider creation and auth.
Switch(id string) (core.Model, core.StreamProvider, error)
// Sync updates the model catalog from an external source (e.g. models.dev).
// Returns the number of models updated.
Sync() (updated int, err error)
}
ModelManager provides model operations to commands and extensions. Implemented by the wiring layer which imports provider/ and config/.
type PickerItem ¶
PickerItem is an item in a picker/modal list. Used by commands to request a selection UI from the TUI.
type PromptSection ¶
type PromptSection struct {
Title string // section heading (e.g. "Code Style")
Content string // markdown content
Order int // lower = earlier in prompt; default 0
TokenHint int // estimated token count; 0 = unknown
}
PromptSection is a block of text injected into the system prompt. Extensions use this to add instructions, guidelines, or context.
type ProviderConfig ¶
type ProviderConfig struct {
BaseURL string
APIKey string
API core.API
Models []core.Model
Headers map[string]string
}
ProviderConfig registers a custom LLM provider from an extension.
type Renderer ¶
Renderer renders a custom message type for display. expanded controls whether the message is shown in full or collapsed.
type SessionManager ¶ added in v0.4.0
type SessionManager interface {
// List returns all sessions, newest first.
List() ([]SessionSummary, error)
// Load opens a session by path.
// Returns an opaque session handle for ActionSwapSession.
Load(path string) (any, error)
// Fork creates a branch of the current session.
// Returns the parent short ID, forked session handle, message count, and any error.
Fork() (parentID string, forked any, count int, err error)
// SetTitle updates the current session's title.
SetTitle(title string) error
// Title returns the current session's title (empty if not set).
Title() string
}
SessionManager provides session operations to commands and extensions. Implemented by the wiring layer (main.go/tui) which imports session/.
type SessionSummary ¶ added in v0.4.0
type SessionSummary struct {
ID string
Path string
Title string
Model string
CWD string
CreatedAt time.Time
Messages int
ParentID string
}
SessionSummary is the ext-layer view of a session. Mirrors session.Summary without importing session/.
type Shortcut ¶
type Shortcut struct {
Key string // e.g. "ctrl+g"
Description string
Handler func(app *App) (Action, error)
}
Shortcut is a keyboard shortcut registered by an extension.
type StatusSection ¶ added in v0.5.0
type StatusSection struct {
Key string // unique key (e.g. "model", "tokens", "cost")
Side StatusSide // left or right side of status bar
Order int // lower = rendered first within the side
}
StatusSection defines an extensible status bar segment. Register via App.RegisterStatusSection. The TUI renders all registered sections sorted by Order within each side (left/right).
type StatusSide ¶ added in v0.5.0
type StatusSide int
StatusSide determines which side of the status bar a section appears on.
const ( StatusLeft StatusSide = iota StatusRight )
type StreamProviderFactory ¶ added in v0.16.11
type StreamProviderFactory func(model core.Model) core.StreamProvider
StreamProviderFactory creates a StreamProvider configured for a specific model. Registered per API type; called each time the agent selects a model served by that API.
type ToolDef ¶
type ToolDef struct {
core.ToolSchema
// Execute runs the tool. Same signature as core.ToolExecuteFn.
Execute func(ctx context.Context, id string, args map[string]any) (*core.ToolResult, error)
// PromptHint is a one-liner injected into the system prompt.
// Example: "Read file contents with line numbers"
PromptHint string
// PromptGuides are bullets injected into the system prompt guidelines.
// Example: ["Use offset/limit for files >2000 lines", "Prefer grep to find content"]
PromptGuides []string
// BackgroundSafe marks this tool as safe for background agent use (read-only).
BackgroundSafe bool
// ConcurrencySafe returns true if this tool call is safe to run concurrently
// with other tool calls. Return false for destructive/mutating operations.
// nil means always safe (default: parallel execution).
ConcurrencySafe func(args map[string]any) bool
// InterruptBehavior controls how this tool reacts to steering.
// InterruptBlock keeps the tool running; InterruptCancel (default) cancels it.
InterruptBehavior InterruptBehavior
// Deferred marks this tool as rarely used. Only name+description sent in API schemas.
// Full schema available via tool_search.
Deferred bool
}
ToolDef extends core.ToolSchema with execution and optional UI rendering.