Skip to content

Ayubjon/tracegram

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

tracegram

Turn an LLM agent conversation into a Mermaid sequence diagram, a Markdown timeline, or a plain-text trace — so you can actually see what your agent did.

tracegram demo: a terminal trace and the rendered sequence diagram it produces

Agent logs are a wall of JSON. When a run goes wrong — a tool got the wrong arguments, a result came back as an error, the model looped — you scroll through nested messages arrays trying to reconstruct the story. tracegram reads that JSON (OpenAI or Anthropic format, auto-detected) and renders the turn-by-turn flow of messages and tool calls in a form you can read at a glance, paste into a PR, or drop into a bug report.

  • 🔁 Auto-detects OpenAI Chat Completions and Anthropic Messages JSON.
  • 🧜 Mermaid output renders natively on GitHub — paste it straight into an issue or README.
  • 📝 Markdown and plain-text outputs for docs and terminals.
  • 🧰 Surfaces tool calls, tool results, and errors (⚠) as first-class events.
  • 📊 Optional one-line stats (message counts, tool usage, rough token estimate).
  • 📦 Zero dependencies. Pure ESM. Works as a CLI and as a library.

Install

Run it instantly with npx:

npx tracegram run.json

Or install globally / as a dependency:

npm install -g tracegram   # for the CLI
npm install tracegram      # to use the library

Requires Node.js ≥ 18. No build step, no API keys, nothing to configure.

Usage

tracegram [file] [options]
cat conversation.json | tracegram [options]
Option Description
-f, --format <fmt> mermaid (default), markdown, or text
-p, --provider <name> Force openai or anthropic (default: auto-detect)
-m, --max-len <n> Max characters per label in Mermaid output (default: 60)
-s, --stats Prepend a one-line stats summary
--no-system Omit the system prompt from the output
-h, --help Show help
-v, --version Show the version

Example

Given an OpenAI conversation with a tool call (examples/openai-weather.json):

tracegram examples/openai-weather.json

produces this Mermaid, which GitHub renders as a live diagram:

sequenceDiagram
    participant U as User
    participant A as Assistant
    participant T as Tools
    Note over A: System: You are a concise weather assistant.
    U->>A: What should I wear in Paris today?
    A->>U: Let me check the current conditions.
    A->>T: get_weather({"city":"Paris","units":"metric"})
    T-->>A: {"temp_c":12,"condition":"light rain","wind_kph":18}
    A->>U: It's 12°C with light rain and a brisk wind in Paris. Wear a…
Loading

Prefer a quick terminal view, with stats?

$ tracegram examples/anthropic-research.json -f text --stats
# messages=3 tool_calls=2 tool_errors=1 tools=[unit_convert, wiki_search] ~tokens=93
SYSTEM    │ You are a research agent. Use tools to gather facts before answering.
USER      │ How tall is the Eiffel Tower, and when was it built?
ASSISTANT │ I'll look that up.
CALL      │ wiki_search({"query":"Eiffel Tower height"})
RESULT    │ wiki_search: Height: 330 m (including antennas). Completed: 1889.
CALL      │ unit_convert({"value":330,"from":"m","to":"ft"})
ERROR     │ unit_convert: service unavailable
ASSISTANT │ The Eiffel Tower is 330 m tall (about 1,083 ft) and was completed in 1889.

Use as a library

import { render } from 'tracegram';

const conversation = {
  messages: [
    { role: 'user', content: 'Hi' },
    { role: 'assistant', content: null, tool_calls: [
      { id: 'c1', function: { name: 'ping', arguments: '{}' } },
    ] },
    { role: 'tool', tool_call_id: 'c1', content: 'pong' },
    { role: 'assistant', content: 'All good.' },
  ],
};

console.log(render(conversation, { format: 'markdown' }));

API

import {
  render,          // (input, opts?) -> string   high-level: normalize + render
  normalize,       // (input, provider?) -> Conversation
  detectProvider,  // (input) -> 'openai' | 'anthropic'
  toMermaid,       // (conv, opts?) -> string
  toMarkdown,      // (conv, opts?) -> string
  toText,          // (conv) -> string
  stats,           // (conv) -> { messages, toolCalls, toolErrors, tools, estTokens, ... }
} from 'tracegram';

render(input, opts) accepts a conversation object, a bare messages array, or a JSON string.

Options: format ('mermaid' | 'markdown' | 'text'), provider (force a provider), maxLen (Mermaid label cap), includeSystem (default true), title (Markdown heading).

The normalized model

Both providers are normalized into one provider-agnostic shape, so the renderers — and your own code — never have to special-case a vendor:

Conversation = { provider, system, events }
Event =
  | { kind: 'message',     role: 'user' | 'assistant', text }
  | { kind: 'tool_call',   id, name, args }
  | { kind: 'tool_result', id, name, text, isError }

Supported input

  • OpenAI{ messages: [...] } or a bare [...] array with system / user / assistant / tool roles, tool_calls, and tool_call_id.
  • Anthropic{ system, messages: [...] } with string or block content (text, tool_use, tool_result, including is_error).

Tool results are matched back to their originating call so the tool name appears on both sides.

Development

git clone https://github.com/Ayubjon/tracegram.git
cd tracegram
node --test        # run the test suite

License

MIT © 2026 Ayubjon

Support

If this project is useful to you, you can support its development with a crypto tip — thank you!

USDT — Ethereum (ERC-20):

0xad39bdf2df0b8dd6991150fcea0a156150ed19b8

View / verify on Etherscan

Send only on the Ethereum (ERC-20) network.

About

Turn an LLM agent conversation (OpenAI or Anthropic JSON) into a Mermaid sequence diagram, Markdown timeline, or plain-text trace. Zero deps.

Topics

Resources

License

Stars

2 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors