Browse documentation
Add a custom tool
Define a model-callable operation, validate its input, use runtime context, and return a supported result.
View MarkdownUse a custom tool when the agent needs executable behavior that is not provided by the built-in file and terminal tools.
Complete example
Create .pi/extensions/customer-tools.mjs:
export default function customerTools(pi) {
pi.registerTool({
name: 'lookup_customer',
label: 'Look up customer',
description: 'Look up a customer using their stable customer ID.',
parameters: {
type: 'object',
properties: {
customerId: {
type: 'string',
description: 'Stable customer identifier.',
},
},
required: ['customerId'],
additionalProperties: false,
},
async execute(_toolCallId, { customerId }, _signal, _onUpdate, ctx) {
const source = ctx.external?.provider ?? 'api';
return {
content: [
{
type: 'text',
text: `Customer ${customerId} requested from ${source}.`,
},
],
details: {
customerId,
source,
},
};
},
});
}Registration fields
| Field | Requirement |
|---|---|
name | 1–64 letters, numbers, underscores, or hyphens |
label | Optional human-readable label |
description | Required explanation used by the model |
parameters | Required JSON-Schema-like object |
execute | Async function called in the sandbox extension host |
Write descriptions that explain when to use the tool. Keep the schema narrow and reject unexpected fields with additionalProperties: false.
Execution arguments
async execute(toolCallId, params, signal, onUpdate, ctx) {
// ...
}| Argument | Hosted behavior |
|---|---|
toolCallId | Stable identifier for this tool invocation |
params | Model arguments validated against the declared schema |
signal | Reserved by the hosted contract; currently may be undefined |
onUpdate | Reserved for progress updates; currently may be undefined |
ctx | Bounded runtime context, including ctx.external |
Do not depend on signal or onUpdate until their hosted behavior is documented as supported.
Return a result
Every successful execution returns:
return {
content: [{ type: "text", text: "Result visible to the model" }],
details: { optional: "structured diagnostic data" },
};Hosted custom tools return text content only.
Failure behavior
Throw an Error with a concise, non-secret message when execution cannot complete:
throw new Error('Customer record was not found.');Tool execution is bounded to 10 minutes. Do not return credentials, raw provider responses containing secrets, or unbounded payloads.
Validate with salambo manifest, then use a real deploy and smoke test.