Browse documentation
React to lifecycle events
Adapt prompts, tools, model behavior, and results with supported hosted hooks.
View MarkdownUse pi.on(eventName, handler) when behavior belongs around the agent lifecycle rather than inside a model-callable tool.
Make Slack responses concise
export default function channelBehavior(pi) {
pi.on('before_agent_start', (event, ctx) => {
if (ctx.external?.provider !== 'slack') {
return;
}
return {
systemPrompt: `${event.systemPrompt}\n\nFor Slack, keep the response concise and easy to scan.`,
};
});
}All hosted handlers receive (event, ctx). event depends on the hook. ctx.external contains bounded integration metadata or null.
Select tools for a turn
Call runtime-changing methods inside a handler, not at module discovery time:
export default function toolPolicy(pi) {
pi.on('before_agent_start', async (_event, ctx) => {
if (ctx.external?.conversationType === 'channel') {
await pi.setActiveTools(['read', 'bash', 'lookup_customer']);
}
});
}The requested names must belong to the deployment's allowed tool set. Salambo restores the selected tools on durable follow-up turns.
Block a tool call
pi.on('tool_call', (event) => {
if (
event.toolName === 'bash' &&
typeof event.input.command === 'string' &&
event.input.command.includes('rm -rf')
) {
return {
block: true,
reason: 'Destructive recursive deletion is not allowed.',
};
}
});tool_call handlers may block a call. They may also mutate event.input in place; later handlers and execution receive the resulting input.
Annotate a tool result
pi.on('tool_result', (event) => {
if (event.toolName !== 'lookup_customer' || event.isError) {
return;
}
return {
details: {
...event.details,
reviewedBy: 'customer-policy-extension',
},
};
});Choose a hook deliberately
| Goal | Hook |
|---|---|
| Modify the prompt or select model/tools | before_agent_start |
| Allow or block a tool call | tool_call |
| Transform a tool result | tool_result |
| Transform model context messages | context |
| Adjust provider stream options | before_provider_request |
| Inspect or replace provider payload | before_provider_payload |
| Observe provider response metadata | after_provider_response |
| Participate in compaction | session_before_compact, session_compact |
| Observe model or thinking changes | model_update, thinking_level_update |
Hooks are bounded to 10 seconds. A timeout, thrown error, or invalid result fails the active extension operation rather than silently ignoring it.
See the authoritative hook event reference for every supported event and return contract.