Skip to content

Override Capability Tool Definitions

Capabilities like memory, workflow, and A2A register their tools with hard-coded descriptors (description, input/output schema). When you need to customize those — for example, to add a domain-specific parameter that downstream consumers rely on — you don’t need to fork PromptKit. Use WithToolDescriptorOverride to patch the descriptor after the capability registers it.

  • The default tool description doesn’t fit your deployment’s wording or policy.
  • You need to add or constrain an input parameter (e.g. an enum validating allowed values).
  • You want to relabel the namespace or augment the output schema.
  • Consumer code (Omnia, internal services) reads a non-standard parameter and the LLM should know to set it.
import (
"github.com/AltairaLabs/PromptKit/runtime/memory"
"github.com/AltairaLabs/PromptKit/runtime/tools"
"github.com/AltairaLabs/PromptKit/sdk"
)
conv, err := sdk.Open(packPath, "chat",
sdk.WithMemory(store, scope),
sdk.WithToolDescriptorOverride(memory.RememberToolName,
func(d *tools.ToolDescriptor) {
d.Description = "Store something in memory; tag it with a category."
}),
)

The patch function receives a clone of the descriptor that the capability registered. Mutate fields in place; the SDK re-registers the patched descriptor before the first Send().

import "encoding/json"
categorySchema := json.RawMessage(`{
"type": "object",
"properties": {
"content": {"type": "string"},
"category": {
"type": "string",
"enum": ["memory:health", "memory:identity", "memory:preferences"]
}
},
"required": ["content", "category"]
}`)
sdk.WithToolDescriptorOverride(memory.RememberToolName,
func(d *tools.ToolDescriptor) {
d.InputSchema = categorySchema
})

Multiple overrides for the same tool compose in registration order — the second sees the descriptor already mutated by the first:

sdk.WithToolDescriptorOverride("memory__remember",
func(d *tools.ToolDescriptor) { d.Description = "step 1" }),
sdk.WithToolDescriptorOverride("memory__remember",
func(d *tools.ToolDescriptor) { d.Description += " | step 2" }),
// Final description: "step 1 | step 2"

If you reference a tool name that doesn’t exist in the registry (for example, a tool that was renamed or removed in a newer PromptKit release), the override is logged at WARN level and skipped. Other overrides still apply. This means override lists survive PromptKit upgrades without breaking the consumer build.

WithToolDescriptorOverride does not subvert the capability — the capability still registers its tools with their defaults. Once all capabilities have run RegisterTools, the SDK iterates the configured overrides and:

  1. Looks up each tool by name in the registry. If absent, logs and skips.
  2. Clones the descriptor (so mutations don’t leak into shared registry state).
  3. Calls the patch function on the clone.
  4. Re-registers the patched descriptor (Registry.Register is last-write-wins, so this replaces the original).
  • The executor that handles the tool. The executor remains the one the capability registered. If you need the executor to recognise a new parameter, you must change the capability code (or wrap the capability with your own).
  • Other tools — patches operate on a clone of one descriptor.
  • Capability lifecycle (Init, Close).