Skip to main content
Custom trace views transform complex traces into interfaces anyone on your team can use. Describe what you want in natural language and Loop generates an interactive React component you can customize or embed anywhere.

Common use cases

Build custom annotation interfaces for large-scale human review tasks, surfacing only relevant information for annotators and subject matter experts.
Replace JSON with intuitive UI components like carousels, playlists, or structured summaries to make traces accessible to PMs, legal reviewers, and domain experts.
Create views that mirror your product experience:
  • Playlist-style views for music applications
  • Interactive source-and-answer layouts
  • Custom dashboards for internal evaluations
Aggregate and display data across conversation turns to analyze dialogue flow and long-running interactions.

Create trace views

To create a custom trace view using Loop:
  1. Select a trace in your logs, experiments, or during human review.
  2. Select Views.
  3. Describe how you want to view your trace data.
After Loop generates your view, refine the view by describing additional changes or edit the React component code directly. Example prompts:
  • “Create a view that renders a list of all tools available in this trace and their outputs”
  • “Build an interface to review each trace one by one with easy switching between traces”
  • “Create a conversation-style view that highlights user messages and assistant responses”
  • “Render the video url from the trace’s metadata field and show simple thumbs up/down buttons”

Share trace views

By default, a custom trace view is only visible and editable by the user who created it. To share your view with all users in the project:
  1. Select Save in the view editor.
  2. Choose Save as new view version.
  3. Select Update to make it available project-wide.
All team members can then use the shared view when reviewing traces. Custom views integrate with Braintrust workflows — use them during human review, write annotations that flow into datasets, and combine with Loop for analysis.
Self-hosted deployments: If you restrict outbound access, allowlist https://www.braintrustsandbox.dev to enable custom views. This domain hosts the sandboxed iframe that securely renders custom view code.

Edit trace view React code

Custom trace views are React components that run inside Braintrust. You can edit the component code directly to customize behavior beyond what Loop generates. To edit the React code:
  1. Go to the custom trace view.
  2. Select in the lower left of the view.
  3. Select Edit.
Your React component receives the following props:
PropTypeDescription
traceobjectContains all spans and methods for the trace
spanobjectThe currently selected span with full data
updatefunctionUpdate span metadata: update('field', value)
selectSpanfunctionNavigate to a different span: selectSpan(spanId)
The trace object includes:
  • rootSpanId, selectedSpanId - Current span context
  • spanOrder - All span IDs in execution order
  • spans - Map of span_id → span (IDs/relationships only)
  • fetchSpanFields - Fetch full data for multiple spans (see Access data from multiple spans)
The component can be copied and embedded in your own applications, enabling you to:
  • Reuse custom views outside of Braintrust
  • Integrate review interfaces into internal tools
  • Build standalone annotation applications
  • Create consistent review experiences across different contexts

Add interactive controls

Custom views support interactive elements that write data back to traces. Add buttons, inputs, or custom controls to collect:
  • Human review scores
  • Thumbs up/down feedback
  • Custom metadata fields
  • Annotation notes
Use the update function to write metadata back to the trace. This enables annotation workflows where review and data collection happen in the same interface.
Example: Add thumbs up/down buttons
function FeedbackView({ trace, span, update }) {
  const handleFeedback = (isPositive) => {
    update('metadata', {
      ...span.metadata,
      user_feedback: isPositive ? 'positive' : 'negative',
      reviewed_at: new Date().toISOString(),
    });
  };

  return (
    <div className="p-4">
      <h3 className="text-lg font-semibold mb-4">Review this output</h3>
      <pre className="bg-slate-100 p-2 rounded mb-4">
        {JSON.stringify(span.output, null, 2)}
      </pre>
      <div className="flex gap-2">
        <button onClick={() => handleFeedback(true)}>👍 Good</button>
        <button onClick={() => handleFeedback(false)}>👎 Bad</button>
      </div>
    </div>
  );
}

module.exports = FeedbackView;

Access data from multiple spans

By default, only the selected span has full data (input, output, expected, metadata). To access data from other spans, use fetchSpanFields:
// Fetch all fields for one span
const data = await trace.fetchSpanFields(spanId);

// Fetch specific fields for multiple spans
const data = await trace.fetchSpanFields(trace.spanOrder, ['input', 'output']);
Example: Display all span inputs
function AllInputsView({ trace, span }) {
  const [spanData, setSpanData] = React.useState(null);
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState(null);

  React.useEffect(() => {
    if (!trace?.fetchSpanFields) return;

    trace.fetchSpanFields(trace.spanOrder, ['input'])
      .then(setSpanData)
      .catch((err) => {
        console.error('Failed to fetch span data:', err.message);
        setError(err.message);
      })
      .finally(() => setLoading(false));
  }, [trace]);

  if (loading) return <div className="p-4">Loading...</div>;
  if (error) return <div className="p-4 text-red-600">Error: {error}</div>;

  return (
    <div className="p-4 space-y-2">
      {trace.spanOrder.map((id) => (
        <pre key={id} className="text-xs bg-slate-100 p-2 rounded text-wrap">
          {JSON.stringify(spanData?.[id]?.input, null, 2)}
        </pre>
      ))}
    </div>
  );
}

module.exports = AllInputsView;

Next steps