Skip to content

Concepts

Versions

How every save becomes a version, how to see who made it and what changed, restore an old one, and how comments attach to panels.

Every save of a dashboard is a new version, numbered from 1 in a single line. A version holds the whole ObserveSpec document as it was saved, so no version depends on another, and a version is never edited after it is written.

These all save a version:

  • The first save, which is version 1, whether it comes from the agent, the web app, the API or a Grafana import.
  • A change in the web app: saving a layout, or saving a panel from the panel editor. Both ask for a short summary.
  • A change to the title, description or tags with Edit details in the More menu. It asks for no summary and writes Rename to "<title>" when only the title changed and “Edit dashboard details” otherwise.
  • The agent revising a dashboard, and update_dashboard from an MCP client.
  • POST /api/v1/dashboards/{id}/versions over the API.
  • A restore of an older version.

Moving a dashboard to another folder saves no version.

What a version records

Each version keeps a summary of 1 to 500 characters, the time, and who or what made it:

  • The author, which is a person or a service account. When the agent saves a version, the author is the person or key that asked for it.
  • The origin, one of web, cli, mcp or api, and for mcp the client’s own name, such as claude-code. The client’s name is what the client reports about itself and is not verified. The origin is a label and never decides what someone may do.
  • The agent request that saved it, if there was one.
  • The version it was restored from, if it is a restore.

The version menu in the dashboard header lists the five latest versions with their summaries. It shows “Agent” for a version the built-in agent saved, the MCP client’s name for one saved over MCP, and the author’s name for the rest. The History page also lists the author of each version, which for an agent save is the person who asked. The Dashboards page’s Made by column shows who made version 1: their name, then their email (or “service account”) and the channel, which is Web, CLI, API, the MCP client’s name such as Claude Code, or Agent; an agent save over MCP reads “Agent · Claude Code”. The Made by filter lists each person with their email, and the dashboard header names the client of a dashboard made over MCP.

A save names the version it builds on. If someone saved a newer version in the meantime, the save is refused with 409 and the code version_conflict, and the response gives latest_version.

Compare versions

Choose Compare versions in the version menu to open the History page of the dashboard. It lists the versions, newest first, with View, Compare and Restore, and shows the changes between two versions. Compare on a row diffs it with the version before it, and the From and To menus pick any two. Version 1 can be compared with an empty dashboard.

The changes are grouped under the dashboard, each panel and each variable, and each is marked Added, Removed, Changed or Reordered. Panels are matched by id across versions, so a panel whose title or position changed shows as a change to that panel and not as a removal and an addition.

Over the API, GET /api/v1/dashboards/{id}/diff?from=&to= returns the same changes as JSON pointers into the document. from defaults to the version before to, to defaults to the latest, and from=0 diffs against an empty document.

View opens the dashboard at that version, and the header then reads “v3 of 5” and not “Live”.

Restore a version

Restore on any version except the latest asks for confirmation and then saves a copy of that version as a new latest version, marked “Restored from v3”. Nothing is deleted, so the versions in between stay in the history, and you can restore again to go back. Deleting the dashboard is the only way versions go away: Delete dashboard in the More menu or a row menu, or DELETE /api/v1/dashboards/{id}, deletes every version with it, and it cannot be undone. The summary defaults to “Restore version 3”.

A restore checks the document and that its datasources are still configured, but it does not run the queries again. Restoring a known-good version therefore does not fail because a datasource is briefly down. The restored version keeps the list of panels and variables that were unverified when it was first saved.

Restoring needs Edit on the dashboard’s folder, so a Commenter or Viewer never sees a Restore button (see Roles and Folders and access). Over the API it is POST /api/v1/dashboards/{id}/versions/{version}/restore with the parent_version it builds on, and it can answer 409 like any save. MCP has no restore tool.

Duplicate a dashboard

Duplicate… in a dashboard’s More menu, or in its row menu on the Dashboards page, saves the latest version as version 1 of a new dashboard and opens it. You choose its title, which starts as “ copy”, and a folder you can create dashboards in, which starts as the dashboard’s own folder when you can create there. Duplicating needs View on the dashboard and Edit in the folder you choose. The copy starts its own history: earlier versions, comments, agent requests and the import record stay with the original, and its version 1 reads “Duplicated from “<title>” version 7”. Like a restore, it checks that the datasources are still configured but does not run the queries again, and it keeps the list of unverified panels and variables. Over the API it is <code>POST /api/v1/dashboards/{id}/duplicate</code> with a <code>title</code> and an optional <code>folder_id</code>. MCP and the CLI have no duplicate command.</p> <h2 id="comments">Comments</h2> <p>A comment is anchored to a panel id and to the version it was written on, or to the whole dashboard. It does not move when later versions change the panel. Replies join the thread of the comment they answer and take the same version and panel.</p> <p>Commenters, Editors and Admins can comment; Viewers cannot. A thread is open until someone resolves it. When it is resolved with a version, the thread shows “Resolved by version N”, and a revision that the agent made from the thread records its own version there.</p> <p>Because the anchor is the panel id, keep the id when you change a panel. A panel with a new id is a different panel to its comments. If the latest version no longer has the panel, the comment stays but its <code>panel_present</code> is <code>false</code>. The agent and MCP clients keep ids when they revise a dashboard.</p> <p>MCP clients and the CLI can list, reply to and resolve comments (see <a href="/docs/use/mcp/">MCP</a> and <a href="/docs/use/cli/">CLI</a>).</p> </div></article><div class="docs-end" data-astro-cid-ccykbmgk><div class="links" data-astro-cid-ztrwvmat><div class="actions" data-astro-cid-ztrwvmat><a href="https://github.com/slashobserve/slashobserve/edit/main/docs/concepts/versions.md" target="_blank" rel="noopener" data-astro-cid-ztrwvmat><svg width="14" height="14" viewBox="0 0 24 24" aria-hidden="true" fill="currentColor"><path d="M12 .5C5.65.5.5 5.65.5 12c0 5.08 3.29 9.39 7.86 10.91.58.1.79-.25.79-.56v-2.18c-3.2.7-3.87-1.36-3.87-1.36-.53-1.34-1.29-1.7-1.29-1.7-1.05-.72.08-.7.08-.7 1.16.08 1.77 1.19 1.77 1.19 1.03 1.77 2.7 1.26 3.36.96.1-.75.4-1.26.73-1.55-2.55-.29-5.24-1.28-5.24-5.69 0-1.26.45-2.29 1.19-3.1-.12-.29-.51-1.46.11-3.05 0 0 .97-.31 3.18 1.18.92-.26 1.91-.39 2.89-.39.98 0 1.97.13 2.89.39 2.21-1.49 3.18-1.18 3.18-1.18.62 1.59.23 2.76.11 3.05.74.81 1.19 1.84 1.19 3.1 0 4.42-2.69 5.4-5.25 5.68.41.36.78 1.07.78 2.15v3.19c0 .31.21.67.8.56C20.22 21.39 23.5 17.08 23.5 12 23.5 5.65 18.35.5 12 .5z"></path></svg>Edit this page on GitHub</a><a href="/docs/concepts/versions/index.md" data-astro-cid-ztrwvmat>View as Markdown</a></div><p class="updated" data-astro-cid-ztrwvmat>Last updated <time datetime="2026-11-01T15:44:57.000Z" data-astro-cid-ztrwvmat>Nov 1, 2026</time></p></div><nav aria-label="Previous and next pages" data-slot="pagination" class="pager" data-astro-cid-ccykbmgk="true" data-astro-cid-uzg2fj5b><a href="/docs/concepts/datasources-and-variables/" rel="prev" class="pager-card pager-prev" data-astro-cid-uzg2fj5b><span class="pager-label" data-astro-cid-uzg2fj5b><span aria-hidden="true" class="pager-arrow" data-astro-cid-uzg2fj5b>←</span> Previous</span><span class="pager-title" data-astro-cid-uzg2fj5b>Datasources and variables</span></a><a href="/docs/operate/production/" rel="next" class="pager-card pager-next" data-astro-cid-uzg2fj5b><span class="pager-label" data-astro-cid-uzg2fj5b>Next <span aria-hidden="true" class="pager-arrow" data-astro-cid-uzg2fj5b>→</span></span><span class="pager-title" data-astro-cid-uzg2fj5b>Run in production</span></a></nav><footer class="footer" data-astro-cid-m3vkoxit><div class="brand" data-astro-cid-m3vkoxit><span class="wordmark" translate="no" style="font-size: 15px" data-astro-cid-abbawp5v><span class="slash" data-astro-cid-abbawp5v>/</span>observe</span><span data-astro-cid-m3vkoxit>Open source under Apache-2.0.</span><span data-astro-cid-m3vkoxit>Grafana is a trademark of Grafana Labs. SlashObserve is not affiliated with or endorsed by Grafana Labs.</span></div><nav aria-label="Project" class="project" data-astro-cid-m3vkoxit><a href="https://github.com/slashobserve/slashobserve" data-astro-cid-m3vkoxit>GitHub</a><a href="https://github.com/slashobserve/slashobserve/releases" data-astro-cid-m3vkoxit>Changelog</a><a href="https://github.com/slashobserve/slashobserve/blob/main/LICENSE" data-astro-cid-m3vkoxit>License</a><span class="mono site-commit" data-astro-cid-r6bzul4k>f04d686</span></nav></footer></div></main><aside class="docs-rail" aria-label="On this page" data-nb-toc-scroll-host data-astro-cid-ccykbmgk><div data-slot="toc" data-nb-toc class="toc-container" data-astro-cid-ccykbmgk="true"><h2 class="mb-3 text-[13px] leading-5 font-semibold text-[var(--fg)]">On this page</h2><nav aria-label="Table of contents" class="relative"><svg data-nb-toc-rail aria-hidden="true" class="pointer-events-none absolute inset-0 h-full w-full overflow-visible" fill="none"><path data-nb-toc-rail-active class="stroke-brand opacity-0 transition-[stroke-dasharray,stroke-dashoffset,opacity] duration-300 ease-[cubic-bezier(0.32,0.72,0,1)] data-[ready=true]:opacity-100 data-[initial=true]:transition-opacity motion-reduce:transition-opacity" stroke-width="2" stroke-linecap="round"></path></svg><ul class="flex list-none flex-col m-0 p-0"><li><a href="#what-a-version-records" data-nb-toc-link data-nb-slug="what-a-version-records" class="grid grid-cols-1 border-s-2 border-border py-1 ps-[14px] text-[13px] leading-5 text-[var(--mfg)] no-underline transition-colors duration-[120ms] hover:text-[var(--fg)] aria-[current=true]:font-medium aria-[current=true]:text-[var(--fg)] motion-reduce:transition-none" style="margin-inline-start: calc(0px - 2px);"><span class="col-start-1 row-start-1 [overflow-wrap:anywhere]">What a version records</span><span aria-hidden="true" class="col-start-1 row-start-1 invisible font-medium [overflow-wrap:anywhere]">What a version records</span></a></li><li><a href="#compare-versions" data-nb-toc-link data-nb-slug="compare-versions" class="grid grid-cols-1 border-s-2 border-border py-1 ps-[14px] text-[13px] leading-5 text-[var(--mfg)] no-underline transition-colors duration-[120ms] hover:text-[var(--fg)] aria-[current=true]:font-medium aria-[current=true]:text-[var(--fg)] motion-reduce:transition-none" style="margin-inline-start: calc(0px - 2px);"><span class="col-start-1 row-start-1 [overflow-wrap:anywhere]">Compare versions</span><span aria-hidden="true" class="col-start-1 row-start-1 invisible font-medium [overflow-wrap:anywhere]">Compare versions</span></a></li><li><a href="#restore-a-version" data-nb-toc-link data-nb-slug="restore-a-version" class="grid grid-cols-1 border-s-2 border-border py-1 ps-[14px] text-[13px] leading-5 text-[var(--mfg)] no-underline transition-colors duration-[120ms] hover:text-[var(--fg)] aria-[current=true]:font-medium aria-[current=true]:text-[var(--fg)] motion-reduce:transition-none" style="margin-inline-start: calc(0px - 2px);"><span class="col-start-1 row-start-1 [overflow-wrap:anywhere]">Restore a version</span><span aria-hidden="true" class="col-start-1 row-start-1 invisible font-medium [overflow-wrap:anywhere]">Restore a version</span></a></li><li><a href="#duplicate-a-dashboard" data-nb-toc-link data-nb-slug="duplicate-a-dashboard" class="grid grid-cols-1 border-s-2 border-border py-1 ps-[14px] text-[13px] leading-5 text-[var(--mfg)] no-underline transition-colors duration-[120ms] hover:text-[var(--fg)] aria-[current=true]:font-medium aria-[current=true]:text-[var(--fg)] motion-reduce:transition-none" style="margin-inline-start: calc(0px - 2px);"><span class="col-start-1 row-start-1 [overflow-wrap:anywhere]">Duplicate a dashboard</span><span aria-hidden="true" class="col-start-1 row-start-1 invisible font-medium [overflow-wrap:anywhere]">Duplicate a dashboard</span></a></li><li><a href="#comments" data-nb-toc-link data-nb-slug="comments" class="grid grid-cols-1 border-s-2 border-border py-1 ps-[14px] text-[13px] leading-5 text-[var(--mfg)] no-underline transition-colors duration-[120ms] hover:text-[var(--fg)] aria-[current=true]:font-medium aria-[current=true]:text-[var(--fg)] motion-reduce:transition-none" style="margin-inline-start: calc(0px - 2px);"><span class="col-start-1 row-start-1 [overflow-wrap:anywhere]">Comments</span><span aria-hidden="true" class="col-start-1 row-start-1 invisible font-medium [overflow-wrap:anywhere]">Comments</span></a></li></ul></nav></div><script type="module" src="/_astro/TOC.astro_astro_type_script_index_0_lang.CSH9IvxI.js"></script></aside></div><dialog id="docs-drawer" data-mobile-sidebar data-state="closed" class="drawer" aria-label="Site navigation" data-astro-cid-6lm62vyo><div class="panel" data-astro-cid-6lm62vyo><div class="top" data-astro-cid-6lm62vyo><a class="home" href="/" aria-label="SlashObserve home" data-astro-cid-6lm62vyo><span class="wordmark" translate="no" style="font-size: 20px" data-astro-cid-abbawp5v><span class="slash" data-astro-cid-abbawp5v>/</span>observe</span></a><button type="button" class="docs-icon-btn" data-close-sidebar aria-label="Close navigation" data-astro-cid-6lm62vyo><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" data-astro-cid-6lm62vyo><path d="M6 6l12 12M18 6 6 18" data-astro-cid-6lm62vyo></path></svg></button></div><nav aria-label="Site" class="site-nav" data-astro-cid-6lm62vyo><a href="/build/" data-astro-cid-6lm62vyo>Build</a><a href="/grafana/" data-astro-cid-6lm62vyo>Coming from Grafana</a><a href="/signals/" data-astro-cid-6lm62vyo>Signals</a><a href="https://github.com/slashobserve/slashobserve" data-astro-cid-6lm62vyo><svg width="15" height="15" viewBox="0 0 24 24" aria-hidden="true" fill="currentColor"><path d="M12 .5C5.65.5.5 5.65.5 12c0 5.08 3.29 9.39 7.86 10.91.58.1.79-.25.79-.56v-2.18c-3.2.7-3.87-1.36-3.87-1.36-.53-1.34-1.29-1.7-1.29-1.7-1.05-.72.08-.7.08-.7 1.16.08 1.77 1.19 1.77 1.19 1.03 1.77 2.7 1.26 3.36.96.1-.75.4-1.26.73-1.55-2.55-.29-5.24-1.28-5.24-5.69 0-1.26.45-2.29 1.19-3.1-.12-.29-.51-1.46.11-3.05 0 0 .97-.31 3.18 1.18.92-.26 1.91-.39 2.89-.39.98 0 1.97.13 2.89.39 2.21-1.49 3.18-1.18 3.18-1.18.62 1.59.23 2.76.11 3.05.74.81 1.19 1.84 1.19 3.1 0 4.42-2.69 5.4-5.25 5.68.41.36.78 1.07.78 2.15v3.19c0 .31.21.67.8.56C20.22 21.39 23.5 17.08 23.5 12 23.5 5.65 18.35.5 12 .5z"></path></svg>GitHub</a></nav><div class="rule" role="presentation" data-astro-cid-6lm62vyo></div><div data-nb-sidebar-drawer-slot class="slot" data-astro-cid-6lm62vyo></div></div></dialog><script type="module" src="/_astro/DocsDrawer.astro_astro_type_script_index_0_lang.PpnezgOh.js"></script><script> (function () { function centerActive(sidebar, active) { const sr = sidebar.getBoundingClientRect(); const ar = active.getBoundingClientRect(); sidebar.scrollTop += ar.top - sr.top - sr.height / 2 + ar.height / 2; } function restore() { try { const sidebar = document.querySelector("[data-nb-sidebar-tree]"); if (!sidebar) return; const content = sidebar.querySelector("[data-nb-sidebar]"); if (!content) return; const state = JSON.parse(sessionStorage.getItem("sidebar-state") || "null"); const active = sidebar.querySelector("[aria-current='page']"); if (sidebar.clientHeight === 0) return; if (state && typeof state.scroll === "number") { sidebar.scrollTop = state.scroll; if (active) { const sr = sidebar.getBoundingClientRect(); const ar = active.getBoundingClientRect(); if (ar.top < sr.top || ar.bottom > sr.bottom) centerActive(sidebar, active); } } else if (active) { centerActive(sidebar, active); } } catch (_) {} } restore(); if (!window.__nbSidebarRestoreBound) { window.__nbSidebarRestoreBound = true; document.addEventListener("astro:after-swap", restore); } })(); </script><dialog data-slot="search-dialog" data-dialog class="dialog fixed inset-0 z-50 m-0 h-full w-full max-h-full max-w-full bg-transparent p-0" aria-label="Search documentation" data-search-dialog="true" data-astro-cid-xdz27oll><div data-slot="dialog-content" class="dialog-frame pointer-events-none flex h-full items-start justify-center" data-astro-cid-7nd477ki><div class="dialog-box pointer-events-auto flex flex-col overflow-hidden" data-astro-cid-7nd477ki><div class="search-input-row"><svg width="1em" height="1em" viewBox="0 0 256 256" class="search-input-icon" data-icon="ph:magnifying-glass"><path fill="currentColor" d="m229.66 218.34l-50.07-50.06a88.11 88.11 0 1 0-11.31 11.31l50.06 50.07a8 8 0 0 0 11.32-11.32M40 112a72 72 0 1 1 72 72a72.08 72.08 0 0 1-72-72"></path></svg><input data-search-input role="combobox" aria-label="Search docs" aria-expanded="false" aria-haspopup="listbox" aria-autocomplete="list" aria-controls="search-listbox" type="text" placeholder="Search docs" class="search-input" autocomplete="off" spellcheck="false" autocorrect="off" autocapitalize="none"><button data-slot="dialog-close" data-dialog-close type="button" class="search-esc search-key" aria-label="Close search">Esc</button><script type="module" src="/_astro/DialogClose.astro_astro_type_script_index_0_lang.DdYk3psb.js"></script><button data-slot="dialog-close" data-dialog-close type="button" class="search-cancel">Cancel</button></div><div class="search-body"><p data-search-empty role="status" class="search-status">Search pages and headings.</p><div data-search-results role="listbox" id="search-listbox" aria-label="Results" aria-orientation="vertical" hidden></div></div><div class="search-footer" aria-hidden="true"><span><kbd class="search-key">↑</kbd> <kbd class="search-key">↓</kbd> to navigate</span><span><kbd class="search-key">↵</kbd> to open</span><span><kbd class="search-key">Esc</kbd> to close</span></div></div></div></dialog><script type="module" src="/_astro/Dialog.astro_astro_type_script_index_0_lang.r9cKhfIv.js"></script><script type="module" src="/_astro/SearchDialog.astro_astro_type_script_index_0_lang._8JT2_TX.js"></script><script type="module" src="/_astro/BaseLayout.astro_astro_type_script_index_0_lang.CXDGMZI9.js"></script></body></html>