Actana

Files

The workspace file store. Upload, create, and share files across agents.

ScreenshotFiles module — gallery view with mixed types.

Files is the workspace file store. Anything an agent reads or writes — uploaded documents, generated reports, sandbox-produced assets — lives here. One row per file in workspace_files; the bytes live in object storage and are served through /api/files/serve/... with workspace-scoped permissions.

What a file row stores

The workspace_files table:

ColumnNotes
keyObject-storage key. Globally unique among non-deleted rows.
originalNameThe display name. Unique per workspace among context = 'workspace' rows.
contentTypeMime type (used by the file picker + previews).
sizeBytes.
contextThe bucket the file belongs to. See contexts below.
chatIdSet when the file was uploaded into an Assistant chat.
userId, workspaceIdOwner + scope.
deletedAtSoft-delete timestamp.
uploadedAtInsert time.

Contexts

Each file is tagged with a context so different surfaces don't trample each other. The valid contexts:

ContextSource
workspaceThe Files module — files explicitly placed in the workspace store.
chatFiles attached to an Assistant chat (also tracked separately in assistantChatBagFiles).
copilotLegacy. The schema enum still includes the old copilot/mothership strings for backward compatibility but new uploads go through chat. See the Assistant page for naming history.
knowledge-baseFiles indexed by the (currently hidden) Knowledge Base module.
executionFiles produced by a workflow run — workflow-bag and persistent-files writebacks.
profile-picturesUser and workspace avatars.
generalCatch-all for files that don't belong elsewhere.

The context is set at upload time by the route that owns the upload — see Files › Uploads.

Lifecycle

Files are soft-deleted. deletedAt is set rather than the row being removed; storage objects can be reaped by a background job after a grace period. Two uniqueness rules are enforced only against active (non-deleted) rows:

  • One active file per key globally.
  • One active originalName per (workspaceId, context = 'workspace'). Re-uploading a name that already exists fails until the existing row is soft-deleted or renamed.

How blocks reach files

Workflow blocks pass files around as UserFile objects — a small JSON shape with name, key, context, optional path/url, plus metadata. The File block, Save File block, and any integration block that handles uploads accepts this shape. See Files › References.

Tables hold structured data; Files hold unstructured blobs. If you need to filter or query the contents, store metadata in a Table and reference the file via its key.

Source

  • packages/db/schema.tsworkspace_files
  • apps/actana/lib/uploads/utils/file-utils.tsUserFile shape, inferContextFromKey
  • apps/actana/lib/uploads/utils/file-utils.server.tsdownloadFileFromStorage
  • apps/actana/app/api/files/ — upload, serve, presign routes

On this page