As stated in the docs I shared, one thing you missed is each index should share the same storage context in order to persist (I know, a little annoying)
storage_context = StorageContext.from_defaults()
index1 = GPTVectorStoreIndex.from_documents(documents, storage_context=storage_context)
index2 = GPTVectorStoreIndex.from_documents(documents, storage_context=storage_context)
# build graph
graph = ComposableGraph.from_indices(
GPTListIndex,
[index1, index2 ],
index_summaries=[index1_summary, index2_summary],
storage_context=storage_context
)
# set id
graph.root_index.set_index_id("my_id")
# save
graph.root_index.storage_context.persist(persist_dir="./storage")
# load
from llama_index import StorageContext, load_graph_from_storage
storage_context = StorageContext.from_defaults(persist_dir="./storage")
graph = load_graph_from_storage(storage_context, root_id="my_id")