Workspace files
Give an agent durable scratch files, final outputs, and approval-gated writes.
Use a workspace when an agent needs to create files without stuffing every intermediate result into the prompt.
This recipe gives the model:
/workspacefor notes and intermediate files./outputsfor final deliverables.- file tools through
use: [files]. - approval middleware for writes.
import { approvalMiddleware, prompt } from "@use-crux/core";
import { inMemoryStorage, storage } from "@use-crux/core/storage";
import { workspace, workspaceToolNames } from "@use-crux/core/workspace";
const files = workspace({
id: "case-files",
namespace: "case:demo",
storage: inMemoryStorage(),
tools: {
prefix: "case",
},
});
const names = workspaceToolNames({ prefix: "case" });
const writeApproval = approvalMiddleware({
id: "approve-file-writes",
match: [names.writeFile, names.editFile],
onRequest: async ({ input }) => {
console.log("File write requested:", input);
},
});
export const writer = prompt({
id: "case-writer",
use: [files],
middleware: [writeApproval],
system: `
You are a careful case writer.
Use /workspace for notes.
Write the final user-facing deliverable to /outputs.
Read existing files before editing them.
`,
});The injected tools are prefixed:
listCaseWorkspace
readCaseWorkspaceFile
writeCaseWorkspaceFile
editCaseWorkspaceFileDelete is not injected unless you explicitly enable it:
const files = workspace({
id: "case-files",
namespace: "case:demo",
storage: storage({ records, assets }),
tools: {
prefix: "case",
delete: true,
},
});Production Storage
For production, replace the in-memory stores with durable adapters.
import { convexRecordStore, convexAssetStore } from "@use-crux/convex";
import { storage } from "@use-crux/core/storage";
import { workspace } from "@use-crux/core/workspace";
const files = workspace({
id: "thread-files",
namespace: threadId,
storage: storage({
records: convexRecordStore({ component: components.crux, ctx }),
assets: convexAssetStore({ ctx }),
}),
});records keeps file metadata and small inline text. assets keeps binary and large files. See Storage and AssetStore for custom S3/R2/GCS-style asset stores.
For source material that already lives in a retriever, MCP server, project index, connected drive, or app document service, use a source-backed mount instead of copying everything into the workspace. Provider mounts are read-only by default and can opt into writes through custom source hooks. See Federated workspace sources.