Skip to content

R2 Storage Layout Reference

GSV uses a single Cloudflare R2 bucket (gsv-storage) for persistent storage of agent workspace files, session archives, skill definitions, and media attachments.

Bucket Structure

gsv-storage/
├── agents/{agentId}/
│   ├── AGENTS.md
│   ├── SOUL.md
│   ├── IDENTITY.md
│   ├── USER.md
│   ├── MEMORY.md
│   ├── TOOLS.md
│   ├── HEARTBEAT.md
│   ├── BOOTSTRAP.md
│   ├── memory/
│   │   └── {YYYY-MM-DD}.md
│   ├── sessions/
│   │   ├── {sessionId}.jsonl.gz
│   │   └── {sessionId}-part{timestamp}.jsonl.gz
│   └── skills/
│       └── {skillName}/
│           └── SKILL.md
├── skills/
│   └── {skillName}/
│       └── SKILL.md
└── media/
    └── {sessionKey}/
        └── {uuid}.{ext}

Workspace Files

Workspace files are per-agent markdown files loaded at the start of each LLM call to build the system prompt. All workspace files are optional; absent files are skipped.

Loading Order

Workspace files are loaded in parallel from R2 and assembled into the system prompt in a defined order. The loader reads from the path agents/{agentId}/.

Normal operation order:

OrderFilePrompt SectionCondition
1(base prompt)Core scaffoldAlways
2SOUL.md"Your Soul"File exists
3IDENTITY.md"Your Identity"File exists
4USER.md"About Your Human"File exists
5AGENTS.md"Operating Instructions"File exists
6MEMORY.md"Long-Term Memory"File exists AND session is main session
7memory/{yesterday}.md"Recent Context > Yesterday"File exists
8memory/{today}.md"Recent Context > Today"File exists
9TOOLS.md"Tool Notes"File exists
10HEARTBEAT.md"Heartbeats"File exists and has meaningful content
11Skills"Skills (Mandatory Scan)"Eligible skills exist
12(runtime info)"Runtime"Always

Bootstrap (first-run) order:

When BOOTSTRAP.md exists, it takes priority. The prompt includes the core scaffold, then BOOTSTRAP.md as a commissioning ceremony, followed by SOUL.md, IDENTITY.md, and USER.md if present. Other workspace files are skipped.

File Descriptions

agents/{agentId}/SOUL.md

PropertyValue
FormatMarkdown
ReadEvery LLM call
Written byUser or agent (via workspace write tool)

Core values, personality, and behavioral foundations for the agent.

agents/{agentId}/IDENTITY.md

PropertyValue
FormatMarkdown
ReadEvery LLM call
Written byUser or agent

Name, class designation, emoji, and other identity attributes.

agents/{agentId}/USER.md

PropertyValue
FormatMarkdown
ReadEvery LLM call
Written byUser or agent

Information about the human user the agent serves.

agents/{agentId}/AGENTS.md

PropertyValue
FormatMarkdown
ReadEvery LLM call (normal operation only)
Written byUser or agent

Operating instructions and behavioral guidelines.

agents/{agentId}/MEMORY.md

PropertyValue
FormatMarkdown
ReadEvery LLM call, main session only
Written byUser or agent

Long-term persistent memory. Restricted to main sessions for security — non-main sessions (e.g., DMs from other peers in per-peer mode) do not see this file.

agents/{agentId}/TOOLS.md

PropertyValue
FormatMarkdown
ReadEvery LLM call (normal operation only)
Written byUser or agent

Tool-specific configuration notes and instructions.

agents/{agentId}/HEARTBEAT.md

PropertyValue
FormatMarkdown
ReadEvery LLM call (when non-empty)
Written byUser or agent

Instructions for heartbeat behavior. The file is considered empty (and skipped) if it contains only whitespace, markdown headers with no body text, HTML comments, or horizontal rules.

agents/{agentId}/BOOTSTRAP.md

PropertyValue
FormatMarkdown
ReadEvery LLM call (while file exists)
Written byUser (typically a template)

First-run commissioning ceremony. When present, overrides the normal prompt assembly order. The agent is expected to complete the commissioning and then delete or rename this file.

Daily Memory Files

agents/{agentId}/memory/{YYYY-MM-DD}.md

PropertyValue
FormatMarkdown
Path patternagents/{agentId}/memory/YYYY-MM-DD.md
ReadEvery LLM call (today's and yesterday's files)
Written byCompaction engine, reset memory extraction, or agent

Daily memory files accumulate context extracted during session compaction and pre-reset memory extraction.

Read behavior: The workspace loader reads two daily memory files:

  • Today's date (YYYY-MM-DD from server time)
  • Yesterday's date

Write behavior: Memories are appended with a timestamped section header:

markdown
### Extracted from context compaction (HH:MM)

<extracted memories>

Pre-reset extraction writes to the date of the conversation's last activity (updatedAt), not the current date.

Session Archives

agents/{agentId}/sessions/{sessionId}.jsonl.gz

PropertyValue
FormatJSONL, gzip-compressed
WrittenOn session reset (manual or auto)
ReadOn transcript retrieval

Contains the complete message history of a session at the time it was reset.

JSONL format: Each line is a JSON-serialized message object conforming to the Message type from @mariozechner/pi-ai. Messages have a role field (user, assistant, or toolResult) and role-specific content structures.

Example line (user message):

json
{"role":"user","content":"Hello","timestamp":1708300000000}

Example line (assistant message):

json
{"role":"assistant","content":[{"type":"text","text":"Hi there!"}],"timestamp":1708300001000}

Example line (tool result):

json
{"role":"toolResult","toolCallId":"call_abc","toolName":"Bash","content":[{"type":"text","text":"output"}],"isError":false,"timestamp":1708300002000}

R2 custom metadata stored on the object:

KeyTypeDescription
sessionKeystringSession routing key
sessionIdstringUUID of the archived session
agentIdstringAgent identifier
messageCountstring (numeric)Number of messages in the archive
archivedAtstring (epoch ms)Timestamp of archival
inputTokensstring (numeric)Cumulative input tokens at time of reset
outputTokensstring (numeric)Cumulative output tokens at time of reset
totalTokensstring (numeric)Cumulative total tokens at time of reset

agents/{agentId}/sessions/{sessionId}-part{timestamp}.jsonl.gz

PropertyValue
FormatJSONL, gzip-compressed
WrittenDuring context compaction
ReadNot read during normal operation

Partial archives created when the compaction engine removes older messages from an active session. The {timestamp} is Date.now() at the time of compaction.

R2 custom metadata:

KeyTypeDescription
sessionKeystringSession routing key
sessionIdstringUUID of the active session
agentIdstringAgent identifier
partNumberstring (numeric)Same as the timestamp suffix
messageCountstring (numeric)Number of messages in this partial archive
archivedAtstring (epoch ms)Timestamp of archival

Skills

agents/{agentId}/skills/{skillName}/SKILL.md

PropertyValue
FormatMarkdown with YAML frontmatter
ReadEvery LLM call (during workspace loading for listing); on-demand when agent loads a skill
Written byUser, agent, or deployment tooling

Agent-local skill definition. Takes precedence over a global skill with the same {skillName}.

skills/{skillName}/SKILL.md

PropertyValue
FormatMarkdown with YAML frontmatter
ReadEvery LLM call (during workspace loading for listing); on-demand when agent loads a skill
Written byDeployment tooling or admin

Global skill definition. Used when no agent-local skill with the same name exists.

Skill resolution order: Agent-local skills (agents/{agentId}/skills/) are listed first. Global skills (skills/) are listed second, skipping any name already present from the agent-local set.

See the Skills Frontmatter Reference for the SKILL.md file format.

Media

media/{sessionKey}/{uuid}.{ext}

PropertyValue
FormatBinary (original media encoding)
Max size25 MB
WrittenOn inbound message with media attachment
ReadDuring LLM call (hydrated from r2Key references in messages)
DeletedOn session reset

Media files (images, audio, video, documents) attached to inbound messages. Stored as raw binary with the original content type.

Key construction: media/{sessionKey}/{uuid}.{ext} where {uuid} is a crypto.randomUUID() and {ext} is derived from the MIME type.

MIME type to extension mapping:

MIME TypeExtension
image/jpegjpg
image/pngpng
image/gifgif
image/webpwebp
image/svg+xmlsvg
audio/oggogg
audio/opusopus
audio/mpegmp3
audio/mp3mp3
audio/mp4m4a
audio/m4am4a
audio/wavwav
audio/webmwebm
audio/flacflac
video/mp4mp4
video/webmwebm
video/quicktimemov
application/pdfpdf
application/msworddoc
application/vnd.openxmlformats-officedocument.wordprocessingml.documentdocx
(other)bin

R2 HTTP metadata:

KeyValue
contentTypeOriginal MIME type of the media

R2 custom metadata:

KeyTypeDescription
originalFilenamestringOriginal filename (may be empty)
uploadedAtstring (epoch ms)Upload timestamp
sessionKeystringSession routing key

Lifecycle: Media files are stored when an inbound message is processed. The base64 data is stripped from the in-memory message and replaced with an r2Key reference. During LLM calls, references are hydrated back to base64 via an in-memory LRU cache (50 MB budget). On session reset, all media under the media/{sessionKey}/ prefix is deleted.

Read/Write Summary

Path PatternRead ByWritten ByLifecycle
agents/{id}/SOUL.mdPrompt builderUser/agentPersistent
agents/{id}/IDENTITY.mdPrompt builderUser/agentPersistent
agents/{id}/USER.mdPrompt builderUser/agentPersistent
agents/{id}/AGENTS.mdPrompt builderUser/agentPersistent
agents/{id}/MEMORY.mdPrompt builder (main session)User/agentPersistent
agents/{id}/TOOLS.mdPrompt builderUser/agentPersistent
agents/{id}/HEARTBEAT.mdPrompt builderUser/agentPersistent
agents/{id}/BOOTSTRAP.mdPrompt builderUser/templateDeleted after commissioning
agents/{id}/memory/{date}.mdPrompt builder (today + yesterday)Compaction/reset/agentAccumulates daily
agents/{id}/sessions/{sid}.jsonl.gzTranscript retrievalReset handlerOne per reset
agents/{id}/sessions/{sid}-part{ts}.jsonl.gzNot read in normal operationCompaction engineOne per compaction
agents/{id}/skills/{name}/SKILL.mdSkill lister + agent on-demandUser/agent/deployPersistent
skills/{name}/SKILL.mdSkill lister + agent on-demandDeploy toolingPersistent
media/{sessionKey}/{uuid}.{ext}LLM call (hydration)Inbound media processorDeleted on session reset