Skip to content

Commit c783943

Browse files
authored
feat: introduce experimental Workspace support with filesystem, sandb… (#1025)
* feat: introduce experimental Workspace support with filesystem, sandbox execution * fix: docs * feat: add custom sandbox * fix: skills * fix: sp format * fix: docs * fix: code reviews * fix: build error * chore: fix codereviews * chore: fix code reviews * chore: fix code reviews * chore: fix code reviews * fix: code reviews * chore: fix code review * chore: fix codereview * chore: fix codereview * chore: fix code review * chore: fix codereview * chore: fix code reviews * chore: fix codereviews
1 parent 10e8411 commit c783943

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+13807
-1409
lines changed

.changeset/cruel-jobs-hunt.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
---
2+
"@voltagent/sandbox-daytona": patch
3+
"@voltagent/serverless-hono": patch
4+
"@voltagent/server-elysia": patch
5+
"@voltagent/sandbox-e2b": patch
6+
"@voltagent/server-core": patch
7+
"@voltagent/server-hono": patch
8+
"@voltagent/core": patch
9+
---
10+
11+
feat: introduce experimental Workspace support with filesystem, sandbox execution, search indexing, and skill discovery; add global workspace defaults and optional sandbox providers (E2B/Daytona). - #1008
12+
13+
Example:
14+
15+
```ts
16+
import { Agent, Workspace, LocalSandbox, NodeFilesystemBackend } from "@voltagent/core";
17+
18+
const workspace = new Workspace({
19+
id: "support-workspace",
20+
operationTimeoutMs: 30_000,
21+
filesystem: {
22+
backend: new NodeFilesystemBackend({
23+
rootDir: "./.workspace",
24+
}),
25+
},
26+
sandbox: new LocalSandbox({
27+
rootDir: "./.sandbox",
28+
isolation: { provider: "detect" },
29+
cleanupOnDestroy: true,
30+
}),
31+
search: {
32+
autoIndexPaths: ["/notes", "/tickets"],
33+
},
34+
skills: {
35+
rootPaths: ["/skills"],
36+
},
37+
});
38+
39+
const agent = new Agent({
40+
name: "support-agent",
41+
model,
42+
instructions: "Use workspace tools to review tickets and summarize findings.",
43+
workspace,
44+
workspaceToolkits: {
45+
filesystem: {
46+
toolPolicies: {
47+
tools: { write_file: { needsApproval: true } },
48+
},
49+
},
50+
},
51+
});
52+
53+
const { text } = await agent.generateText(
54+
[
55+
"Scan /tickets and /notes.",
56+
"Use workspace_search to find urgent issues from the last week.",
57+
"Summarize the top 3 risks and include file paths as citations.",
58+
].join("\n"),
59+
{ maxSteps: 40 }
60+
);
61+
```

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,8 @@ vitest.config.*.timestamp*
166166
# claude
167167
.claude
168168
skills
169+
!packages/core/src/workspace/skills
170+
!packages/core/src/workspace/skills/**
169171

170172
dev-debug.log
171173
node_modules/
@@ -179,3 +181,7 @@ node_modules/
179181

180182
# serena
181183
.serena
184+
185+
186+
# example skills
187+
!examples/with-workspace/workspace/skills

examples/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ Create a multi-agent research workflow where different AI agents collaborate to
8383
## All Examples
8484

8585
- [Base Starter](./base) — Minimal VoltAgent starter with a single agent, memory, and dev server.
86+
- [Workspace](./with-workspace) — Workspace filesystem, sandbox execution, search, and skills.
8687
- [Summarization](./with-summarization) — Agent summarization with a low trigger window for easy testing.
8788
- [Retries and Fallbacks](./with-retries-fallback) — Model fallback list with per-model retries and agent-level defaults.
8889
- [Middleware](./with-middleware) — Input/output middleware with retry feedback.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
OPENAI_API_KEY=your_openai_api_key_here

examples/with-workspace/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules
2+
dist
3+
.DS_Store

examples/with-workspace/README.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<div align="center">
2+
<a href="https://voltagent.dev/">
3+
<img width="1800" alt="435380213-b6253409-8741-462b-a346-834cd18565a9" src="https://github.com/user-attachments/assets/452a03e7-eeda-4394-9ee7-0ffbcf37245c" />
4+
</a>
5+
6+
<br/>
7+
<br/>
8+
9+
<div align="center">
10+
<a href="https://voltagent.dev">Home Page</a> |
11+
<a href="https://voltagent.dev/docs/">Documentation</a> |
12+
<a href="https://github.com/voltagent/voltagent/tree/main/examples">Examples</a> |
13+
<a href="https://s.voltagent.dev/discord">Discord</a> |
14+
<a href="https://voltagent.dev/blog/">Blog</a>
15+
</div>
16+
</div>
17+
18+
<br/>
19+
20+
<div align="center">
21+
<strong>VoltAgent is an open source TypeScript framework for building and orchestrating AI agents.</strong><br>
22+
Escape the limitations of no-code builders and the complexity of starting from scratch.
23+
<br />
24+
<br />
25+
</div>
26+
27+
<div align="center">
28+
29+
[![npm version](https://img.shields.io/npm/v/@voltagent/core.svg)](https://www.npmjs.com/package/@voltagent/core)
30+
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.0-4baaaa.svg)](CODE_OF_CONDUCT.md)
31+
[![Discord](https://img.shields.io/discord/1361559153780195478.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://s.voltagent.dev/discord)
32+
[![Twitter Follow](https://img.shields.io/twitter/follow/voltagent_dev?style=social)](https://twitter.com/voltagent_dev)
33+
34+
</div>
35+
36+
<br/>
37+
38+
<div align="center">
39+
<a href="https://voltagent.dev/">
40+
<img width="896" alt="VoltAgent Schema" src="https://github.com/user-attachments/assets/f0627868-6153-4f63-ba7f-bdfcc5dd603d" />
41+
</a>
42+
43+
</div>
44+
45+
## VoltAgent: Workspace Example
46+
47+
This example shows how to attach a Workspace to an agent, giving it a persistent filesystem, sandboxed command execution, file search (BM25 + vector), and reusable skills loaded from `SKILL.md` files.
48+
49+
## Try Example
50+
51+
```bash
52+
npm create voltagent-app@latest -- --example with-workspace
53+
```
54+
55+
## Highlights
56+
57+
- Workspace filesystem rooted at `./workspace`
58+
- Sandbox execution with `execute_command`
59+
- Workspace search via `workspace_index` and `workspace_search`
60+
- Skills loaded from `/skills` with `workspace_list_skills` and `workspace_read_skill`
61+
- Filesystem extras: `stat`, `mkdir`, and `list_tree`
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"name": "voltagent-example-with-workspace",
3+
"author": "",
4+
"dependencies": {
5+
"@ai-sdk/openai": "^3.0.0",
6+
"@voltagent/cli": "^0.1.21",
7+
"@voltagent/core": "^2.3.3",
8+
"@voltagent/libsql": "^2.1.0",
9+
"@voltagent/logger": "^2.0.2",
10+
"@voltagent/server-hono": "^2.0.4",
11+
"ai": "^6.0.0",
12+
"zod": "^3.25.76"
13+
},
14+
"devDependencies": {
15+
"@types/node": "^24.2.1",
16+
"tsx": "^4.19.3",
17+
"typescript": "^5.8.2"
18+
},
19+
"keywords": [
20+
"agent",
21+
"ai",
22+
"voltagent"
23+
],
24+
"license": "MIT",
25+
"private": true,
26+
"repository": {
27+
"type": "git",
28+
"url": "https://github.com/VoltAgent/voltagent.git",
29+
"directory": "examples/with-workspace"
30+
},
31+
"scripts": {
32+
"build": "tsc",
33+
"dev": "tsx watch --env-file=.env ./src",
34+
"start": "node dist/index.js",
35+
"volt": "volt"
36+
},
37+
"type": "module"
38+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import path from "node:path";
2+
import {
3+
Agent,
4+
InMemoryVectorAdapter,
5+
LocalSandbox,
6+
Memory,
7+
NodeFilesystemBackend,
8+
VoltAgent,
9+
Workspace,
10+
} from "@voltagent/core";
11+
import { LibSQLMemoryAdapter, LibSQLVectorAdapter } from "@voltagent/libsql";
12+
import { createPinoLogger } from "@voltagent/logger";
13+
import { honoServer } from "@voltagent/server-hono";
14+
15+
// Create logger
16+
const logger = createPinoLogger({
17+
name: "with-workspace",
18+
level: "info",
19+
});
20+
21+
// Create Memory instance with vector support for semantic search and working memory
22+
const memory = new Memory({
23+
storage: new LibSQLMemoryAdapter(),
24+
embedding: "openai/text-embedding-3-small",
25+
vector: new LibSQLVectorAdapter(),
26+
generateTitle: true,
27+
});
28+
29+
const workspaceRoot = path.resolve(process.cwd(), "workspace");
30+
31+
const workspace = new Workspace({
32+
id: "workspace-example",
33+
name: "Workspace Example",
34+
filesystem: {
35+
backend: new NodeFilesystemBackend({
36+
rootDir: workspaceRoot,
37+
virtualMode: true,
38+
}),
39+
},
40+
sandbox: new LocalSandbox({
41+
rootDir: workspaceRoot,
42+
}),
43+
search: {
44+
autoIndexPaths: [{ path: "/", glob: "**/*.{md,txt,csv}" }],
45+
embedding: "openai/text-embedding-3-small",
46+
vector: new InMemoryVectorAdapter(),
47+
},
48+
skills: {
49+
rootPaths: ["/skills"],
50+
},
51+
});
52+
53+
const skillsHook = workspace.createSkillsPromptHook({
54+
includeAvailable: true,
55+
includeActivated: true,
56+
});
57+
58+
const agent = new Agent({
59+
name: "Workspace Agent",
60+
instructions: [
61+
"You are a helpful assistant.",
62+
"Use the workspace filesystem for notes under /notes and data under /data.",
63+
"Use workspace_search to find relevant files before answering.",
64+
"Skills live under /skills; activate them when a task matches the description.",
65+
].join(" "),
66+
model: "openai/gpt-4o-mini",
67+
memory,
68+
workspace,
69+
hooks: skillsHook,
70+
workspaceToolkits: {
71+
filesystem: {
72+
toolPolicies: {
73+
tools: { write_file: { needsApproval: true } },
74+
},
75+
},
76+
},
77+
});
78+
79+
new VoltAgent({
80+
agents: { agent },
81+
server: honoServer(),
82+
logger,
83+
});
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ES2022",
4+
"module": "NodeNext",
5+
"moduleResolution": "NodeNext",
6+
"esModuleInterop": true,
7+
"forceConsistentCasingInFileNames": true,
8+
"strict": true,
9+
"outDir": "dist",
10+
"skipLibCheck": true
11+
},
12+
"include": ["src"],
13+
"exclude": ["node_modules", "dist"]
14+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
customer_id,segment,mrr,region,plan
2+
C-001,mid-market,1200,NA,Pro
3+
C-002,enterprise,9000,EU,Enterprise
4+
C-003,smb,300,NA,Starter
5+
C-004,mid-market,1800,APAC,Pro
6+
C-005,enterprise,15000,NA,Enterprise

0 commit comments

Comments
 (0)