Skip to content

Feature: Tool Hooks for External UI Visibility #2904

@JustMaier

Description

@JustMaier

Problem Statement

When an agent session is churning through tool calls (long-running exec, polling background processes, etc.), there's no visibility into what it's doing from external UIs like Discord. The channel goes silent even though the agent is actively working.

Example: A session running benchmarks for 2+ minutes with no Discord updates — stuck in a toolUsetoolResulttoolUse loop, never producing a user-facing message.

Proposed Solution

Add a Tool Hook Bridge that connects the existing agent event system to the internal hooks system, enabling workspace hooks to react to tool lifecycle events.

Architecture

Agent Runtime
    ↓ emitAgentEvent({ stream: "tool", phase: "start|update|result" })
Agent Event Bus (agent-events.js)
    ↓ onAgentEvent()
Tool Hook Bridge (NEW: infra/agent-hook-bridge.js)
    ↓ triggerInternalHook({ type: "tool", action: phase })
Internal Hooks System
    ↓
Workspace Hook Scripts (e.g., Discord visibility hook)

New Hook Events

  • tool:start — Tool execution begins (includes args)
  • tool:update — Streaming output during execution (hook handles throttling)
  • tool:result — Tool execution completes (includes result, isError)

Context Provided to Hooks

{
  type: "tool",
  action: "start" | "update" | "result",
  sessionKey: "agent:main:discord:channel:123456",
  timestamp: Date,
  context: {
    runId: string,
    toolName: string,
    toolCallId: string,
    args?: any,           // on start
    partialResult?: any,  // on update
    result?: any,         // on result
    isError?: boolean,    // on result
    meta: object,
    sessionMeta: {        // Parsed for convenience
      agentId: string,
      platform: string,   // discord, telegram, etc.
      channelType: string,
      channelId: string,
    }
  }
}

Use Cases

  1. Ephemeral status messages — Post "⏳ Running: `exec npm run benchmark`..." to Discord, update when done
  2. Typing indicators — Show typing while tools are executing
  3. Audit logging — Track all tool usage for debugging/compliance
  4. Timeout warnings — Alert if a tool is taking unusually long
  5. Real-time dashboards — Stream tool activity to WebSocket UIs

Implementation Plan

  1. Create src/infra/agent-hook-bridge.ts with startAgentHookBridge() function
  2. Subscribe to agent events and translate to hook events
  3. Parse session keys to provide structured sessionMeta
  4. Call from gateway startup after hooks are loaded
  5. Document new hook event types

Design Decisions

  • Update events not filtered — Hook scripts handle their own rate limiting (allows both throttled Discord updates AND real-time WebSocket streaming)
  • Fire-and-forgetvoid triggerInternalHook() so tool execution isn't blocked by slow hooks
  • Reuse existing utilities — Uses parseAgentSessionKey from session-key-utils.js
  • Dedicated module — Keeps gateway startup clean

Related

  • Discussed in Discord #Feature channel
  • External review by Gemini agent confirmed architecture approach

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions