Skip to main content

Overview

Serialization is a process of converting complex data structures or objects (e.g., agents, memories, or tools) into a format that can be easily stored, transmitted, and reconstructed later. Think of it as creating a blueprint of your object that can be used to rebuild it exactly as it was. BeeAI framework provides robust serialization capabilities through its built-in Serializer class that enables:
  • 💾 Persistence: Store agent state, memory, tools, and other components
  • 🔄 Transmission: Send complex objects across network boundaries or processes
  • 📦 Snapshots: Create point-in-time captures of component state
  • 🔧 Reconstruction: Rebuild objects from their serialized representation
Example coming soon
import { Serializer } from "beeai-framework/serializer/serializer";

const original = new Date("2024-01-01T00:00:00.000Z");
const serialized = await Serializer.serialize(original);
const deserialized = await Serializer.deserialize(serialized);

console.info(deserialized instanceof Date); // true
console.info(original.toISOString() === deserialized.toISOString()); // true


Core Concepts

Serializable Class

Most framework components implement the Serializable class with these key methods:
MethodPurpose
createSnapshot()Captures the current state
loadSnapshot(snapshot)Applies a snapshot to the current instance
fromSnapshot(snapshot)Creates a new instance from a snapshot (static)
fromSerialized(data)Creates a new instance from serialized data (static)

Serialization Process

The serialization process involves:
  1. Converting complex objects into a format that preserves their structure and data
  2. Including type information to enable proper reconstruction
  3. Managing references to maintain object identity across serialization boundaries
  4. Handling special cases like circular references and custom types

Basic Usage

Serializing framework components

Most BeeAI components can be serialized out of the box. Here’s an example using memory:
Example coming soon
import { TokenMemory } from "beeai-framework/memory/tokenMemory";
import { AssistantMessage, UserMessage } from "beeai-framework/backend/message";

const memory = new TokenMemory();
await memory.add(new UserMessage("What is your name?"));

const serialized = await memory.serialize();
const deserialized = await TokenMemory.fromSerialized(serialized);

await deserialized.add(new AssistantMessage("Bee"));

Most framework components are Serializable.

Advanced Features

Custom Serialization

If you want to serialize a class that the Serializer does not know, you may register it using one of the following options. 1. Register External Classes You can register external classes with the serializer:
Example coming soon
import { Serializer } from "beeai-framework/serializer/serializer";

class MyClass {
  constructor(public readonly name: string) {}
}

Serializer.register(MyClass, {
  // Defines how to transform a class to a plain object (snapshot)
  toPlain: (instance) => ({ name: instance.name }),
  // Defines how to transform a plain object (snapshot) a class instance
  fromPlain: (snapshot) => new MyClass(snapshot.name),

  // optional handlers to support lazy initiation (handling circular dependencies)
  createEmpty: () => new MyClass(""),
  updateInstance: (instance, update) => {
    Object.assign(instance, update);
  },
});

const instance = new MyClass("Bee");
const serialized = await Serializer.serialize(instance);
const deserialized = await Serializer.deserialize<MyClass>(serialized);

console.info(instance);
console.info(deserialized);

2. Implement the Serializable Interface For deeper integration, extend the Serializable class:
Example coming soon
import { Serializable } from "beeai-framework/internals/serializable";

class MyClass extends Serializable {
  constructor(public readonly name: string) {
    super();
  }

  static {
    // register class to the global serializer register
    this.register();
  }

  createSnapshot(): unknown {
    return {
      name: this.name,
    };
  }

  loadSnapshot(snapshot: ReturnType<typeof this.createSnapshot>) {
    Object.assign(this, snapshot);
  }
}

const instance = new MyClass("Bee");
const serialized = await instance.serialize();
const deserialized = await MyClass.fromSerialized(serialized);

console.info(instance);
console.info(deserialized);

Failure to register a class that the Serializer does not know will result in the SerializerError error. BeeAI framework avoids importing all potential classes automatically to prevent increased application size and unnecessary dependencies.

Context matters

Example coming soon
import { UnconstrainedMemory } from "beeai-framework/memory/unconstrainedMemory";
import { UserMessage } from "beeai-framework/backend/message";

// String containing serialized `UnconstrainedMemory` instance with one message in it.
const serialized = `{"__version":"0.0.0","__root":{"__serializer":true,"__class":"Object","__ref":"18","__value":{"target":"UnconstrainedMemory","snapshot":{"__serializer":true,"__class":"Object","__ref":"17","__value":{"messages":{"__serializer":true,"__class":"Array","__ref":"1","__value":[{"__serializer":true,"__class":"SystemMessage","__ref":"2","__value":{"content":{"__serializer":true,"__class":"Array","__ref":"3","__value":[{"__serializer":true,"__class":"Object","__ref":"4","__value":{"type":"text","text":"You are a helpful assistant."}}]},"meta":{"__serializer":true,"__class":"Object","__ref":"5","__value":{"createdAt":{"__serializer":true,"__class":"Date","__ref":"6","__value":"2025-02-06T14:51:01.459Z"}}},"role":"system"}},{"__serializer":true,"__class":"UserMessage","__ref":"7","__value":{"content":{"__serializer":true,"__class":"Array","__ref":"8","__value":[{"__serializer":true,"__class":"Object","__ref":"9","__value":{"type":"text","text":"Hello!"}}]},"meta":{"__serializer":true,"__class":"Object","__ref":"10","__value":{"createdAt":{"__serializer":true,"__class":"Date","__ref":"11","__value":"2025-02-06T14:51:01.459Z"}}},"role":"user"}},{"__serializer":true,"__class":"AssistantMessage","__ref":"12","__value":{"content":{"__serializer":true,"__class":"Array","__ref":"13","__value":[{"__serializer":true,"__class":"Object","__ref":"14","__value":{"type":"text","text":"Hello, how can I help you?"}}]},"meta":{"__serializer":true,"__class":"Object","__ref":"15","__value":{"createdAt":{"__serializer":true,"__class":"Date","__ref":"16","__value":"2025-02-06T14:51:01.459Z"}}},"role":"assistant"}}]}}}}}}`;

// If `Message` was not imported the serialization would fail because the `Message` had no chance to register itself.
const memory = await UnconstrainedMemory.fromSerialized(serialized, {
  // this part can be omitted if all classes used in the serialized string are imported (and have `static` register block) or at least one initiated
  extraClasses: [UserMessage],
});
console.info(memory.messages);


Examples

TypeScript

Explore reference serialization implementations in TypeScript

Python

COMING SOON: Explore reference serialization implementations in Python