Skip to content

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

@100yenadmin

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions