Skip to Content
How-To GuidesMoonBitFile I/O in MoonBit Golem Agents

File I/O in MoonBit Golem Agents

Overview

MoonBit Golem agents can access files provisioned into the agent’s filesystem via golem.yaml. File access uses the SDK’s @fs package (golemcloud/golem_sdk/filesystem), which provides convenience functions and re-exports of the necessary types.

To provision files into an agent’s filesystem, See the golem-add-initial-files guide.

Prerequisites: Adding the Dependency

Add the filesystem package to your agent’s moon.pkg:

import { "golemcloud/golem_sdk/filesystem" @fs, }

No WIT changes or binding regeneration is needed — the SDK already includes the filesystem imports.

File Provisioning

Files must first be provisioned via golem.yaml (see golem-add-initial-files guide). Provisioned files are available through preopened directories. The preopened directory for provisioned files is typically mounted at /.

Reading Files

Getting the Root Directory

Use @fs.get_root_dir() to get the preopened directory at /:

///| fn get_root() -> @fs.Descriptor { @fs.get_root_dir().unwrap() }

Or use @fs.get_preopened_dir(path) for a specific mount point.

Reading a Text File

Use the convenience function @fs.read_string:

///| fn read_file(path : String) -> String!Error { let root = @fs.get_root_dir().unwrap() @fs.read_string(root, path).unwrap() }

Reading a Binary File

Use @fs.read_bytes:

///| fn read_binary(path : String) -> FixedArray[Byte]!Error { let root = @fs.get_root_dir().unwrap() @fs.read_bytes(root, path).unwrap() }

Writing Files

Only files provisioned with read-write permission (or files in non-provisioned paths) can be written to.

Writing a Text File

///| fn write_file(path : String, content : String) -> Unit!Error { let root = @fs.get_root_dir().unwrap() @fs.write_string(root, path, content).unwrap() }

Writing Binary Data

///| fn write_binary(path : String, data : FixedArray[Byte]) -> Unit!Error { let root = @fs.get_root_dir().unwrap() @fs.write_bytes(root, path, data).unwrap() }

Listing Directory Entries

///| fn list_dir(path : String) -> Array[String]!Error { let root = @fs.get_root_dir().unwrap() @fs.list_directory(root, path).unwrap() }

Low-Level Access

For more control (e.g., opening with specific flags, using streams, stat), use the re-exported types directly from @fs:

///| fn open_read_only(path : String) -> @fs.Descriptor!Error { let root = @fs.get_root_dir().unwrap() root .open_at( @fs.PathFlags::default(), path, @fs.OpenFlags::default(), @fs.DescriptorFlags::default().set(@fs.READ), ) .unwrap() }

Available re-exported types from @fs: Descriptor, DirectoryEntryStream, DescriptorFlags, PathFlags, OpenFlags, ErrorCode, DirectoryEntry, DescriptorStat, NewTimestamp, DescriptorType, Advice, MetadataHashValue, DescriptorFlagsFlag (READ, WRITE, etc.), PathFlagsFlag, OpenFlagsFlag (CREATE, DIRECTORY, EXCLUSIVE, TRUNCATE).

Complete Agent Example

/// File reader agent that reads provisioned files #derive.agent struct FileReader { name : String } fn FileReader::new(name : String) -> FileReader { { name } } /// Reads the content of a provisioned text file pub fn FileReader::read_text(self : Self, path : String) -> String { let _ = self let root = @fs.get_root_dir().unwrap() @fs.read_string(root, path).unwrap() } /// Writes content to a file (must be writable) pub fn FileReader::write_text(self : Self, path : String, content : String) -> Unit { let _ = self let root = @fs.get_root_dir().unwrap() @fs.write_string(root, path, content).unwrap() } /// Lists entries in a directory pub fn FileReader::list_dir(self : Self, path : String) -> Array[String] { let _ = self let root = @fs.get_root_dir().unwrap() @fs.list_directory(root, path).unwrap() }

Key Constraints

  • Files provisioned via golem-add-initial-files with read-only permission cannot be written to
  • The filesystem is per-agent-instance — each agent has its own isolated filesystem
  • File changes within an agent are persistent across invocations (durable state)
  • All paths are relative to a preopened directory descriptor — there is no global filesystem root; you must obtain a descriptor via get_root_dir() or get_preopened_dir(path)
Last updated on