diff --git a/hooks/agentmon/HOOK.md b/hooks/agentmon/HOOK.md index e4d6654..15b4441 100644 --- a/hooks/agentmon/HOOK.md +++ b/hooks/agentmon/HOOK.md @@ -9,13 +9,8 @@ metadata: - "command:reset" - "message:received" - "message:sent" - - "tool_result_persist" - - "session:compact:before" - - "session:compact:after" + - "agent:bootstrap" export: "default" - requires: - env: - - "AGENTMON_INGEST_URL" --- # Agentmon Telemetry Hook diff --git a/hooks/agentmon/handler.ts b/hooks/agentmon/handler.ts index 4a2e180..1b09d9c 100644 --- a/hooks/agentmon/handler.ts +++ b/hooks/agentmon/handler.ts @@ -14,7 +14,6 @@ let flushTimer: ReturnType | null = null; let isFlushing = false; const activeRuns = new Map(); -const activeCompactions = new Map(); function isRecord(value: unknown): value is Dict { return value !== null && typeof value === 'object' && !Array.isArray(value); @@ -274,7 +273,6 @@ const handler = async (rawEvent: unknown) => { enqueue(buildEnvelope('session.end', sessionKey)); if (sessionKey) { activeRuns.delete(sessionKey); - activeCompactions.delete(sessionKey); } return; } @@ -284,7 +282,28 @@ const handler = async (rawEvent: unknown) => { enqueue(buildEnvelope('session.start', sessionKey)); if (sessionKey) { activeRuns.delete(sessionKey); - activeCompactions.delete(sessionKey); + } + return; + } + + if (eventName === 'agent:bootstrap') { + // Only emit run.start if no run is already active for this session. + // Interactive message-channel sessions already emit run.start via + // message:received; this handler captures cron/automation embedded runs. + const existingRunId = sessionKey ? activeRuns.get(sessionKey) : undefined; + if (!existingRunId) { + const runId = randomUUID(); + if (sessionKey) { + activeRuns.set(sessionKey, runId); + } + + enqueue(buildEnvelope('run.start', sessionKey, { + runId, + attributes: { + agent_id: pickString(context.agentId as string | undefined), + run_kind: 'embedded', + }, + })); } return; } @@ -330,79 +349,6 @@ const handler = async (rawEvent: unknown) => { return; } - if (eventName === 'tool_result_persist') { - const runId = sessionKey ? activeRuns.get(sessionKey) : undefined; - const spanId = randomUUID(); - const success = context.success !== false && !context.error; - const toolName = pickString(context.toolName, context.tool_name, context.name) || 'unknown_tool'; - const payload: Dict = { - status: success ? 'success' : 'error', - }; - - const duration = pickNumber(context.duration_ms, context.durationMs, context.elapsed_ms); - if (duration !== undefined) { - payload.duration_ms = duration; - } - - const resultPreview = truncate(context.result ?? context.output, 500); - if (resultPreview) { - payload.result_preview = resultPreview; - } - - enqueue(buildEnvelope('span.end', sessionKey, { - runId, - spanId, - attributes: { - span_kind: 'tool', - name: toolName, - }, - payload, - })); - - if (!success) { - emitError(sessionKey, runId, spanId, context.error); - } - return; - } - - if (eventName === 'session:compact:before') { - const runId = sessionKey ? activeRuns.get(sessionKey) : undefined; - const spanId = randomUUID(); - if (sessionKey) { - activeCompactions.set(sessionKey, spanId); - } - - enqueue(buildEnvelope('span.start', sessionKey, { - runId, - spanId, - attributes: { - span_kind: 'internal', - name: 'context_compaction', - }, - })); - return; - } - - if (eventName === 'session:compact:after') { - const runId = sessionKey ? activeRuns.get(sessionKey) : undefined; - const spanId = (sessionKey && activeCompactions.get(sessionKey)) || randomUUID(); - if (sessionKey) { - activeCompactions.delete(sessionKey); - } - - enqueue(buildEnvelope('span.end', sessionKey, { - runId, - spanId, - attributes: { - span_kind: 'internal', - name: 'context_compaction', - }, - payload: { - status: 'success', - duration_ms: pickNumber(context.duration_ms, context.durationMs, context.elapsed_ms), - }, - })); - } } catch { console.debug('[agentmon] handler error'); }