Agent Filesystem
Each agent runs in a sandboxed filesystem. Both the / path and the current working directory of an agent point to the root of this sandboxed filesystem.
There is no way for an agent to access files outside its own filesystem.
Accessing the filesystem
TypeScript
For TypeScript agents, use node:fs or node:fs/promises to work with files.
In Golem 1.5, the QuickJS runtime provides a comprehensive filesystem API, so standard operations such as reading, writing, checking existence, creating directories, and listing directories are available.
Initial File System
The Initial File System (IFS) refers to all files that are present in the agent filesystem before the agent is started. These can include configuration files, static assets and other things that you want to include with your agent.
The IFS is configured on the level of a component, meaning that all agents created from a given component + version will always start with the
same filesystem. To configure the IFS, include a files section in your golem.yaml
If you are using profiles in your golem.yaml, you currently have to include the files section in each of your profiles when overriding.
components:
example:filesystem:
template: ts
files:
- sourcePath: ./files/foo.txt
targetPath: /foobar.txt
permissions: read-write
- sourcePath: ./files/bar.txt
targetPath: /bar.txt
permissions: read-onlyAfter deploying the component, any new agents created will have the file /foobar.txt (and ./foobar.txt as the agent’s initial current directory is the root) available to them.
The file /bar.txt on the other hand is only available for reading. Trying to open the file for writing will fail with a language-dependent error.
Updating an agent
Updating an agent that uses IFS requires some special consideration depending on the update mode you choose:
- Automatic updates: When using automatic updates the old agent invocations are replayed on top of the new IFS. This means that the agent should produce exactly the same results and side effects as it did with the old IFS. For example, changing the format of a file will work without issues, but changing a file that gets read by the agent and returned to the user will likely lead to divergence. In such cases a manual update might be necessary.
- Manual updates: When using manual updates, you are responsible for saving and restoring the content of files in the agent filesystem. You can
use the
golem:api/save-snapshotfunction to persist the files and later restore / migrate them usinggolem:api/load-snapshot.
Externally accessing agent files
It is easy to expose files on the agent filesystem via HTTP using code-first route definitions.
For example, we can define an agent with a download endpoint that serves files:
TypeScript
import * as fs from 'node:fs';
import { BaseAgent, agent, endpoint, UnstructuredBinary } from '@golemcloud/golem-ts-sdk';
@agent({ mount: "/files/{name}" })
class FileServerAgent extends BaseAgent {
constructor(readonly name: string) {
super();
}
@endpoint({ get: "/download/{path}" })
downloadFile(path: string): UnstructuredBinary {
try {
const buffer = fs.readFileSync(`/web/${path}`);
let contentType = 'application/octet-stream';
if (path.endsWith('.html')) {
contentType = 'text/html';
} else if (path.endsWith('.js')) {
contentType = 'application/javascript';
}
return UnstructuredBinary.fromInline(buffer, contentType);
} catch (err) {
return UnstructuredBinary.fromInline(
new TextEncoder().encode(`Not found! (${err})`),
'text/plain',
);
}
}
}With the @endpoint / #[endpoint] annotations, the HTTP route is automatically registered — no separate API mapping is needed. The agent above will serve files at GET /files/{name}/download/{path}.
For more information about defining code-first HTTP endpoints for agents, check the dedicated documentation page.
For serving static content, it is good practice to define a separate agent in an ephemeral component that is only responsible for serving files. This way the file-serving endpoints will not ever block by waiting for a stateful agent to process their requests.