Skip to content

LAM-2006: read agent outputs from separate trace_outputs_v0 view#2120

Draft
dinmukhamedm wants to merge 8 commits into
devfrom
feat/new-traces
Draft

LAM-2006: read agent outputs from separate trace_outputs_v0 view#2120
dinmukhamedm wants to merge 8 commits into
devfrom
feat/new-traces

Conversation

@dinmukhamedm

@dinmukhamedm dinmukhamedm commented Jul 24, 2026

Copy link
Copy Markdown
Member

Summary

Ports the agent-IO work on this branch to the split read-path: agent_output is removed from the default trace schema (traces_v0 / traces_agg_v0) — the dict-resolving output join was too expensive inside the hot traces view (why is a separate investigation) — and is now read from the dedicated trace_outputs_v0 view, which returns the winning LLM span's entire output-message array (one raw message JSON per element, hashes resolved through deduped_content_dict).

Changes

ClickHouse (migration 55)

  • Recreates traces_agg_v0 without the trace_agent_output join and repoints traces_v0 at traces_agg; both expose agent_input only. trace_outputs_v0 (created in migration 54) is project-parameterized only, not time-parameterized.

Query engine / SQL surface

  • trace_outputs registered as an allowlisted table (validator.rs TableRegistry, schema.rs prompt, frontend tableSchemas, MCP joins hint trace_outputs.trace_id = traces.id); agent_output removed from the traces allowlist and editor schema. Validator test added for the rewrite.

Shared extraction (frontend/lib/traces/agent-output.ts)

  • extractAgentOutput pulls the valuable bits out of each output message: non-empty thinking/reasoning, non-empty text (or GenAI content), and tool calls rendered as name(payload) (message-level tool_calls, Anthropic tool_use, AI SDK tool-call, OpenAI Responses items, etc.). Deliberately permissive — unknown parts are stringified rather than dropped, so it degrades to extracting more instead of nothing. Pinned by tests/test-agent-output-extraction.test.ts (16 cases).

Read path

  • getAgentOutputsBatch (frontend/lib/actions/traces/outputs.ts) reads trace_outputs via the query engine, extracts text with the shared helper, and falls back to the legacy last-main-agent-LLM-span preview for traces without a trace_agent_output row.
  • Trace view: getTrace / getSharedTrace resolve agentOutput in parallel with the trace row; the transcript renders it as a trailing OutputItem row.
  • Session + debugger views: collapsed trace cards lazily fetch outputs for rows in view via the batched POST /api/projects/:id/traces/output route (store-level batching/debounce/dedupe, key agentOutputs).
  • Traces table: Output column + filter removed (agent_output no longer exists on the trace row).

Testing

  • cargo test --bin app-server query_engine — 112 passed.
  • pnpm test extraction suite — 16/16 passed; tsc --noEmit clean (two pre-existing unrelated test failures also fail on dev).
  • End-to-end against the staging stack: applied migrations 54+55, seeded a trace_agent_output row from real deduped_content hashes, and verified in the browser that (1) the trace-view transcript shows the extracted Output row, (2) the session view's collapsed trace card populates output via POST /traces/output, (3) SELECT agent_output FROM traces is now rejected while SELECT ... FROM trace_outputs and the traces ⋈ trace_outputs join work through the query engine. No console errors.

🤖 Generated with Claude Code

olzhik11 and others added 8 commits July 24, 2026 09:13
Drop agent_output from the default trace schema (traces_v0 /
traces_agg_v0 and everything that read it there) — the dict-resolving
join was too expensive inside the hot traces view. Outputs now live in
the dedicated trace_outputs_v0 view over the trace_agent_output RMT
(migration 54), returning the winning span's full output-message array
(one raw message JSON per element).

- query engine: register trace_outputs in the validator TableRegistry,
  dedupe the schema-prompt entry, add the frontend tableSchemas entry
  and MCP joins hint; drop agent_output from the traces column
  allowlist / schema / editor autocomplete
- shared extraction (lib/traces/agent-output.ts): per message part
  keep non-empty thinking/reasoning, non-empty text, and tool calls as
  name(payload); unknown parts are stringified rather than dropped
  (pinned by tests/test-agent-output-extraction.test.ts)
- getAgentOutputsBatch (lib/actions/traces/outputs.ts) reads the view
  via the query engine and falls back to the legacy last-LLM-span
  preview for traces without a trace_agent_output row; consumed by
  getTrace/getSharedTrace (trace view transcript Output row) and the
  batched POST /traces/output route driving session + debugger views
- traces table: drop the Output column/filter (agent_output is no
  longer on the trace row)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@laminar-coding-agent laminar-coding-agent Bot changed the title Feat/new traces LAM-2006: read agent outputs from separate trace_outputs_v0 view Jul 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants