Skip to content

RFC: pi-embedded plugin tool-event subscription \u2014 stable seam for tool-call observation #71427

Description

@100yenadmin

Problem statement

Plugins that need to observe tool execution events (tool start/end/persist, with the agent context) currently have to patch src/agents/pi-embedded-subscribe.handlers.tools.ts to add a hook callout. The file is the host's tool-execution dispatcher; modifying it requires re-baselining on every host version that touches it.

Smarter-Claw maintains installer/patches/core/pi-embedded-subscribe-exit-plan-mode-emit.diff for this exact purpose — to wire plan-mode tool emission events to the plugin so it can persist plan archetype markdown, drain injection queues, etc.

Proposed change

Add before_tool_call_persist and after_tool_call_persist lifecycle events to the plugin SDK, callable via the existing api.on(...) pattern.

SDK contract (additive)

// In existing plugin-sdk/lifecycle types
export type ToolCallPersistEvent = {
  sessionKey: string;
  agentId: string;
  toolName: string;
  toolCallId: string;
  toolInput: unknown;     // raw tool input
  toolResult: unknown;    // raw tool output (after_ only)
  messageId: string;      // upstream message id
};

// Plugins subscribe:
api.on("before_tool_call_persist", async (event: ToolCallPersistEvent) => {
  // observe; return modifications via api.runtime.* if needed
});
api.on("after_tool_call_persist", async (event: ToolCallPersistEvent) => {
  // observe persisted result
});

Host dispatch (gateway-side, ~30 LOC)

In the existing pi-embedded-subscribe.handlers.tools.ts:persistToolCall flow:

await pluginRegistry.dispatch("before_tool_call_persist", { sessionKey, agentId, toolName, ... });
const persisted = await persistToolResult(...);
await pluginRegistry.dispatch("after_tool_call_persist", { sessionKey, agentId, toolName, toolResult: persisted, ... });

Backward compatibility

Fully additive. Existing plugins that don't subscribe see no change.

What this saves Smarter-Claw

  • Delete installer/patches/core/pi-embedded-subscribe-exit-plan-mode-emit.diff (~80 LOC)
  • Move tool-event subscription out of host patch into typed plugin code
  • Eliminate version-bump fragility for this seam

The two events together cover the same surface area as our current patch (which observes tool persist transitions for plan-mode state changes).

Tests proposed

  • Plugin subscribes to before_tool_call_persist; verify event dispatched with all fields populated for any tool call
  • Plugin subscribes to after_tool_call_persist; verify dispatched after persist completes with toolResult populated
  • Plugin handler throws → host logs and continues (best-effort observer pattern)
  • Multiple plugins subscribed → all dispatched (registration order)

Cross-link

Smarter-Claw filing: this is RFC #3 of a series pushing the plugin/host seam upstream. Sister RFCs:

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions