Skip to content

Local Visualization (Current)

Conductr Local is the current local visualizer for Railtracks. It reads the JSONL event stream that every run records, and lets you browse runs, LLM calls, middleware decisions, and raw events, with filtering, sorting, and pagination on every table. It is installed separately from the legacy visualizer, so both can be used in the same project.

The Agent Traces page of the current visualizer The Agent Traces page of the current visualizer

Still in beta

The current visualizer is still in beta, which is why it's started with --beta. Its UI and /api/v2 contract are under active development. Response fields, filters, and other behavior can change between releases without notice.

Install and start

Install the optional visualization dependencies:

Install the CLI visualization tools
pip install 'railtracks[visual]'

Initialize Railtracks from your project root, install the beta UI, and start the server:

Initialize and start the current visualizer
railtracks init
railtracks update --beta
railtracks viz --beta
  • railtracks init creates the .railtracks directory and installs the legacy UI.
  • railtracks update --beta installs the beta build alongside it in .railtracks/beta-ui.
  • If the beta UI is missing, railtracks viz --beta downloads it automatically before starting the server.

The server opens at http://localhost:3031. Its API uses /api/v2/... routes, and interactive API documentation is available at http://localhost:3031/docs.

The page doesn't update on its own. After a new run, press Refresh at the top right of any page to load it.

Agent Traces

Agent Traces is the home page. Each row is one run of a flow, with its status, entry point, the middleware it passed through, cost, tokens (input and output), duration, and start time.

  • The tiles at the top summarize every run that matches the current filters. Click Failures or Blocked to show only those runs, and click again to clear the filter.
  • Narrow the list by date range (24h, 7 days, 30 days, All, or a custom range), flow name, entry point, or status.
  • Show, hide, and resize columns with Columns. Your layout is remembered in the browser.

A run is Running while it's still in progress. Once it ends, it's Completed or Failed, or Blocked when a guardrail or verifier stopped it. Click a middleware icon in a row to open that middleware's decisions for the run.

Session details

Click a run to open its session. The tree on the left shows every node the run called, nested under the node that called it, with each one's latency. Select a node to see its cost, tokens, inputs, and outputs on the right. For an agent, that's the full message history it sent to the model.

A session with the Research Lead agent selected A session with the Research Lead agent selected

When a node made more than one LLM call, a table lists each call's model, tokens, cost, and latency. Select a call to see exactly what that call sent.

Nodes that raised an exception are marked Failed. To read the exception itself, open the run's events (see Event Logs) and select its node.failure event.

A failed run with the fetch_metrics tool selected A failed run with the fetch_metrics tool selected

Buttons at the top of the session:

  • Visualizer switches to a graph of the run. Click a node to inspect it, and use Session Details to switch back.
  • Events opens Event Logs filtered to this run.
  • The copy button copies the session ID.

The graph view of a parallel code review run The graph view of a parallel code review run

LLM Traces

LLM Traces lists every model call across all runs, with the flow, agent, model, tokens, cost, and latency. The tiles show the call count, errors, total tokens and cost, average latency, and the slowest call. Click Errors to show only failed calls. Filter by flow, agent, or model.

The LLM Traces page The LLM Traces page

Click a call to see its messages, its output, the provider, and the error if it failed. Open in session jumps to the node that made the call.

One LLM call opened from LLM Traces One LLM call opened from LLM Traces

Middleware

Middleware rolls up every middleware across all runs. One row is one middleware: how often it ran, how many decisions it made, how many calls it blocked or interrupted, and how many sessions it appeared in.

The Middleware page with a guardrail and a verifier The Middleware page with a guardrail and a verifier

Kind is what the middleware does:

Kind Created with
Input guard @rt.input_guard
Output guard @rt.output_guard
Request transform @rt.pre_llm
Response transform @rt.post_llm
Result hook @rt.post_node
LLM wrapper @rt.wrap_llm
Node wrapper @rt.wrap_node
Verifier pre_verifier, post_verifier

Band is where it was attached: Node for middleware= and LLM for model_middleware=.

Click Blocks to show only middleware that blocked something. The Framework switch also shows the middleware Railtracks adds internally for observability, which is hidden by default.

Click a row for its full roll-up, including when it was first and last seen and the reason it gave for its latest decision. View events opens its events in Event Logs.

A verifier's roll-up with the reason for its latest decision A verifier's roll-up with the reason for its latest decision

Event Logs

Event Logs is the raw event stream: every event Railtracks recorded, newest first. Search the payloads, or filter by namespace (such as node, llm, or middleware), event type, and flow. Click Failures to show only events that reported an exception.

The Event Logs page The Event Logs page

Click an event to see its full payload. For a failure, that includes the exception's name and message. Open in session jumps to the run, with the event's node selected.

A node.failure event showing the exception A node.failure event showing the exception

Middleware events carry each decision. Here, a pre_verifier declined a refund and recorded why, along with the arguments it was asked to approve:

A verifier decision event declining a refund A verifier decision event declining a refund

Evaluations

Evaluations aren't in the current visualizer yet. Its Evaluations page is a placeholder. To browse evaluation results, use the legacy visualizer as described in Evaluation Visualization.

Record event-stream data

Events are recorded automatically to .railtracks/data/events with no setup required. The current visualizer reads from the same directory.

Customize event writers

To use your own writer set (or add more alongside the default), call configure_writers(...). You can call it at any time: the writers it replaces are shut down, and the new ones receive every event after the call.

Configure local event storage
from railtracks.observability import JsonlWriter, configure_writers

configure_writers([JsonlWriter()])

configure_writers

configure_writers replaces the auto-registered default, so if you'd like to still have the local event files, you need to pass JsonlWriter() as well as any new or custom writers.

A custom writer is any object with plain (not async) start(), write(event) and shutdown() methods, matching the Writer protocol in railtracks.observability. Railtracks calls them on the thread that emits each event, one call at a time per writer, so keep write quick. configure_writers raises a TypeError if any of these methods is async.

Use another event directory

Set RAILTRACKS_EVENTS_DIR in both the process recording events and the visualizer process. Relative paths are resolved from the current working directory. This redirects the auto-injected writer without any code change.

Record and view another event store
export RAILTRACKS_EVENTS_DIR=./saved-events
python my_agent.py
railtracks viz --beta

Choose what context events record

rt.context calls are recorded as context.* events. Set RAILTRACKS_CONTEXT_EVENTS to 0 for no context events, 1 for keys without values, or 2 (the default) for keys and values. Every other event is recorded either way. See Global Context for details.

Record context keys but not their values
export RAILTRACKS_CONTEXT_EVENTS=1

Deployed environments with no writable disk

Set RAILTRACKS_DISABLE_EVENTS=True on hosts where Railtracks can't (or shouldn't) write to disk. It skips both the auto-registered event writer and the legacy save_state session dump, regardless of what save_state= is set to.

Turn off Railtracks-owned disk writes
export RAILTRACKS_DISABLE_EVENTS=True

For hosted observability in these environments, use Conductr.

save_state is deprecated

save_state=True still writes .railtracks/data/sessions/*.json for the legacy visualizer this release, but passing the argument at all now emits a DeprecationWarning. The file dump is being replaced by the event stream (.railtracks/data/events/). Default: True this release, flips to False next release. Remove the argument to let the framework default take over.

Running from multiple directories?

Run railtracks init once from your project root, at the same level as your .git directory. Railtracks walks up from the current directory to locate that project's .railtracks directory.

For a fixed location, set RAILTRACKS_HOME to the parent directory where .railtracks should live. RAILTRACKS_HOME takes priority over directory traversal.

Debug the API

Add --debug to emit structured diagnostics:

Start with API diagnostics
railtracks viz --beta --debug

Debug mode writes newline-delimited JSON records to stderr for v2 requests, DuckDB queries, and event-store connection changes.

Debug logs can contain user input

Request records include query parameter values, such as search terms. Review or redact debug output before sharing it or sending it to a log collector.

Update the UI

The legacy and current builds are updated independently. Refresh only the current build, in .railtracks/beta-ui, with:

Update the current visualizer
railtracks update --beta