<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>vigoo&#x27;s software development blog - durability</title>
    <link rel="self" type="application/atom+xml" href="https://blog.vigoo.dev/tags/durability/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://blog.vigoo.dev"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-04-15T00:00:00+00:00</updated>
    <id>https://blog.vigoo.dev/tags/durability/atom.xml</id>
    <entry xml:lang="en">
        <title>Golem 1.5 features - Part 6: User-defined snapshotting</title>
        <published>2026-04-15T00:00:00+00:00</published>
        <updated>2026-04-15T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Daniel Vigovszky
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.vigoo.dev/posts/golem15-part6-user-defined-snapshotting/"/>
        <id>https://blog.vigoo.dev/posts/golem15-part6-user-defined-snapshotting/</id>
        
        <content type="html" xml:base="https://blog.vigoo.dev/posts/golem15-part6-user-defined-snapshotting/">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;I am writing a series of &lt;em&gt;short&lt;&#x2F;em&gt; posts showcasing the new features of &lt;strong&gt;Golem 1.5&lt;&#x2F;strong&gt;, to be released at the end of April, 2026. The episodes of this series will be short and assume the reader knows what Golem is. Check my &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.vigoo.dev&#x2F;tags&#x2F;golem&#x2F;&quot;&gt;other Golem-related posts&lt;&#x2F;a&gt; for more information!&lt;&#x2F;p&gt;
&lt;p&gt;Parts released so far:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;posts&#x2F;golem15-part1-code-first-routes&quot;&gt;Part 1: Code-first routes&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;posts&#x2F;golem15-part2-webhooks&quot;&gt;Part 2: Webhooks&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;posts&#x2F;golem15-part3-mcp&quot;&gt;Part 3: MCP&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;posts&#x2F;golem15-part4-nodejs&quot;&gt;Part 4: Node.js compatibility&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;posts&#x2F;golem15-part5-scala&quot;&gt;Part 5: Scala support&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;posts&#x2F;golem15-part6-user-defined-snapshotting&quot;&gt;Part 6: User-defined snapshotting&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;snapshot-based-recovery&quot;&gt;Snapshot based recovery&lt;&#x2F;h2&gt;
&lt;p&gt;One of the primary features of &lt;strong&gt;Golem&lt;&#x2F;strong&gt; is that it can recover an agent&#x27;s state transparently. Under the hood this is implemented by replaying an &lt;strong&gt;oplog&lt;&#x2F;strong&gt; that records every side-effect&#x27;s results among other things, so we can reconstruct the application&#x27;s state on recovery. This works perfectly but can be slow if the agent does something CPU-heavy, or it simply have been running long enough to accumulate a long oplog.&lt;&#x2F;p&gt;
&lt;p&gt;One way to fix this slowness is to do periodic &lt;strong&gt;snapshots&lt;&#x2F;strong&gt; - a fully automated snapshotting mechanism would take the snapshot of the agent&#x27;s memory, file system etc., and during recovery we would only need to replay the part of the oplog that happened &lt;em&gt;after&lt;&#x2F;em&gt; the last snapshot. We did experiments with  automatic snapshotting like this, but it is not part of Golem at the time of writing yet.&lt;&#x2F;p&gt;
&lt;p&gt;In &lt;strong&gt;Golem 1.5&lt;&#x2F;strong&gt; we introduce a new feature that is in some ways more limited, but one can argue that for many use cases even more powerful than the fully automatic snapshotting.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;user-defined-snapshotting&quot;&gt;User-defined snapshotting&lt;&#x2F;h3&gt;
&lt;p&gt;Instead of snapshotting automatically the whole memory and other state of an agent, an agent can &lt;strong&gt;opt-in&lt;&#x2F;strong&gt; to snapshot support by implementing a pair of load&#x2F;save functions. With this the agent only serializes the actual state that matters - but it is no longer transparent, it is something the developer must think through.&lt;&#x2F;p&gt;
&lt;p&gt;Note that the load&#x2F;save snapshot functions are not really new in Golem 1.5 - we had it since the first release, but previously it was only used as a way to migrate to new versions of an agent when the automatic update was not possible (code leading to diverging replays).&lt;&#x2F;p&gt;
&lt;p&gt;The following example shows how the manually implemented save&#x2F;load pair would look like for the default template&#x27;s &lt;code&gt;CounterAgent&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;div class=&quot;code-tabs&quot; id=&quot;codetabs-1&quot;&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;agent&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; CounterAgent&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; BaseAgent&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    private readonly&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;: string&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    private&lt;&#x2F;span&gt;&lt;span&gt; value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;: number =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;    &#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    override async&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; saveSnapshot&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; Promise&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;Uint8Array&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;        const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; snapshot&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; Uint8Array&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;        const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; view&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; DataView&lt;&#x2F;span&gt;&lt;span&gt;(snapshot.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;buffer&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        view.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;setUint32&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt; this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt; snapshot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    override async&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; loadSnapshot&lt;&#x2F;span&gt;&lt;span&gt;(bytes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; Uint8Array&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; Promise&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;void&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span&gt; view&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; DataView&lt;&#x2F;span&gt;&lt;span&gt;(bytes.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;buffer&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;        this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; view.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;getUint32&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #986801;&quot;&gt;#[agent_implementation()]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; CounterImpl&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;    _name&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;    count&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #986801;&quot;&gt;#[agent_implementation()]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt; CounterAgent&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; for&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt; CounterImpl&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;    &#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; load_snapshot&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt; arr&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span&gt;] =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;try_into&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50A14F;&quot;&gt; &amp;quot;Expected a 4-byte long snapshot&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)?;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span&gt;.count =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;from_be_bytes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;arr&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;        Ok&lt;&#x2F;span&gt;&lt;span&gt;(())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; save_snapshot&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;        Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.count.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;to_be_bytes&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;to_vec&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@agentImplementation()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;final class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; SnapshotCounterImpl&lt;&#x2F;span&gt;&lt;span&gt;(@unused &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;private val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt; name&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; SnapshotCounter&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;  private var&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt; value&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; Int&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; saveSnapshot&lt;&#x2F;span&gt;&lt;span&gt;():&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; Future&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;Array&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;Byte&lt;&#x2F;span&gt;&lt;span&gt;]] =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;    Future&lt;&#x2F;span&gt;&lt;span&gt;.successful(encodeU32(value))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; loadSnapshot&lt;&#x2F;span&gt;&lt;span&gt;(bytes:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; Array&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;Byte&lt;&#x2F;span&gt;&lt;span&gt;]):&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; Future&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;Unit&lt;&#x2F;span&gt;&lt;span&gt;] =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;    Future&lt;&#x2F;span&gt;&lt;span&gt;.successful {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      value = decodeU32(bytes)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;  private def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; encodeU32&lt;&#x2F;span&gt;&lt;span&gt;(i:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; Int&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; Array&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;Byte&lt;&#x2F;span&gt;&lt;span&gt;] =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;    Array&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      ((i &amp;gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 24&lt;&#x2F;span&gt;&lt;span&gt;) &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0xff&lt;&#x2F;span&gt;&lt;span&gt;).toByte,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      ((i &amp;gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 16&lt;&#x2F;span&gt;&lt;span&gt;) &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0xff&lt;&#x2F;span&gt;&lt;span&gt;).toByte,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      ((i &amp;gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span&gt;) &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0xff&lt;&#x2F;span&gt;&lt;span&gt;).toByte,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      (i &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0xff&lt;&#x2F;span&gt;&lt;span&gt;).toByte&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;  private def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; decodeU32&lt;&#x2F;span&gt;&lt;span&gt;(bytes:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; Array&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;Byte&lt;&#x2F;span&gt;&lt;span&gt;]):&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; Int&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ((bytes(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;) &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0xff&lt;&#x2F;span&gt;&lt;span&gt;) &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 24&lt;&#x2F;span&gt;&lt;span&gt;) |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      ((bytes(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;) &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0xff&lt;&#x2F;span&gt;&lt;span&gt;) &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 16&lt;&#x2F;span&gt;&lt;span&gt;) |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      ((bytes(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;) &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0xff&lt;&#x2F;span&gt;&lt;span&gt;) &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span&gt;) |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      (bytes(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;) &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0xff&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;moonbit&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F;|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; Counter agent with snapshot persistence&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;#derive.agent&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; CounterAgent&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;  name&lt;&#x2F;span&gt;&lt;span&gt; : &lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;  mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt; value&lt;&#x2F;span&gt;&lt;span&gt; : &lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;UInt64&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;&#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt; @agents.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;Snapshottable&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; for&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; CounterAgent&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; with&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; save_snapshot&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; Bytes&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt; snapshot&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; Bytes&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;make&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt; value&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.value&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;  snapshot&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;] = ((&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt; &amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 56&lt;&#x2F;span&gt;&lt;span&gt;) &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0xFF&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;to_byte&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;  snapshot&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;] = ((&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt; &amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 48&lt;&#x2F;span&gt;&lt;span&gt;) &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0xFF&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;to_byte&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;  snapshot&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;] = ((&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt; &amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 40&lt;&#x2F;span&gt;&lt;span&gt;) &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0xFF&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;to_byte&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;  snapshot&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;] = ((&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt; &amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 32&lt;&#x2F;span&gt;&lt;span&gt;) &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0xFF&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;to_byte&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;  snapshot&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;] = ((&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt; &amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 24&lt;&#x2F;span&gt;&lt;span&gt;) &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0xFF&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;to_byte&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;  snapshot&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;] = ((&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt; &amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 16&lt;&#x2F;span&gt;&lt;span&gt;) &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0xFF&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;to_byte&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;  snapshot&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;] = ((&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt; &amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span&gt;) &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0xFF&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;to_byte&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;  snapshot&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;7&lt;&#x2F;span&gt;&lt;span&gt;] = (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0xFF&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;to_byte&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;  snapshot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt; @agents.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;Snapshottable&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; for&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; CounterAgent&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; with&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; load_snapshot&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;  self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;  bytes&lt;&#x2F;span&gt;&lt;span&gt; : &lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;Bytes&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;Unit&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;] {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;() !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; Err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50A14F;&quot;&gt;&amp;quot;Invalid snapshot length: expected 8, got &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt; value&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;bytes&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;to_uint64&lt;&#x2F;span&gt;&lt;span&gt;() &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 56&lt;&#x2F;span&gt;&lt;span&gt;) |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;bytes&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;to_uint64&lt;&#x2F;span&gt;&lt;span&gt;() &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 48&lt;&#x2F;span&gt;&lt;span&gt;) |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;bytes&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;to_uint64&lt;&#x2F;span&gt;&lt;span&gt;() &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 40&lt;&#x2F;span&gt;&lt;span&gt;) |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;bytes&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;to_uint64&lt;&#x2F;span&gt;&lt;span&gt;() &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 32&lt;&#x2F;span&gt;&lt;span&gt;) |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;bytes&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;to_uint64&lt;&#x2F;span&gt;&lt;span&gt;() &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 24&lt;&#x2F;span&gt;&lt;span&gt;) |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;bytes&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;to_uint64&lt;&#x2F;span&gt;&lt;span&gt;() &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 16&lt;&#x2F;span&gt;&lt;span&gt;) |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;bytes&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;to_uint64&lt;&#x2F;span&gt;&lt;span&gt;() &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span&gt;) |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;    bytes&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;7&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;to_uint64&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;  self&lt;&#x2F;span&gt;&lt;span&gt;.value =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt; value&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;  Ok&lt;&#x2F;span&gt;&lt;span&gt;(())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;div&gt;
&lt;h3 id=&quot;recovery-configuration&quot;&gt;Recovery configuration&lt;&#x2F;h3&gt;
&lt;p&gt;Defining the pair of snapshotting functions is enough to use these for &lt;strong&gt;updating agents&lt;&#x2F;strong&gt; but it does not enable &lt;strong&gt;snapshot-based recovery&lt;&#x2F;strong&gt;. We can configure that through the agent annotation:&lt;&#x2F;p&gt;
&lt;div class=&quot;code-tabs&quot; id=&quot;codetabs-2&quot;&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;agent&lt;&#x2F;span&gt;&lt;span&gt;({&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt; snapshotting&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt; periodic&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50A14F;&quot;&gt; &amp;#39;5s&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; } })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; CounterAgent&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; BaseAgent&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #986801;&quot;&gt;#[agent_definition(snapshotting &lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50A14F;&quot;&gt; &amp;quot;periodic(5s)&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;trait&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; CounterAgent&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;    &#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@agentDefinition(snapshotting =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50A14F;&quot;&gt; &amp;quot;periodic(5 seconds)&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;trait&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; CounterAgent&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; BaseAgent&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;moonbit&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;#derive.agent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;snapshotting&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50A14F;&quot;&gt;&amp;quot;periodic(5)&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; CounterAgent&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;div&gt;
&lt;p&gt;The options can be &lt;code&gt;disabled&lt;&#x2F;code&gt;, &lt;code&gt;enabled&lt;&#x2F;code&gt; to use the server-side default (which is set to disabled by default), &lt;code&gt;every(N)&lt;&#x2F;code&gt; meaning snapshot after every &lt;em&gt;Nth&lt;&#x2F;em&gt; oplog entry, or &lt;code&gt;periodic(5s)&lt;&#x2F;code&gt; to make a snapshot every 5 seconds.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;default-implementation&quot;&gt;Default implementation&lt;&#x2F;h3&gt;
&lt;p&gt;Having snapshot-based recovery is really useful but we realized that writing these manual serialization functions may be too painful. In &lt;strong&gt;Golem 1.5&lt;&#x2F;strong&gt; each supported language has a mechanism to opt-in for a &lt;strong&gt;default snapshotting implementation&lt;&#x2F;strong&gt; while still allowing defining a fully custom pair of methods like we&#x27;ve seen above.&lt;&#x2F;p&gt;
&lt;div class=&quot;code-tabs&quot; id=&quot;codetabs-3&quot;&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; CounterAgent&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; BaseAgent&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; For TypeScript, simply NOT defining loadSnapshot and saveSnapshot will &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; provide a default implementation that saves&#x2F;loads the agent class itself &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; as JSON&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #986801;&quot;&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;Serialize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt; Deserialize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; CounterAgentImpl&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;    count&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #986801;&quot;&gt;    #[serde(skip)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;    _id&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #986801;&quot;&gt;#[agent_implementation]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt; CounterAgent&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; for&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt; CounterAgentImpl&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Not overriding save_snapshot and load_snapshot will provide the &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;    &#x2F;&#x2F; default implementation, if the agent type has serde Serialize &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;    &#x2F;&#x2F; and Deserialize instances&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;&#x2F;&#x2F; For Scala we need to explicitly define the state to be serialized&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;&#x2F;&#x2F; and mix-in the `Snapshotted[T]` trait&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;final case class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; SnapshotCounterState&lt;&#x2F;span&gt;&lt;span&gt;(value:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; Int&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;object&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; SnapshotCounterState&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;  implicit val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt; schema&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; Schema&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;SnapshotCounterState&lt;&#x2F;span&gt;&lt;span&gt;] =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; Schema&lt;&#x2F;span&gt;&lt;span&gt;.derived&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@agentImplementation()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;final class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; CounterAgentImpl&lt;&#x2F;span&gt;&lt;span&gt;(@unused &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;private val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt; name&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; CounterAgent&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    with&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; Snapshotted&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;SnapshotCounterState&lt;&#x2F;span&gt;&lt;span&gt;] {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;  var&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt; state&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; SnapshotCounterState&lt;&#x2F;span&gt;&lt;span&gt;                                 =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; SnapshotCounterState&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;  val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt; stateSchema&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; Schema&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;SnapshotCounterState&lt;&#x2F;span&gt;&lt;span&gt;] =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; SnapshotCounterState&lt;&#x2F;span&gt;&lt;span&gt;.schema&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;moonbit&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;#derive.agent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;snapshotting&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50A14F;&quot;&gt;&amp;quot;every_n(1)&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt; Counter&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;  name&lt;&#x2F;span&gt;&lt;span&gt; : &lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;  mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt; value&lt;&#x2F;span&gt;&lt;span&gt; : &lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;UInt64&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;ToJson&lt;&#x2F;span&gt;&lt;span&gt;, @json.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;FromJson&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;&#x2F;&#x2F; If an agent derives ToJson&#x2F;FromJson and has no manual Snapshottable instance,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;&#x2F;&#x2F; the SDK provides a default implementation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;div&gt;
&lt;h3 id=&quot;observability&quot;&gt;Observability&lt;&#x2F;h3&gt;
&lt;p&gt;Using the default snapshotting implementation, or implementing one by hand that uses the &lt;code&gt;application&#x2F;json&lt;&#x2F;code&gt; content type has one more nice feature: when observing the &lt;strong&gt;oplog&lt;&#x2F;strong&gt; of an agent for debugging purposes, we can see the snapshot entries with the serialized JSON state!&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s see an example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#00021:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;INVOKE COMPLETED&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          at:                2026-04-15T13:19:04.618Z&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          consumed fuel:     200796&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          result:            AgentMethod(AgentInvocationOutputParameters { output: Tuple(ElementValues { elements: [] }) })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#00022:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;SNAPSHOT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          at:                2026-04-15T13:19:04.619Z&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          data:              {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;quot;principal&amp;quot;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;quot;tag&amp;quot;: &amp;quot;anonymous&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;quot;state&amp;quot;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;quot;name&amp;quot;: &amp;quot;test1&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;quot;value&amp;quot;: 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;quot;version&amp;quot;: 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#00023:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ENQUEUED INVOCATION increment&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          at:                2026-04-15T13:19:05.355Z&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          idempotency key:   3da50be7-f426-427b-8f50-a05ced00d20a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</content>
        
    </entry>
</feed>
