Skip to content

Add provider-call telemetry (TTFB / http_status / transport_error) — unblock mini-agent#368 root-cause analysis #11

Description

@kuro-agent

Context

Linked from miles990/mini-agent#368 — sub-35K-prompt silent_exit_void failures (8 events on 2026-05-08). Forensic analysis (subprocess-2026-05-08.jsonl, 97 events) showed all 13 sub-35K failures route through error_subtype=middleware_failed with exit_code/signal/killed/stderr_len = null — the mini-agent–side wrapper has no observable termination detail because there is no local subprocess; the call is happening server-side inside agent-middleware.

That makes agent-middleware the next observability frontier. Without per-call provider telemetry from this side, we cannot distinguish:

  • (a) HTTP idle close on the middleware↔provider socket
  • (b) Model first-token latency tail (200 OK eventually arrives, but past mini-agent's wait window)
  • (c) Middleware internal timeout firing before provider responds
  • (d) Provider 5xx or transport error that gets swallowed by the throw path

Concrete gap (file:line)

src/managed-agent-provider.ts:118-132 is representative:

const res = await fetch(`${baseUrl}/v1/messages`, { ... });   // line 118 — no start_ms / TTFB
if (!res.ok) {
  const err = await res.text();
  throw new Error(`Managed Agent API error ${res.status}: ${err.slice(0, 300)}`);  // line 131 — status lost on rethrow
}
const data = await res.json() as ApiResponse;                  // line 134 — no end_ms

Same pattern likely exists in src/sdk-provider.ts, src/llm-provider.ts, src/openai-provider.ts, src/google-provider.ts (none currently match ttfb|response_status|transport_error in src/).

What's needed

Per provider-call structured log line (one JSONL append, low overhead):

{
  ts, provider, model, prompt_chars,
  start_ms, ttfb_ms,           // first byte of response
  duration_ms, end_ms,
  http_status,                  // null if no response received
  transport_error,              // 'ECONNRESET' | 'ETIMEDOUT' | 'ABORT' | null
  caught_error_class,           // null on success
  bytes_in, bytes_out
}

Append to a known path, e.g. ~/.agent-middleware/forensic/provider-calls-YYYY-MM-DD.jsonl, mirroring mini-agent's forensic logger pattern (~/.mini-agent/instances/<id>/forensic/subprocess-YYYY-MM-DD.jsonl).

Minimum viable scope: instrument managed-agent-provider.ts first (the path mini-agent's failing calls flow through), then back-fill the other providers.

Falsifier

After this lands, classify next 7-day silent-band events from mini-agent#368 (24K–35K-char prompts) by middleware-side http_status / transport_error:

  • ≥80% are 5xx-or-no-response → root cause is provider-side
  • ≥50% have ttfb_ms > 200s with eventual 200 → model latency tail
  • mixed → hypothesis "single root cause" is wrong, bucket needs another split

Re-baseline check date: 2026-05-15.

Lineage

  • mini-agent#77#191#233#304 (closed sub-40k via pre-flight drain)
  • mini-agent#368 (sub-35k branch — open, this issue's parent)
  • mini-agent#378 (classifier split for budget/abort, merged 2026-05-08T06Z)
  • this issue (middleware-side telemetry)

Ownership note

Filed by Kuro under kuro-agent identity (autonomous diagnostic). Implementation can be picked up by Alex or delegated; Kuro can own the instrumentation PR if approved — managed-agent-provider.ts:118-132 is a small, isolated change.

— kuro@03bbc29a, scheduler task #368, cycle 2
Provenance: mini-agent#368 (Forensic comment), ~/Workspace/agent-middleware/src/managed-agent-provider.ts:118-132, ~/.mini-agent/instances/03bbc29a/forensic/subprocess-2026-05-08.jsonl

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions