Skip to content

feat(ui): agent traces open in a side drawer with a chat-style run view - #43972

Merged
ishaan-berri merged 9 commits into
mainfrom
litellm_improved_lens_ui
Oct 1, 2026
Merged

ishaan-berri merged 9 commits into
mainfrom
litellm_improved_lens_ui

Conversation

@ishaan-berri

@ishaan-berri ishaan-berri commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

TLDR

Problem this solves:

  • Clicking a trace took over the whole page and lost the list
  • AI messages showed raw JSON (reasoning blobs, encrypted content)
  • Long conversations got cut mid-JSON, so nothing rendered
  • "Set up tracing" was easy to miss

How it solves it:

  • Traces open in a resizable drawer on the right, list stays clickable
  • j / k or the header arrows switch traces, Esc closes
  • New tree: connector lines, waterfall bar per step, provider logos, hover card with timings
  • Input / Output render as chat cards, tool calls as key/value rows
  • Decoder keeps the text from reasoning / function_call blocks and trims old messages instead of cutting JSON
  • Span decoding split into one class per convention under litellm/tracing/normalizers/, so adding a new framework is one file
  • New standard "LiteLLM UI" span format: the span endpoint returns input_ui / output_ui as messages, fields or text, and the UI renders those instead of re-parsing raw payloads (falls back to the old parsing against an older proxy)

Intentional product change: the run view is a side drawer now, not a full page. The list stays visible behind it

User Flow

Before: a developer opens a multi-turn agent trace and can't read it

  1. Go to http://localhost:4000/ui/?page=logs, open the Agent Traces tab
  2. Click a run, the list disappears and the run fills the page
  3. Click a ChatOpenAI step, Input and Output show escaped JSON with encrypted reasoning blobs
  4. To look at another run they have to go back to the list and click again

After: the same trace reads like a chat, and switching runs is one key

  1. Go to http://localhost:4000/ui/?page=logs, open the Agent Traces tab
  2. Click a run, it opens in a drawer on the right and the list stays visible
  3. Click a ChatOpenAI step, Input and Output show User / AI cards with the model's text and tool calls
  4. Press j / k (or the arrows in the drawer header) to move between runs, Esc to close

before

after list

after drawer

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have added meaningful tests
  • The handful of test files covering my change pass locally, e.g. uv run pytest tests/unit/<your_test_file>.py -v. Leave the suites (make test-unit-*, make test-unit) to CI: it finishes in ~15 minutes where a laptop takes an hour or more
  • My PR passes all required CI/CD checks (e.g., lint, schema.d.ts sync check, etc.)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have received a Greptile Confidence Score of at least 4/5 before requesting a maintainer review (Greptile reviews automatically once the PR is opened; only comment @greptileai to re-request a review after pushing changes)

Delays in PR merge?

If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).

Screenshots / Proof of Fix

Traces come from real Deep Agents runs on gpt-6.1-sol, exported over OTLP to a local proxy with tracing: store: clickhouse

Before (ae60fd1)

  1. Open http://localhost:4000/ui/?page=logs, Agent Traces tab, click travel-turn-7
  2. Run takes over the page, the ChatOpenAI step's Input and Output are raw JSON (first screenshot above)

After (0f8c043)

  1. Open http://localhost:4000/ui/?page=logs, Agent Traces tab, the list shows clean previews and a boxed "Set up tracing" button (second screenshot)
  2. Click a run, the drawer opens on the right with the tree and chat-style Output (third screenshot)
  3. Press j, the drawer swaps to the next run without closing; Esc closes it

Type

🆕 New Feature
🐛 Bug Fix

Caveats (if any)

Low

  • Traces already stored keep their old decoded text; only new spans get the cleaner messages. The UI also unwraps reasoning/text blocks on read, so most old traces look fine
  • Drawer width is remembered in localStorage per browser

Final Attestation

  • The tests check the right things, including the edge cases, and regressions in the respective real-world customer use-cases are not possible after this PR

Tree with connector lines, typed icon tiles and provider logos, hover
cards with timing, and Input/Output sections rendered as message cards.
…alizers per convention

OpenAI responses-style content (reasoning + text blocks) rendered as raw
JSON in the trace view. Keep the text blocks and drop opaque reasoning.

Move each convention into litellm/tracing/normalizers with an ordered
registry so new frameworks plug in without touching OTLP decoding.
…-style tree

Clicking a run opens it in a drawer over the list instead of a full page.
j/k and the header arrows switch runs, Esc closes. The tree gets dashed
connectors, per-span waterfall bars, mono tool names and real provider
logos. AI messages with reasoning/function_call blocks render as text.
@ishaan-berri
ishaan-berri requested a review from a team October 1, 2026 02:56
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@codecov

codecov Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.52174% with 12 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
litellm/tracing/normalizers/langsmith.py 96.00% 3 Missing ⚠️
litellm/tracing/normalizers/messages.py 91.17% 3 Missing ⚠️
litellm/tracing/decode.py 96.61% 2 Missing ⚠️
litellm/tracing/normalizers/base.py 77.77% 2 Missing ⚠️
litellm/tracing/ui_format.py 98.16% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@greptile-apps

greptile-apps Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 4/5

[Medium risk] Adds trace normalization and UI formatting for agent spans.

The PR needs its repository-instruction violations addressed before merging; oversized tool calls also warrant a trace-readability fix

Findings

  1. P2 Oversized tool calls disappear ▶
  2. P2 Unnecessary source comment ▶
  3. P2 Normalizer mutates span rows ▶

Summary

The PR moves agent traces into a resizable side drawer and presents span payloads as chat messages, fields, or text. It also reorganizes span normalization and adds server-provided UI content

  • Recent changes retain both endpoint messages when oversized fields exceed the trace budget and preserve failed-tool styling for a single-message result
  • Oversized tool-call arguments can still remove the call itself from the displayed trace

Reviews (4) · Last reviewed commit: "fix(tracing): keep both messages when to..."

Comment thread litellm/tracing/decode.py Outdated
Comment thread litellm/tracing/decode.py Outdated
Comment thread ui/litellm-dashboard/src/components/view_logs/TraceView/RunDrawer.tsx Outdated
Comment thread ui/litellm-dashboard/src/components/view_logs/TraceView/traceUtils.ts Outdated
Comment thread litellm/tracing/decode.py Outdated
@codspeed

codspeed Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing litellm_improved_lens_ui (27110aa) with main (d9f7324)1

Open in CodSpeed

Footnotes

  1. No successful run was found on main (91ff045) during the generation of this report, so d9f7324 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report. ↩

@veria-ai

veria-ai Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

PR overview

All previously flagged issues have been addressed. No open security concerns remain on this pull request.

Security review

No open security issues remain on this pull request.

Fixed/addressed: 1 · PR risk: 0/10

@ishaan-berri

Copy link
Copy Markdown
Contributor Author

@greptileai fixed JSON trimming, drawer shortcuts, reduced motion, narrow screens, tree guides and expandable tool output. Please re-review

Comment thread litellm/tracing/decode.py
ishaan-berri and others added 2 commits September 30, 2026 20:41
GET /v1/traces/{trace_id}/spans/{span_id} now also returns input_ui and
output_ui, a tagged union of messages, fields or text built server side by
litellm/tracing/ui_format.py. The trace UI renders from those fields and only
falls back to client-side parsing when talking to an older proxy. The raw
input and output strings are unchanged, and so is storage

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ishaan-berri

Copy link
Copy Markdown
Contributor Author

@greptileai added the standard LiteLLM UI span format and fixed the oversized-fields truncation case. Please re-review

Comment thread litellm/tracing/decode.py
return has_role and ("content" in message.model_fields_set or bool(message.tool_calls))


def _arguments_text(arguments: JsonValue) -> str:
return "assistant" if has_tool_calls else "user"


def _ui_message(message: _RawMessage) -> UIMessage:
@ishaan-berri

Copy link
Copy Markdown
Contributor Author

@greptileai kept both messages when tool_calls are oversized and preserved failed-tool styling. Please re-review

Comment thread litellm/tracing/decode.py
Comment on lines +88 to +92
role_only: Final = MappingProxyType({"role": message.get("role", "user")})
attempts: Final = (
_cut_content(message, text, budget, 1),
_cut_content(role_only, text, budget, 1),
_cut_content(role_only, text, budget, _MAX_JSON_ESCAPE_BYTES),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Oversized tool calls disappear When arguments exceed the message budget, this fallback drops tool_calls, so the trace no longer shows which tool the assistant called

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment thread litellm/tracing/decode.py
Comment on lines +82 to +85
"""One message cut to `budget` bytes, as valid JSON.

Shortens `content` first; if other fields (e.g. huge tool_calls) still don't fit, keeps only role + content.
"""

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Unnecessary source comment This docstring explains straightforward fallback code, violating the repository's limits on source comments. Remove it before merging

Suggested change
"""One message cut to `budget` bytes, as valid JSON.
Shortens `content` first; if other fields (e.g. huge tool_calls) still don't fit, keeps only role + content.
"""

Context Used: AGENTS.md (source)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines +25 to +28
elif operation == "execute_tool":
row["ObservationType"] = "tool"
row["AgentName"] = attributes.get("gen_ai.agent.name", "")
row["Model"] = attributes.get("gen_ai.request.model") or attributes.get("gen_ai.response.model", "")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Normalizer mutates span rows These assignments violate the repository's immutability instruction for new code. Return normalized values or justify unavoidable mutation before merging

Context Used: AGENTS.md (source)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

…ns_ui

# Conflicts:
#	litellm/tracing/decode.py
@ishaan-berri
ishaan-berri enabled auto-merge (squash) October 1, 2026 17:52
@ishaan-berri
ishaan-berri merged commit d24240c into main Oct 1, 2026
92 of 94 checks passed
@ishaan-berri
ishaan-berri deleted the litellm_improved_lens_ui branch October 1, 2026 17:55
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.

4 participants