Artifacts are any files produced during a research session — plots, datasets, notebooks, reports, XML exports, SVG figures, HTML summaries, CSV tables, or any other output the agent or notebook kernel writes. Open Science stores them durably on disk, organized by project, session, and message, so that results are always reproducible and every output can be traced back to the turn that produced it.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/aipoch/open-science/llms.txt
Use this file to discover all available pages before exploring further.
The ArtifactFile Shape
Every artifact is described by an ArtifactFile record (defined in src/shared/artifacts.ts). This type crosses the IPC boundary and is used by both the runtime and the renderer.
| Field | Type | Description |
|---|---|---|
id | string | Unique artifact ID, composed as sessionId:ownerId:filename. |
projectName | string | The logical project bucket that owns this artifact’s storage subtree. |
sessionId | string | The session that produced this artifact. |
messageId | string? | The message ID assigned after finalization; absent while the run is still pending. |
runId | string? | The run ID assigned at prompt activation; present for pending artifacts. |
name | string | The display filename (e.g. histogram.png). |
path | string | Absolute path on disk, used by the main process for open/preview operations. |
fileUrl | string | file:// URL generated by pathToFileURL(), used by the renderer to load the file. |
mimeType | string? | MIME type if supplied by the agent or inferred; absent for formats without registered types. |
size | number | File size in bytes, from fs.stat. |
mtimeMs | number | Last-modified time as epoch milliseconds, from fs.stat. |
Artifact Lifecycle
Agent calls write_artifact_file
During a prompt turn, the agent calls the The write is atomic — content is written to a
write_artifact_file tool exposed by the open-science-artifacts MCP server. The call specifies a filename, an optional MIME type, and either an inline source or a local file path. The MCP server validates the filename (no path separators, no control characters, no .. traversal) and delegates to ArtifactRepository.writePendingFile(), which writes the content to:.tmp file first, then renamed to the final path.activateArtifactRun() writes the handoff file
Before This file contains
sendPrompt() calls the agent, activateArtifactRun() writes a small JSON file at:{ "runId": "artifact-run-<timestamp>-<seq>" }. The artifact MCP server reads this file to discover the active run ID without the agent ever supplying it directly, preventing model-supplied IDs from influencing storage paths.emitArtifactRunEvent() claims pending files
When the agent’s response stream emits a
stop signal, emitArtifactRunEvent() calls ArtifactRepository.listPendingRunFiles() to discover all files written during the run. If any files were written, the ArtifactRunRegistry registers a claim and returns an opaque artifactClaimId. The runtime then emits an artifact event carrying the claim ID and the ArtifactFile list so the renderer can attach them visually to the finishing message — before the stop event fires.finalizeRun() commits artifacts to a message
After the renderer assigns a The
messageId to the finished assistant message, it calls artifacts:finalizeRun via IPC with the claimId and messageId. The main process resolves the claim through ArtifactRunRegistry.resolve(), then calls ArtifactRepository.finalizeRunArtifacts() to move every file from the pending directory to:finalizeRunArtifacts() method is idempotent — a replayed finalization recovers metadata from already-moved files and returns the correct list without duplicating writes.Write Sources
The agent passes one of twoArtifactWriteSource variants to write_artifact_file:
localPath writes, the ArtifactRepository resolves the path against a set of allowed import roots configured at session creation — the session working directory and the notebook session root. This prevents the agent from importing arbitrary files from outside its managed workspace.
Storage Root
All app-managed data — the SQLite database, session JSON files, artifact files, and notebook run history — lives under a single root directory resolved bysrc/main/storage-root.ts:
| Platform | Production path | Development path |
|---|---|---|
| macOS | ~/.open-science | ~/.open-science-project |
| Windows | %USERPROFILE%\.open-science | %USERPROFILE%\.open-science-project |
| Linux | ~/.open-science | ~/.open-science-project |
.open-science-project directory so that running npm run dev never touches a production installation’s data. The dev/prod branch is determined by app.isPackaged at runtime.
Artifacts specifically live under:
In-App Preview
The preview workbench renders artifact files natively without requiring the researcher to open them in an external tool. Supported formats include CSV, FASTA, HTML, image formats (PNG, JPG, SVG, and others), JSON, Markdown, and plain text, plus a read-only notebook view that shows code cells and their execution output side by side. Renderer-initiated preview reads go throughartifacts:readPreview IPC, which calls ArtifactRepository.readManagedFilePreview(). This method validates that the requested path is genuinely inside the artifact storage root (rejecting path traversal and symlink escapes) before reading the file, and returns a bounded text preview with a truncated flag for large files.